From 0e0bea01393955bb8791c221ee2ad0097bf8c37d Mon Sep 17 00:00:00 2001 From: Lauri Ojansivu Date: Wed, 23 Feb 2022 09:38:28 +0200 Subject: [PATCH] Merged meteor-files changes PR and removed wekan-cfs. --- packages/wekan-cfs-access-point/.travis.yml | 5 - packages/wekan-cfs-access-point/CHANGELOG.md | 288 ------- packages/wekan-cfs-access-point/LICENSE.md | 20 - packages/wekan-cfs-access-point/README.md | 32 - .../access-point-client.js | 58 -- .../access-point-common.js | 199 ----- .../access-point-handlers.js | 307 ------- .../access-point-server.js | 362 --------- packages/wekan-cfs-access-point/api.md | 271 ------- .../wekan-cfs-access-point/internal.api.md | 332 -------- packages/wekan-cfs-access-point/package.js | 65 -- .../tests/client-tests.js | 125 --- .../tests/server-tests.js | 68 -- packages/wekan-cfs-base-package/.travis.yml | 5 - packages/wekan-cfs-base-package/LICENSE.md | 20 - packages/wekan-cfs-base-package/README.md | 11 - packages/wekan-cfs-base-package/api.md | 213 ----- .../wekan-cfs-base-package/base-client.js | 51 -- .../wekan-cfs-base-package/base-common.js | 317 -------- .../wekan-cfs-base-package/base-server.js | 95 --- .../wekan-cfs-base-package/internal.api.md | 293 ------- packages/wekan-cfs-base-package/package.js | 37 - .../wekan-cfs-base-package/polyfill.base64.js | 179 ---- .../tests/common-tests.js | 161 ---- .../wekan-cfs-collection-filters/.travis.yml | 5 - .../wekan-cfs-collection-filters/LICENSE.md | 20 - .../wekan-cfs-collection-filters/README.md | 8 - packages/wekan-cfs-collection-filters/api.md | 44 - .../wekan-cfs-collection-filters/filters.js | 191 ----- .../internal.api.md | 72 -- .../wekan-cfs-collection-filters/package.js | 29 - .../tests/client-tests.js | 27 - .../tests/server-tests.js | 27 - packages/wekan-cfs-collection/.travis.yml | 5 - packages/wekan-cfs-collection/CHANGELOG.md | 727 ----------------- packages/wekan-cfs-collection/LICENSE.md | 20 - packages/wekan-cfs-collection/README.md | 8 - packages/wekan-cfs-collection/api.common.js | 260 ------ packages/wekan-cfs-collection/api.md | 180 ----- packages/wekan-cfs-collection/common.js | 171 ---- packages/wekan-cfs-collection/internal.api.md | 390 --------- packages/wekan-cfs-collection/package.js | 43 - .../tests/client-tests.js | 33 - .../tests/server-tests.js | 96 --- packages/wekan-cfs-data-man/.travis.yml | 5 - packages/wekan-cfs-data-man/LICENSE.md | 20 - packages/wekan-cfs-data-man/README.md | 8 - packages/wekan-cfs-data-man/api.md | 309 ------- packages/wekan-cfs-data-man/client/Blob.js | 166 ---- .../wekan-cfs-data-man/client/data-man-api.js | 302 ------- packages/wekan-cfs-data-man/internal.api.md | 674 --------------- packages/wekan-cfs-data-man/package.js | 48 -- .../wekan-cfs-data-man/server/data-man-api.js | 176 ---- .../server/data-man-buffer.js | 82 -- .../server/data-man-datauri.js | 14 - .../server/data-man-filepath.js | 108 --- .../server/data-man-readstream.js | 80 -- .../wekan-cfs-data-man/server/data-man-url.js | 133 --- .../wekan-cfs-data-man/tests/client-tests.js | 296 ------- packages/wekan-cfs-data-man/tests/common.js | 38 - .../wekan-cfs-data-man/tests/server-tests.js | 366 --------- packages/wekan-cfs-file/.travis.yml | 5 - packages/wekan-cfs-file/CHANGELOG.md | 283 ------- packages/wekan-cfs-file/LICENSE.md | 20 - packages/wekan-cfs-file/README.md | 8 - packages/wekan-cfs-file/api.md | 588 -------------- packages/wekan-cfs-file/fsFile-common.js | 765 ------------------ packages/wekan-cfs-file/fsFile-server.js | 361 --------- packages/wekan-cfs-file/internal.api.md | 749 ----------------- packages/wekan-cfs-file/package.js | 55 -- packages/wekan-cfs-file/tests/file-tests.js | 436 ---------- packages/wekan-cfs-filesystem/.travis.yml | 5 - packages/wekan-cfs-filesystem/LICENSE.md | 20 - packages/wekan-cfs-filesystem/README.md | 41 - .../wekan-cfs-filesystem/filesystem.client.js | 10 - .../wekan-cfs-filesystem/filesystem.server.js | 157 ---- packages/wekan-cfs-filesystem/package.js | 24 - packages/wekan-cfs-filesystem/tests.js | 9 - .../tests/client-tests.js | 44 - .../tests/server-tests.js | 49 -- packages/wekan-cfs-gridfs/.travis.yml | 5 - packages/wekan-cfs-gridfs/LICENSE.md | 20 - packages/wekan-cfs-gridfs/README.md | 48 -- packages/wekan-cfs-gridfs/api.md | 69 -- packages/wekan-cfs-gridfs/gridfs.client.js | 21 - packages/wekan-cfs-gridfs/gridfs.server.js | 176 ---- packages/wekan-cfs-gridfs/internal.api.md | 75 -- packages/wekan-cfs-gridfs/package.js | 24 - .../wekan-cfs-gridfs/tests/client-tests.js | 44 - .../wekan-cfs-gridfs/tests/server-tests.js | 49 -- packages/wekan-cfs-http-methods/.editorconfig | 18 - packages/wekan-cfs-http-methods/.gitignore | 2 - packages/wekan-cfs-http-methods/.jshintrc | 140 ---- packages/wekan-cfs-http-methods/.travis.yml | 5 - packages/wekan-cfs-http-methods/CHANGELOG.md | 152 ---- packages/wekan-cfs-http-methods/LICENSE.md | 20 - packages/wekan-cfs-http-methods/README.md | 215 ----- .../http.methods.client.api.js | 6 - .../http.methods.server.api.js | 644 --------------- .../http.methods.tests.js | 117 --- packages/wekan-cfs-http-methods/package.js | 31 - packages/wekan-cfs-http-publish/.editorconfig | 18 - packages/wekan-cfs-http-publish/.gitignore | 4 - packages/wekan-cfs-http-publish/.jshintrc | 97 --- packages/wekan-cfs-http-publish/.travis.yml | 5 - packages/wekan-cfs-http-publish/LICENSE.md | 20 - packages/wekan-cfs-http-publish/README.md | 129 --- packages/wekan-cfs-http-publish/api.md | 153 ---- .../http.publish.client.api.js | 12 - .../http.publish.server.api.js | 466 ----------- .../http.publish.tests.client.js | 175 ---- .../http.publish.tests.server.js | 149 ---- .../wekan-cfs-http-publish/internal.api.md | 330 -------- packages/wekan-cfs-http-publish/package.js | 34 - .../packages/.gitignore | 2 - packages/wekan-cfs-power-queue/.editorconfig | 18 - packages/wekan-cfs-power-queue/.gitignore | 3 - packages/wekan-cfs-power-queue/.jshintrc | 114 --- packages/wekan-cfs-power-queue/.travis.yml | 5 - packages/wekan-cfs-power-queue/LICENSE.md | 20 - packages/wekan-cfs-power-queue/README.md | 136 ---- packages/wekan-cfs-power-queue/api.md | 420 ---------- .../wekan-cfs-power-queue/internal.api.md | 535 ------------ packages/wekan-cfs-power-queue/package.js | 27 - packages/wekan-cfs-power-queue/power-queue.js | 727 ----------------- .../spinal-queue.spec.md | 151 ---- packages/wekan-cfs-power-queue/tests.js | 198 ----- .../wekan-cfs-reactive-list/.editorconfig | 18 - packages/wekan-cfs-reactive-list/.gitignore | 2 - packages/wekan-cfs-reactive-list/.jshintrc | 115 --- packages/wekan-cfs-reactive-list/.travis.yml | 5 - packages/wekan-cfs-reactive-list/LICENSE.md | 20 - packages/wekan-cfs-reactive-list/README.md | 82 -- packages/wekan-cfs-reactive-list/api.md | 195 ----- .../wekan-cfs-reactive-list/internal.api.md | 203 ----- packages/wekan-cfs-reactive-list/package.js | 23 - .../wekan-cfs-reactive-list/reactive-list.js | 313 ------- packages/wekan-cfs-reactive-list/tests.js | 104 --- .../wekan-cfs-reactive-property/.editorconfig | 18 - .../wekan-cfs-reactive-property/.gitignore | 2 - .../wekan-cfs-reactive-property/.jshintrc | 97 --- .../wekan-cfs-reactive-property/LICENSE.md | 20 - .../wekan-cfs-reactive-property/README.md | 32 - packages/wekan-cfs-reactive-property/api.md | 152 ---- .../internal.api.md | 167 ---- .../wekan-cfs-reactive-property/package.js | 23 - .../reactive-property.js | 137 ---- packages/wekan-cfs-reactive-property/tests.js | 30 - .../wekan-cfs-standard-packages/.travis.yml | 5 - .../wekan-cfs-standard-packages/ADVANCED.md | 265 ------ .../wekan-cfs-standard-packages/CHANGELOG.md | 721 ----------------- .../wekan-cfs-standard-packages/LICENSE.md | 20 - .../wekan-cfs-standard-packages/README.md | 16 - .../wekan-cfs-standard-packages/package.js | 42 - .../tests/client-tests.js | 25 - .../tests/server-tests.js | 25 - .../wekan-cfs-storage-adapter/.travis.yml | 5 - packages/wekan-cfs-storage-adapter/LICENSE.md | 20 - packages/wekan-cfs-storage-adapter/README.md | 7 - packages/wekan-cfs-storage-adapter/api.md | 0 .../wekan-cfs-storage-adapter/internal.api.md | 101 --- packages/wekan-cfs-storage-adapter/package.js | 50 -- .../storageAdapter.client.js | 37 - .../storageAdapter.server.js | 269 ------ .../tests/client-tests.js | 44 - .../tests/server-tests.js | 49 -- .../transform.server.js | 119 --- packages/wekan-cfs-temp-store/.travis.yml | 5 - packages/wekan-cfs-temp-store/CHANGELOG.md | 169 ---- packages/wekan-cfs-temp-store/LICENSE.md | 20 - packages/wekan-cfs-temp-store/README.md | 24 - packages/wekan-cfs-temp-store/api.md | 112 --- packages/wekan-cfs-temp-store/internal.api.md | 225 ------ packages/wekan-cfs-temp-store/package.js | 32 - packages/wekan-cfs-temp-store/tempStore.js | 395 --------- .../tests/server-tests.js | 39 - packages/wekan-cfs-upload-http/.travis.yml | 5 - packages/wekan-cfs-upload-http/LICENSE.md | 20 - packages/wekan-cfs-upload-http/README.md | 8 - packages/wekan-cfs-upload-http/api.md | 24 - .../wekan-cfs-upload-http/internal.api.md | 160 ---- packages/wekan-cfs-upload-http/package.js | 37 - .../tests/client-tests.js | 27 - .../tests/server-tests.js | 27 - .../upload-http-client.js | 260 ------ .../upload-http-common.js | 1 - packages/wekan-cfs-worker/.travis.yml | 5 - packages/wekan-cfs-worker/CHANGELOG.md | 123 --- packages/wekan-cfs-worker/LICENSE.md | 20 - packages/wekan-cfs-worker/README.md | 8 - packages/wekan-cfs-worker/api.md | 38 - packages/wekan-cfs-worker/fileWorker.js | 185 ----- packages/wekan-cfs-worker/internal.api.md | 143 ---- packages/wekan-cfs-worker/package.js | 34 - .../wekan-cfs-worker/tests/client-tests.js | 44 - .../wekan-cfs-worker/tests/server-tests.js | 49 -- 196 files changed, 23970 deletions(-) delete mode 100644 packages/wekan-cfs-access-point/.travis.yml delete mode 100644 packages/wekan-cfs-access-point/CHANGELOG.md delete mode 100644 packages/wekan-cfs-access-point/LICENSE.md delete mode 100644 packages/wekan-cfs-access-point/README.md delete mode 100644 packages/wekan-cfs-access-point/access-point-client.js delete mode 100644 packages/wekan-cfs-access-point/access-point-common.js delete mode 100644 packages/wekan-cfs-access-point/access-point-handlers.js delete mode 100644 packages/wekan-cfs-access-point/access-point-server.js delete mode 100644 packages/wekan-cfs-access-point/api.md delete mode 100644 packages/wekan-cfs-access-point/internal.api.md delete mode 100644 packages/wekan-cfs-access-point/package.js delete mode 100644 packages/wekan-cfs-access-point/tests/client-tests.js delete mode 100644 packages/wekan-cfs-access-point/tests/server-tests.js delete mode 100644 packages/wekan-cfs-base-package/.travis.yml delete mode 100644 packages/wekan-cfs-base-package/LICENSE.md delete mode 100644 packages/wekan-cfs-base-package/README.md delete mode 100644 packages/wekan-cfs-base-package/api.md delete mode 100644 packages/wekan-cfs-base-package/base-client.js delete mode 100644 packages/wekan-cfs-base-package/base-common.js delete mode 100644 packages/wekan-cfs-base-package/base-server.js delete mode 100644 packages/wekan-cfs-base-package/internal.api.md delete mode 100644 packages/wekan-cfs-base-package/package.js delete mode 100644 packages/wekan-cfs-base-package/polyfill.base64.js delete mode 100644 packages/wekan-cfs-base-package/tests/common-tests.js delete mode 100644 packages/wekan-cfs-collection-filters/.travis.yml delete mode 100644 packages/wekan-cfs-collection-filters/LICENSE.md delete mode 100644 packages/wekan-cfs-collection-filters/README.md delete mode 100644 packages/wekan-cfs-collection-filters/api.md delete mode 100644 packages/wekan-cfs-collection-filters/filters.js delete mode 100644 packages/wekan-cfs-collection-filters/internal.api.md delete mode 100644 packages/wekan-cfs-collection-filters/package.js delete mode 100644 packages/wekan-cfs-collection-filters/tests/client-tests.js delete mode 100644 packages/wekan-cfs-collection-filters/tests/server-tests.js delete mode 100644 packages/wekan-cfs-collection/.travis.yml delete mode 100644 packages/wekan-cfs-collection/CHANGELOG.md delete mode 100644 packages/wekan-cfs-collection/LICENSE.md delete mode 100644 packages/wekan-cfs-collection/README.md delete mode 100644 packages/wekan-cfs-collection/api.common.js delete mode 100644 packages/wekan-cfs-collection/api.md delete mode 100644 packages/wekan-cfs-collection/common.js delete mode 100644 packages/wekan-cfs-collection/internal.api.md delete mode 100644 packages/wekan-cfs-collection/package.js delete mode 100644 packages/wekan-cfs-collection/tests/client-tests.js delete mode 100644 packages/wekan-cfs-collection/tests/server-tests.js delete mode 100644 packages/wekan-cfs-data-man/.travis.yml delete mode 100644 packages/wekan-cfs-data-man/LICENSE.md delete mode 100644 packages/wekan-cfs-data-man/README.md delete mode 100644 packages/wekan-cfs-data-man/api.md delete mode 100644 packages/wekan-cfs-data-man/client/Blob.js delete mode 100644 packages/wekan-cfs-data-man/client/data-man-api.js delete mode 100644 packages/wekan-cfs-data-man/internal.api.md delete mode 100644 packages/wekan-cfs-data-man/package.js delete mode 100644 packages/wekan-cfs-data-man/server/data-man-api.js delete mode 100644 packages/wekan-cfs-data-man/server/data-man-buffer.js delete mode 100644 packages/wekan-cfs-data-man/server/data-man-datauri.js delete mode 100644 packages/wekan-cfs-data-man/server/data-man-filepath.js delete mode 100644 packages/wekan-cfs-data-man/server/data-man-readstream.js delete mode 100644 packages/wekan-cfs-data-man/server/data-man-url.js delete mode 100644 packages/wekan-cfs-data-man/tests/client-tests.js delete mode 100644 packages/wekan-cfs-data-man/tests/common.js delete mode 100644 packages/wekan-cfs-data-man/tests/server-tests.js delete mode 100644 packages/wekan-cfs-file/.travis.yml delete mode 100644 packages/wekan-cfs-file/CHANGELOG.md delete mode 100644 packages/wekan-cfs-file/LICENSE.md delete mode 100644 packages/wekan-cfs-file/README.md delete mode 100644 packages/wekan-cfs-file/api.md delete mode 100644 packages/wekan-cfs-file/fsFile-common.js delete mode 100644 packages/wekan-cfs-file/fsFile-server.js delete mode 100644 packages/wekan-cfs-file/internal.api.md delete mode 100644 packages/wekan-cfs-file/package.js delete mode 100644 packages/wekan-cfs-file/tests/file-tests.js delete mode 100644 packages/wekan-cfs-filesystem/.travis.yml delete mode 100644 packages/wekan-cfs-filesystem/LICENSE.md delete mode 100644 packages/wekan-cfs-filesystem/README.md delete mode 100644 packages/wekan-cfs-filesystem/filesystem.client.js delete mode 100644 packages/wekan-cfs-filesystem/filesystem.server.js delete mode 100644 packages/wekan-cfs-filesystem/package.js delete mode 100644 packages/wekan-cfs-filesystem/tests.js delete mode 100644 packages/wekan-cfs-filesystem/tests/client-tests.js delete mode 100644 packages/wekan-cfs-filesystem/tests/server-tests.js delete mode 100644 packages/wekan-cfs-gridfs/.travis.yml delete mode 100644 packages/wekan-cfs-gridfs/LICENSE.md delete mode 100644 packages/wekan-cfs-gridfs/README.md delete mode 100644 packages/wekan-cfs-gridfs/api.md delete mode 100644 packages/wekan-cfs-gridfs/gridfs.client.js delete mode 100644 packages/wekan-cfs-gridfs/gridfs.server.js delete mode 100644 packages/wekan-cfs-gridfs/internal.api.md delete mode 100755 packages/wekan-cfs-gridfs/package.js delete mode 100644 packages/wekan-cfs-gridfs/tests/client-tests.js delete mode 100644 packages/wekan-cfs-gridfs/tests/server-tests.js delete mode 100644 packages/wekan-cfs-http-methods/.editorconfig delete mode 100644 packages/wekan-cfs-http-methods/.gitignore delete mode 100644 packages/wekan-cfs-http-methods/.jshintrc delete mode 100644 packages/wekan-cfs-http-methods/.travis.yml delete mode 100644 packages/wekan-cfs-http-methods/CHANGELOG.md delete mode 100644 packages/wekan-cfs-http-methods/LICENSE.md delete mode 100644 packages/wekan-cfs-http-methods/README.md delete mode 100644 packages/wekan-cfs-http-methods/http.methods.client.api.js delete mode 100644 packages/wekan-cfs-http-methods/http.methods.server.api.js delete mode 100644 packages/wekan-cfs-http-methods/http.methods.tests.js delete mode 100644 packages/wekan-cfs-http-methods/package.js delete mode 100644 packages/wekan-cfs-http-publish/.editorconfig delete mode 100644 packages/wekan-cfs-http-publish/.gitignore delete mode 100644 packages/wekan-cfs-http-publish/.jshintrc delete mode 100644 packages/wekan-cfs-http-publish/.travis.yml delete mode 100644 packages/wekan-cfs-http-publish/LICENSE.md delete mode 100644 packages/wekan-cfs-http-publish/README.md delete mode 100644 packages/wekan-cfs-http-publish/api.md delete mode 100644 packages/wekan-cfs-http-publish/http.publish.client.api.js delete mode 100644 packages/wekan-cfs-http-publish/http.publish.server.api.js delete mode 100644 packages/wekan-cfs-http-publish/http.publish.tests.client.js delete mode 100644 packages/wekan-cfs-http-publish/http.publish.tests.server.js delete mode 100644 packages/wekan-cfs-http-publish/internal.api.md delete mode 100644 packages/wekan-cfs-http-publish/package.js delete mode 100644 packages/wekan-cfs-http-publish/packages/.gitignore delete mode 100644 packages/wekan-cfs-power-queue/.editorconfig delete mode 100644 packages/wekan-cfs-power-queue/.gitignore delete mode 100644 packages/wekan-cfs-power-queue/.jshintrc delete mode 100644 packages/wekan-cfs-power-queue/.travis.yml delete mode 100644 packages/wekan-cfs-power-queue/LICENSE.md delete mode 100644 packages/wekan-cfs-power-queue/README.md delete mode 100644 packages/wekan-cfs-power-queue/api.md delete mode 100644 packages/wekan-cfs-power-queue/internal.api.md delete mode 100644 packages/wekan-cfs-power-queue/package.js delete mode 100644 packages/wekan-cfs-power-queue/power-queue.js delete mode 100644 packages/wekan-cfs-power-queue/spinal-queue.spec.md delete mode 100644 packages/wekan-cfs-power-queue/tests.js delete mode 100644 packages/wekan-cfs-reactive-list/.editorconfig delete mode 100644 packages/wekan-cfs-reactive-list/.gitignore delete mode 100644 packages/wekan-cfs-reactive-list/.jshintrc delete mode 100644 packages/wekan-cfs-reactive-list/.travis.yml delete mode 100644 packages/wekan-cfs-reactive-list/LICENSE.md delete mode 100644 packages/wekan-cfs-reactive-list/README.md delete mode 100644 packages/wekan-cfs-reactive-list/api.md delete mode 100644 packages/wekan-cfs-reactive-list/internal.api.md delete mode 100644 packages/wekan-cfs-reactive-list/package.js delete mode 100644 packages/wekan-cfs-reactive-list/reactive-list.js delete mode 100644 packages/wekan-cfs-reactive-list/tests.js delete mode 100644 packages/wekan-cfs-reactive-property/.editorconfig delete mode 100644 packages/wekan-cfs-reactive-property/.gitignore delete mode 100644 packages/wekan-cfs-reactive-property/.jshintrc delete mode 100644 packages/wekan-cfs-reactive-property/LICENSE.md delete mode 100644 packages/wekan-cfs-reactive-property/README.md delete mode 100644 packages/wekan-cfs-reactive-property/api.md delete mode 100644 packages/wekan-cfs-reactive-property/internal.api.md delete mode 100644 packages/wekan-cfs-reactive-property/package.js delete mode 100644 packages/wekan-cfs-reactive-property/reactive-property.js delete mode 100644 packages/wekan-cfs-reactive-property/tests.js delete mode 100644 packages/wekan-cfs-standard-packages/.travis.yml delete mode 100644 packages/wekan-cfs-standard-packages/ADVANCED.md delete mode 100644 packages/wekan-cfs-standard-packages/CHANGELOG.md delete mode 100644 packages/wekan-cfs-standard-packages/LICENSE.md delete mode 100644 packages/wekan-cfs-standard-packages/README.md delete mode 100644 packages/wekan-cfs-standard-packages/package.js delete mode 100644 packages/wekan-cfs-standard-packages/tests/client-tests.js delete mode 100644 packages/wekan-cfs-standard-packages/tests/server-tests.js delete mode 100644 packages/wekan-cfs-storage-adapter/.travis.yml delete mode 100644 packages/wekan-cfs-storage-adapter/LICENSE.md delete mode 100644 packages/wekan-cfs-storage-adapter/README.md delete mode 100644 packages/wekan-cfs-storage-adapter/api.md delete mode 100644 packages/wekan-cfs-storage-adapter/internal.api.md delete mode 100644 packages/wekan-cfs-storage-adapter/package.js delete mode 100644 packages/wekan-cfs-storage-adapter/storageAdapter.client.js delete mode 100644 packages/wekan-cfs-storage-adapter/storageAdapter.server.js delete mode 100644 packages/wekan-cfs-storage-adapter/tests/client-tests.js delete mode 100644 packages/wekan-cfs-storage-adapter/tests/server-tests.js delete mode 100644 packages/wekan-cfs-storage-adapter/transform.server.js delete mode 100644 packages/wekan-cfs-temp-store/.travis.yml delete mode 100644 packages/wekan-cfs-temp-store/CHANGELOG.md delete mode 100644 packages/wekan-cfs-temp-store/LICENSE.md delete mode 100644 packages/wekan-cfs-temp-store/README.md delete mode 100644 packages/wekan-cfs-temp-store/api.md delete mode 100644 packages/wekan-cfs-temp-store/internal.api.md delete mode 100644 packages/wekan-cfs-temp-store/package.js delete mode 100644 packages/wekan-cfs-temp-store/tempStore.js delete mode 100644 packages/wekan-cfs-temp-store/tests/server-tests.js delete mode 100644 packages/wekan-cfs-upload-http/.travis.yml delete mode 100644 packages/wekan-cfs-upload-http/LICENSE.md delete mode 100644 packages/wekan-cfs-upload-http/README.md delete mode 100644 packages/wekan-cfs-upload-http/api.md delete mode 100644 packages/wekan-cfs-upload-http/internal.api.md delete mode 100644 packages/wekan-cfs-upload-http/package.js delete mode 100644 packages/wekan-cfs-upload-http/tests/client-tests.js delete mode 100644 packages/wekan-cfs-upload-http/tests/server-tests.js delete mode 100644 packages/wekan-cfs-upload-http/upload-http-client.js delete mode 100644 packages/wekan-cfs-upload-http/upload-http-common.js delete mode 100644 packages/wekan-cfs-worker/.travis.yml delete mode 100644 packages/wekan-cfs-worker/CHANGELOG.md delete mode 100644 packages/wekan-cfs-worker/LICENSE.md delete mode 100644 packages/wekan-cfs-worker/README.md delete mode 100644 packages/wekan-cfs-worker/api.md delete mode 100644 packages/wekan-cfs-worker/fileWorker.js delete mode 100644 packages/wekan-cfs-worker/internal.api.md delete mode 100644 packages/wekan-cfs-worker/package.js delete mode 100644 packages/wekan-cfs-worker/tests/client-tests.js delete mode 100644 packages/wekan-cfs-worker/tests/server-tests.js diff --git a/packages/wekan-cfs-access-point/.travis.yml b/packages/wekan-cfs-access-point/.travis.yml deleted file mode 100644 index 6a4640033..000000000 --- a/packages/wekan-cfs-access-point/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - "0.10" -before_install: - - "curl -L http://git.io/s0Zu-w | /bin/sh" \ No newline at end of file diff --git a/packages/wekan-cfs-access-point/CHANGELOG.md b/packages/wekan-cfs-access-point/CHANGELOG.md deleted file mode 100644 index 759f22a03..000000000 --- a/packages/wekan-cfs-access-point/CHANGELOG.md +++ /dev/null @@ -1,288 +0,0 @@ -# Changelog - -## [v0.1.50] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.1.46) -#### 21/1/19 by Harry Adel - -- Bump to version 0.1.50 - -- *Merged pull-request:* "filename conversion for FS.HTTP.Handlers.Get" [#9](https://github.com/zcfs/Meteor-CollectionFS/pull/994) ([yatusiter](https://github.com/yatusiter)) - - - -## [v0.1.46] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.1.46) -#### 30/3/15 by Eric Dobbertin - -- Bump to version 0.1.46 - -- *Merged pull-request:* [#611](https://github.com/zcfs/Meteor-CollectionFS/issues/611) - -- Exposed request handlers on `FS.HTTP.Handlers` object so that app can override - -## [v0.1.43] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.1.43) -#### 20/12/14 by Morten Henriksen -- add changelog - -- Bump to version 0.1.43 - -- *Fixed bug:* "Doesn't work in IE 8" [#10](https://github.com/zcfs/Meteor-cfs-access-point/issues/10) - -- *Merged pull-request:* "rootUrlPathPrefix fix for cordova" [#9](https://github.com/zcfs/Meteor-cfs-access-point/issues/9) ([dmitriyles](https://github.com/dmitriyles)) - -- *Merged pull-request:* "Support for expiration token" [#1](https://github.com/zcfs/Meteor-cfs-access-point/issues/1) ([tanis2000](https://github.com/tanis2000)) - -Patches by GitHub users [@dmitriyles](https://github.com/dmitriyles), [@tanis2000](https://github.com/tanis2000). - -## [v0.1.42] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.1.42) -#### 17/12/14 by Morten Henriksen -## [v0.1.41] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.1.41) -#### 17/12/14 by Morten Henriksen -- mbr update, remove versions.json - -- Cordova rootUrlPathPrefix fix - -- Bump to version 0.1.41 - -## [v0.1.40] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.1.40) -#### 17/12/14 by Morten Henriksen -- mbr fixed warnings - -- fixes to GET handler - -- add back tests - -- support apps in server subdirectories; closes #8 - -- 0.9.1 support - -## [v0.0.39] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.39) -#### 28/08/14 by Morten Henriksen -- Meteor Package System Update - -## [v0.0.38] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.38) -#### 27/08/14 by Eric Dobbertin -## [v0.0.37] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.37) -#### 26/08/14 by Eric Dobbertin -- change package name to lowercase - -## [v0.0.36] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.36) -#### 06/08/14 by Eric Dobbertin -- pass correct arg - -## [v0.0.35] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.35) -#### 06/08/14 by Eric Dobbertin -- move to correct place - -## [v0.0.34] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.34) -#### 05/08/14 by Eric Dobbertin -- *Merged pull-request:* "Added contentLength for ranges and inline content" [#5](https://github.com/zcfs/Meteor-cfs-access-point/issues/5) ([maomorales](https://github.com/maomorales)) - -- Content-Length and Last-Modified headers - -Patches by GitHub user [@maomorales](https://github.com/maomorales). - -## [v0.0.33] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.33) -#### 31/07/14 by Eric Dobbertin -- *Merged pull-request:* "Force browser to download with filename passed in url" [#3](https://github.com/zcfs/Meteor-cfs-access-point/issues/3) ([elbowz](https://github.com/elbowz)) - -- Force browser to download with filename passed in url - -Patches by GitHub user [@elbowz](https://github.com/elbowz). - -## [v0.0.32] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.32) -#### 28/07/14 by Eric Dobbertin -- support collection-specific GET headers - -- update API docs - -## [v0.0.31] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.31) -#### 06/07/14 by Eric Dobbertin -- allow override filename - -## [v0.0.30] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.30) -#### 30/04/14 by Eric Dobbertin -- ignore auth on server so that url method can be called on the server - -## [v0.0.29] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.29) -#### 30/04/14 by Eric Dobbertin -- rework the new authtoken stuff to make it easier to debug and cleaner - -## [v0.0.28] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.28) -#### 29/04/14 by Eric Dobbertin -- generate api docs - -- adjustments to use new FS.File API functions, plus have `url` function omit query string whenever possible - -- *Merged pull-request:* "Support for expiration token" [#1](https://github.com/zcfs/Meteor-cfs-access-point/issues/1) ([tanis2000](https://github.com/tanis2000)) - -- Switched to HTTP.call() to get the server time - -- Better check for options.auth being a number. Check to see if we have Buffer() available on the server side. New check to make sure we have the token. Switched Metheor.method to HTTP.methods for the getServerTime() function. - -- Expiration is now optional. If auth is set to a number, that is the number of seconds the token is valid for. - -- Added time sync with the server for token generation. - -- Added code to pass a token with a set expiration date from the client. Added token check on the server side. - -Patches by GitHub user [@tanis2000](https://github.com/tanis2000). - -## [v0.0.27] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.27) -#### 08/04/14 by Eric Dobbertin -- clean up/fix whole-file upload handler - -## [v0.0.26] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.26) -#### 07/04/14 by Eric Dobbertin -- add URL options to get temporary images while uploading and storing - -## [v0.0.25] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.25) -#### 03/04/14 by Eric Dobbertin -- * allow `setBaseUrl` to be called either outside of Meteor.startup or inside * move encodeParams helper to FS.Utility - -## [v0.0.24] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.24) -#### 03/04/14 by Eric Dobbertin -- properly remount URLs - -- when uploading chunks, check the insert allow/deny since it's part of inserting - -## [v0.0.23] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.23) -#### 31/03/14 by Eric Dobbertin -- use latest releases - -## [v0.0.22] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.22) -#### 29/03/14 by Morten Henriksen -- remove underscore deps - -## [v0.0.21] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.21) -#### 25/03/14 by Morten Henriksen -- add comments about shareId - -## [v0.0.20] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.20) -#### 23/03/14 by Morten Henriksen -- Rollback to specific git dependency - -- Try modified test script - -- deps are already in collectionFS - -## [v0.0.19] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.19) -#### 22/03/14 by Morten Henriksen -- try to fix travis test by using general package references - -## [v0.0.18] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.18) -#### 22/03/14 by Morten Henriksen -- If the read stream fails we send an error to the client - -## [v0.0.17] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.17) -#### 21/03/14 by Morten Henriksen -- remove smart lock - -- commit smart.lock, trying to get tests to pass on travis - -- some minor pkg adjustments; trying to get tests to pass on travis - -## [v0.0.16] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.16) -#### 18/03/14 by Morten Henriksen -- Rollback to using the direct storage adapter - makes more sense when serving files - -- shift to new http.methods streaming api - -- move server side DDP access points to cfs-download-ddp pkg; update API docs - -- fix typo... - -- return something useful - -- convert to streaming - -- Add streaming WIP - -- fix/adjust some tests; minor improvements to some handlers - -- Add unmount and allow mount to use default selector function - -- Refactor access point - wip - -## [v0.0.15] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.15) -#### 05/03/14 by Morten Henriksen -- Refactor note, encode stuff should be prefixed into FS.Utility - -- FS.File.url add user deps when auth is used - -- fix url method - -- query string fix - -- move PUT access points for HTTP upload into this package; mount DELETE on /record/ as well as /files/; some fixes and improvements to handlers - -## [v0.0.14] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.14) -#### 03/03/14 by Eric Dobbertin -- better error; return Buffer instead of converting to Uint8Array - -## [v0.0.13] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.13) -#### 02/03/14 by Eric Dobbertin -- more tests, make everything work, add unpublish method - -- Merge branch 'master' of https://github.com/zcfs/Meteor-cfs-access-point - -## [v0.0.12] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.12) -#### 01/03/14 by Eric Dobbertin -- add travis-ci image - -- rework URLs a bit, use http-publish package to publish FS.Collection listing, and add a test for this (!) - -- add http-publish dependency - -- del should be delete - -## [v0.0.11] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.11) -#### 28/02/14 by Eric Dobbertin -- move some code to other packages; redo the HTTP GET/DEL methods - -## [v0.0.10] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.10) -#### 28/02/14 by Eric Dobbertin -- move DDP upload methods to new cfs-upload-ddp package - -## [v0.0.9] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.9) -#### 21/02/14 by Eric Dobbertin -- new URL syntax; use the store's file key instead of ID; also fix allow/deny checks with insecure - -## [v0.0.8] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.8) -#### 20/02/14 by Eric Dobbertin -- support HTTP PUT of new file and fix PUT of existing file - -## [v0.0.7] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.7) -#### 17/02/14 by Morten Henriksen -- add http-methods dependency - -## [v0.0.6] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.6) -#### 16/02/14 by Morten Henriksen -## [v0.0.5] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.5) -#### 16/02/14 by Morten Henriksen -- a few fixes and improvements - -- need to actually mount it - -- attempt at switching to generic HTTP access point; also add support for chunked http downloads (range header) - -## [v0.0.4] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.4) -#### 15/02/14 by Morten Henriksen -- Merge branch 'master' of https://github.com/zcfs/Meteor-cfs-access-point - -- corrected typo - -- added debugging - -- call HTTP.methods on server only - -- run client side, too, for side effects - -- rework for additional abstraction; also DDP methods don't need to be per-collection so they no longer are - -## [v0.0.3] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.3) -#### 13/02/14 by Morten Henriksen -## [v0.0.2] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.2) -#### 13/02/14 by Morten Henriksen -## [v0.0.1] (https://github.com/zcfs/Meteor-cfs-access-point/tree/v0.0.1) -#### 13/02/14 by Morten Henriksen -- init commit - diff --git a/packages/wekan-cfs-access-point/LICENSE.md b/packages/wekan-cfs-access-point/LICENSE.md deleted file mode 100644 index 1a3820821..000000000 --- a/packages/wekan-cfs-access-point/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 [@raix](https://github.com/raix) and [@aldeed](https://github.com/aldeed), aka Morten N.O. Nørgaard Henriksen, mh@gi-software.com - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/wekan-cfs-access-point/README.md b/packages/wekan-cfs-access-point/README.md deleted file mode 100644 index fe7583265..000000000 --- a/packages/wekan-cfs-access-point/README.md +++ /dev/null @@ -1,32 +0,0 @@ -wekan-cfs-access-point [![Build Status](https://travis-ci.org/CollectionFS/Meteor-cfs-access-point.png?branch=master)](https://travis-ci.org/CollectionFS/Meteor-cfs-access-point) -========================= - -This is a Meteor package used by -[CollectionFS](https://github.com/zcfs/Meteor-CollectionFS). - -You don't need to manually add this package to your app. It is added when you -add the `wekan-cfs-standard-packages` package. You could potentially use your own access point -package instead. - -## Define a URL for Collection Listing - -To define a URL that accepts GET requests and returns a list of published -files in a FS.Collection: - -```js -Images = new FS.Collection("images", { - stores: [myStore] -}); - -FS.HTTP.publish(Images, function () { - // `this` provides a context similar to Meteor.publish - return Images.find(); -}); -``` - -The URL will be '/cfs/record/images', where the `cfs` piece is configurable -using the `FS.HTTP.setBaseUrl` method. - -## API Documentation - -[Here](api.md) diff --git a/packages/wekan-cfs-access-point/access-point-client.js b/packages/wekan-cfs-access-point/access-point-client.js deleted file mode 100644 index bc25d0bca..000000000 --- a/packages/wekan-cfs-access-point/access-point-client.js +++ /dev/null @@ -1,58 +0,0 @@ -FS.HTTP.setHeadersForGet = function setHeadersForGet() { - // Client Stub -}; - -FS.HTTP.now = function() { - return new Date(new Date() + FS.HTTP._serverTimeDiff); -}; - -// Returns the localstorage if its found and working -// TODO: check if this works in IE -// could use Meteor._localStorage - just needs a rewrite -FS.HTTP._storage = function() { - var storage, - fail, - uid; - try { - uid = "test"; - (storage = window.localStorage).setItem(uid, uid); - fail = (storage.getItem(uid) !== uid); - storage.removeItem(uid); - if (fail) { - storage = false; - } - } catch(e) { - console.log("Error initializing storage for FS.HTTP"); - console.log(e); - } - - return storage; -}; - -// get our storage if found -FS.HTTP.storage = FS.HTTP._storage(); - -FS.HTTP._prefix = 'fsHTTP.'; - -FS.HTTP._serverTimeDiff = 0; // Time difference in ms - -if (FS.HTTP.storage) { - // Initialize the FS.HTTP._serverTimeDiff - FS.HTTP._serverTimeDiff = (1*FS.HTTP.storage.getItem(FS.HTTP._prefix+'timeDiff')) || 0; - // At client startup we figure out the time difference between server and - // client time - this includes lag and timezone - Meteor.startup(function() { - // Call the server method an get server time - HTTP.get(rootUrlPathPrefix + '/cfs/servertime', function(error, result) { - if (!error) { - // Update our server time diff - var dateNew = new Date(+result.content); - FS.HTTP._serverTimeDiff = dateNew - new Date();// - lag or/and timezone - // Update the localstorage - FS.HTTP.storage.setItem(FS.HTTP._prefix + 'timeDiff', FS.HTTP._serverTimeDiff); - } else { - console.log(error.message); - } - }); // EO Server call - }); -} diff --git a/packages/wekan-cfs-access-point/access-point-common.js b/packages/wekan-cfs-access-point/access-point-common.js deleted file mode 100644 index bccf7c14c..000000000 --- a/packages/wekan-cfs-access-point/access-point-common.js +++ /dev/null @@ -1,199 +0,0 @@ -rootUrlPathPrefix = __meteor_runtime_config__.ROOT_URL_PATH_PREFIX || ""; -// Adjust the rootUrlPathPrefix if necessary -if (rootUrlPathPrefix.length > 0) { - if (rootUrlPathPrefix.slice(0, 1) !== '/') { - rootUrlPathPrefix = '/' + rootUrlPathPrefix; - } - if (rootUrlPathPrefix.slice(-1) === '/') { - rootUrlPathPrefix = rootUrlPathPrefix.slice(0, -1); - } -} - -// prepend ROOT_URL when isCordova -if (Meteor.isCordova) { - rootUrlPathPrefix = Meteor.absoluteUrl(rootUrlPathPrefix.replace(/^\/+/, '')).replace(/\/+$/, ''); -} - -baseUrl = '/cfs'; -FS.HTTP = FS.HTTP || {}; - -// Note the upload URL so that client uploader packages know what it is -FS.HTTP.uploadUrl = rootUrlPathPrefix + baseUrl + '/files'; - -/** - * @method FS.HTTP.setBaseUrl - * @public - * @param {String} newBaseUrl - Change the base URL for the HTTP GET and DELETE endpoints. - * @returns {undefined} - */ -FS.HTTP.setBaseUrl = function setBaseUrl(newBaseUrl) { - - // Adjust the baseUrl if necessary - if (newBaseUrl.slice(0, 1) !== '/') { - newBaseUrl = '/' + newBaseUrl; - } - if (newBaseUrl.slice(-1) === '/') { - newBaseUrl = newBaseUrl.slice(0, -1); - } - - // Update the base URL - baseUrl = newBaseUrl; - - // Change the upload URL so that client uploader packages know what it is - FS.HTTP.uploadUrl = rootUrlPathPrefix + baseUrl + '/files'; - - // Remount URLs with the new baseUrl, unmounting the old, on the server only. - // If existingMountPoints is empty, then we haven't run the server startup - // code yet, so this new URL will be used at that point for the initial mount. - if (Meteor.isServer && !FS.Utility.isEmpty(_existingMountPoints)) { - mountUrls(); - } -}; - -/* - * FS.File extensions - */ - -/** - * @method FS.File.prototype.urlRelative Construct the file url - * @public - * @param {Object} [options] - * @param {String} [options.store] Name of the store to get from. If not defined, the first store defined in `options.stores` for the collection on the client is used. - * @param {Boolean} [options.auth=null] Add authentication token to the URL query string? By default, a token for the current logged in user is added on the client. Set this to `false` to omit the token. Set this to a string to provide your own token. Set this to a number to specify an expiration time for the token in seconds. - * @param {Boolean} [options.download=false] Should headers be set to force a download? Typically this means that clicking the link with this URL will download the file to the user's Downloads folder instead of displaying the file in the browser. - * @param {Boolean} [options.brokenIsFine=false] Return the URL even if we know it's currently a broken link because the file hasn't been saved in the requested store yet. - * @param {Boolean} [options.returnWhenStored=false] Flag relevant only on server, Return the URL only when file has been saved to the requested store. - * @param {Boolean} [options.metadata=false] Return the URL for the file metadata access point rather than the file itself. - * @param {String} [options.uploading=null] A URL to return while the file is being uploaded. - * @param {String} [options.storing=null] A URL to return while the file is being stored. - * @param {String} [options.filename=null] Override the filename that should appear at the end of the URL. By default it is the name of the file in the requested store. - * - * Returns the relative HTTP URL for getting the file or its metadata. - */ -FS.File.prototype.urlRelative = function(options) { - var self = this; - options = options || {}; - options = FS.Utility.extend({ - store: null, - auth: null, - download: false, - metadata: false, - brokenIsFine: false, - returnWhenStored: false, - uploading: null, // return this URL while uploading - storing: null, // return this URL while storing - filename: null // override the filename that is shown to the user - }, options.hash || options); // check for "hash" prop if called as helper - - // Primarily useful for displaying a temporary image while uploading an image - if (options.uploading && !self.isUploaded()) { - return options.uploading; - } - - if (self.isMounted()) { - // See if we've stored in the requested store yet - var storeName = options.store || self.collection.primaryStore.name; - if (!self.hasStored(storeName)) { - if (options.storing) { - return options.storing; - } else if (!options.brokenIsFine) { - // In case we want to get back the url only when he is stored - if (Meteor.isServer && options.returnWhenStored) { - // Wait till file is stored to storeName - self.onStored(storeName); - } else { - // We want to return null if we know the URL will be a broken - // link because then we can avoid rendering broken links, broken - // images, etc. - return null; - } - } - } - - // Add filename to end of URL if we can determine one - var filename = options.filename || self.name({store: storeName}); - if (typeof filename === "string" && filename.length) { - filename = '/' + filename; - } else { - filename = ''; - } - - // TODO: Could we somehow figure out if the collection requires login? - var authToken = ''; - if (Meteor.isClient && typeof Accounts !== "undefined" && typeof Accounts._storedLoginToken === "function") { - if (options.auth !== false) { - // Add reactive deps on the user - Meteor.userId(); - - var authObject = { - authToken: Accounts._storedLoginToken() || '' - }; - - // If it's a number, we use that as the expiration time (in seconds) - if (options.auth === +options.auth) { - authObject.expiration = FS.HTTP.now() + options.auth * 1000; - } - - // Set the authToken - var authString = JSON.stringify(authObject); - authToken = FS.Utility.btoa(authString); - } - } else if (typeof options.auth === "string") { - // If the user supplies auth token the user will be responsible for - // updating - authToken = options.auth; - } - - // Construct query string - var params = {}; - if (authToken !== '') { - params.token = authToken; - } - if (options.download) { - params.download = true; - } - if (options.store) { - // We use options.store here instead of storeName because we want to omit the queryString - // whenever possible, allowing users to have "clean" URLs if they want. The server will - // assume the first store defined on the server, which means that we are assuming that - // the first on the client is also the first on the server. If that's not the case, the - // store option should be supplied. - params.store = options.store; - } - var queryString = FS.Utility.encodeParams(params); - if (queryString.length) { - queryString = '?' + queryString; - } - - // Determine which URL to use - var area; - if (options.metadata) { - area = '/record'; - } else { - area = '/files'; - } - - // Construct and return the http method url - return baseUrl + area + '/' + self.collection.name + '/' + self._id + filename + queryString; - } -}; - -/** - * @method FS.File.prototype.url Construct the file url - * @public - * @param {Object} [options] - * @param {String} [options.store] Name of the store to get from. If not defined, the first store defined in `options.stores` for the collection on the client is used. - * @param {Boolean} [options.auth=null] Add authentication token to the URL query string? By default, a token for the current logged in user is added on the client. Set this to `false` to omit the token. Set this to a string to provide your own token. Set this to a number to specify an expiration time for the token in seconds. - * @param {Boolean} [options.download=false] Should headers be set to force a download? Typically this means that clicking the link with this URL will download the file to the user's Downloads folder instead of displaying the file in the browser. - * @param {Boolean} [options.brokenIsFine=false] Return the URL even if we know it's currently a broken link because the file hasn't been saved in the requested store yet. - * @param {Boolean} [options.metadata=false] Return the URL for the file metadata access point rather than the file itself. - * @param {String} [options.uploading=null] A URL to return while the file is being uploaded. - * @param {String} [options.storing=null] A URL to return while the file is being stored. - * @param {String} [options.filename=null] Override the filename that should appear at the end of the URL. By default it is the name of the file in the requested store. - * - * Returns the HTTP URL for getting the file or its metadata. - */ -FS.File.prototype.url = function(options) { - self = this; - return rootUrlPathPrefix + self.urlRelative(options); -}; \ No newline at end of file diff --git a/packages/wekan-cfs-access-point/access-point-handlers.js b/packages/wekan-cfs-access-point/access-point-handlers.js deleted file mode 100644 index e4615f069..000000000 --- a/packages/wekan-cfs-access-point/access-point-handlers.js +++ /dev/null @@ -1,307 +0,0 @@ -getHeaders = []; -getHeadersByCollection = {}; - -var contentDisposition = Npm.require('content-disposition'); - -FS.HTTP.Handlers = {}; - -/** - * @method FS.HTTP.Handlers.Del - * @public - * @returns {any} response - * - * HTTP DEL request handler - */ -FS.HTTP.Handlers.Del = function httpDelHandler(ref) { - var self = this; - var opts = FS.Utility.extend({}, self.query || {}, self.params || {}); - - // If DELETE request, validate with 'remove' allow/deny, delete the file, and return - FS.Utility.validateAction(ref.collection.files._validators['remove'], ref.file, self.userId); - - /* - * From the DELETE spec: - * A successful response SHOULD be 200 (OK) if the response includes an - * entity describing the status, 202 (Accepted) if the action has not - * yet been enacted, or 204 (No Content) if the action has been enacted - * but the response does not include an entity. - */ - self.setStatusCode(200); - - return { - deleted: !!ref.file.remove() - }; -}; - -/** - * @method FS.HTTP.Handlers.GetList - * @public - * @returns {Object} response - * - * HTTP GET file list request handler - */ -FS.HTTP.Handlers.GetList = function httpGetListHandler() { - // Not Yet Implemented - // Need to check publications and return file list based on - // what user is allowed to see -}; - -/* - requestRange will parse the range set in request header - if not possible it - will throw fitting errors and autofill range for both partial and full ranges - - throws error or returns the object: - { - start - end - length - unit - partial - } -*/ -var requestRange = function(req, fileSize) { - if (req) { - if (req.headers) { - var rangeString = req.headers.range; - - // Make sure range is a string - if (rangeString === ''+rangeString) { - - // range will be in the format "bytes=0-32767" - var parts = rangeString.split('='); - var unit = parts[0]; - - // Make sure parts consists of two strings and range is of type "byte" - if (parts.length == 2 && unit == 'bytes') { - // Parse the range - var range = parts[1].split('-'); - var start = Number(range[0]); - var end = Number(range[1]); - - // Fix invalid ranges? - if (range[0] != start) start = 0; - if (range[1] != end || !end) end = fileSize - 1; - - // Make sure range consists of a start and end point of numbers and start is less than end - if (start < end) { - - var partSize = 0 - start + end + 1; - - // Return the parsed range - return { - start: start, - end: end, - length: partSize, - size: fileSize, - unit: unit, - partial: (partSize < fileSize) - }; - - } else { - throw new Meteor.Error(416, "Requested Range Not Satisfiable"); - } - - } else { - // The first part should be bytes - throw new Meteor.Error(416, "Requested Range Unit Not Satisfiable"); - } - - } else { - // No range found - } - - } else { - // throw new Error('No request headers set for _parseRange function'); - } - } else { - throw new Error('No request object passed to _parseRange function'); - } - - return { - start: 0, - end: fileSize - 1, - length: fileSize, - size: fileSize, - unit: 'bytes', - partial: false - }; -}; - -/** - * @method FS.HTTP.Handlers.Get - * @public - * @returns {any} response - * - * HTTP GET request handler - */ -FS.HTTP.Handlers.Get = function httpGetHandler(ref) { - var self = this; - // Once we have the file, we can test allow/deny validators - // XXX: pass on the "share" query eg. ?share=342hkjh23ggj for shared url access? - FS.Utility.validateAction(ref.collection._validators['download'], ref.file, self.userId /*, self.query.shareId*/); - - var storeName = ref.storeName; - - // If no storeName was specified, use the first defined storeName - if (typeof storeName !== "string") { - // No store handed, we default to primary store - storeName = ref.collection.primaryStore.name; - } - - // Get the storage reference - var storage = ref.collection.storesLookup[storeName]; - - if (!storage) { - throw new Meteor.Error(404, "Not Found", 'There is no store "' + storeName + '"'); - } - - // Get the file - var copyInfo = ref.file.copies[storeName]; - - if (!copyInfo) { - throw new Meteor.Error(404, "Not Found", 'This file was not stored in the ' + storeName + ' store'); - } - - // Set the content type for file - if (typeof copyInfo.type === "string") { - self.setContentType(copyInfo.type); - } else { - self.setContentType('application/octet-stream'); - } - - // Add 'Content-Disposition' header if requested a download/attachment URL - if (typeof ref.download !== "undefined") { - var filename = ref.filename || copyInfo.name; - self.addHeader('Content-Disposition', contentDisposition(filename)); - } else { - self.addHeader('Content-Disposition', 'inline'); - } - - // Get the contents range from request - var range = requestRange(self.request, copyInfo.size); - - // Some browsers cope better if the content-range header is - // still included even for the full file being returned. - self.addHeader('Content-Range', range.unit + ' ' + range.start + '-' + range.end + '/' + range.size); - - // If a chunk/range was requested instead of the whole file, serve that' - if (range.partial) { - self.setStatusCode(206, 'Partial Content'); - } else { - self.setStatusCode(200, 'OK'); - } - - // Add any other global custom headers and collection-specific custom headers - FS.Utility.each(getHeaders.concat(getHeadersByCollection[ref.collection.name] || []), function(header) { - self.addHeader(header[0], header[1]); - }); - - // Inform clients about length (or chunk length in case of ranges) - self.addHeader('Content-Length', range.length); - - // Last modified header (updatedAt from file info) - self.addHeader('Last-Modified', copyInfo.updatedAt.toUTCString()); - - // Inform clients that we accept ranges for resumable chunked downloads - self.addHeader('Accept-Ranges', range.unit); - - if (FS.debug) console.log('Read file "' + (ref.filename || copyInfo.name) + '" ' + range.unit + ' ' + range.start + '-' + range.end + '/' + range.size); - - var readStream = storage.adapter.createReadStream(ref.file, {start: range.start, end: range.end}); - - readStream.on('error', function(err) { - // Send proper error message on get error - if (err.message && err.statusCode) { - self.Error(new Meteor.Error(err.statusCode, err.message)); - } else { - self.Error(new Meteor.Error(503, 'Service unavailable')); - } - }); - - readStream.pipe(self.createWriteStream()); -}; - -// File with unicode or other encodings filename can upload to server susscessfully, -// but when download, the HTTP header "Content-Disposition" cannot accept -// characters other than ASCII, the filename should be converted to binary or URI encoded. -// https://github.com/wekan/wekan/issues/784 -const originalHandler = FS.HTTP.Handlers.Get; -FS.HTTP.Handlers.Get = function (ref) { - try { - var userAgent = (this.requestHeaders['user-agent']||'').toLowerCase(); - if(userAgent.indexOf('msie') >= 0 || userAgent.indexOf('chrome') >= 0) { - ref.filename = encodeURIComponent(ref.filename); - } else if(userAgent.indexOf('firefox') >= 0) { - ref.filename = new Buffer(ref.filename).toString('binary'); - } else { - /* safari*/ - ref.filename = new Buffer(ref.filename).toString('binary'); - } - } catch (ex){ - ref.filename = ref.filename; - } - return originalHandler.call(this, ref); -}; - - -/** - * @method FS.HTTP.Handlers.PutInsert - * @public - * @returns {Object} response object with _id property - * - * HTTP PUT file insert request handler - */ -FS.HTTP.Handlers.PutInsert = function httpPutInsertHandler(ref) { - var self = this; - var opts = FS.Utility.extend({}, self.query || {}, self.params || {}); - - FS.debug && console.log("HTTP PUT (insert) handler"); - - // Create the nice FS.File - var fileObj = new FS.File(); - - // Set its name - fileObj.name(opts.filename || null); - - // Attach the readstream as the file's data - fileObj.attachData(self.createReadStream(), {type: self.requestHeaders['content-type'] || 'application/octet-stream'}); - - // Validate with insert allow/deny - FS.Utility.validateAction(ref.collection.files._validators['insert'], fileObj, self.userId); - - // Insert file into collection, triggering readStream storage - ref.collection.insert(fileObj); - - // Send response - self.setStatusCode(200); - - // Return the new file id - return {_id: fileObj._id}; -}; - -/** - * @method FS.HTTP.Handlers.PutUpdate - * @public - * @returns {Object} response object with _id and chunk properties - * - * HTTP PUT file update chunk request handler - */ -FS.HTTP.Handlers.PutUpdate = function httpPutUpdateHandler(ref) { - var self = this; - var opts = FS.Utility.extend({}, self.query || {}, self.params || {}); - - var chunk = parseInt(opts.chunk, 10); - if (isNaN(chunk)) chunk = 0; - - FS.debug && console.log("HTTP PUT (update) handler received chunk: ", chunk); - - // Validate with insert allow/deny; also mounts and retrieves the file - FS.Utility.validateAction(ref.collection.files._validators['insert'], ref.file, self.userId); - - self.createReadStream().pipe( FS.TempStore.createWriteStream(ref.file, chunk) ); - - // Send response - self.setStatusCode(200); - - return { _id: ref.file._id, chunk: chunk }; -}; diff --git a/packages/wekan-cfs-access-point/access-point-server.js b/packages/wekan-cfs-access-point/access-point-server.js deleted file mode 100644 index 2f17cf9a0..000000000 --- a/packages/wekan-cfs-access-point/access-point-server.js +++ /dev/null @@ -1,362 +0,0 @@ -var path = Npm.require("path"); - -HTTP.publishFormats({ - fileRecordFormat: function (input) { - // Set the method scope content type to json - this.setContentType('application/json'); - if (FS.Utility.isArray(input)) { - return EJSON.stringify(FS.Utility.map(input, function (obj) { - return FS.Utility.cloneFileRecord(obj); - })); - } else { - return EJSON.stringify(FS.Utility.cloneFileRecord(input)); - } - } -}); - -/** - * @method FS.HTTP.setHeadersForGet - * @public - * @param {Array} headers - List of headers, where each is a two-item array in which item 1 is the header name and item 2 is the header value. - * @param {Array|String} [collections] - Which collections the headers should be added for. Omit this argument to add the header for all collections. - * @returns {undefined} - */ -FS.HTTP.setHeadersForGet = function setHeadersForGet(headers, collections) { - if (typeof collections === "string") { - collections = [collections]; - } - if (collections) { - FS.Utility.each(collections, function(collectionName) { - getHeadersByCollection[collectionName] = headers || []; - }); - } else { - getHeaders = headers || []; - } -}; - -/** - * @method FS.HTTP.publish - * @public - * @param {FS.Collection} collection - * @param {Function} func - Publish function that returns a cursor. - * @returns {undefined} - * - * Publishes all documents returned by the cursor at a GET URL - * with the format baseUrl/record/collectionName. The publish - * function `this` is similar to normal `Meteor.publish`. - */ -FS.HTTP.publish = function fsHttpPublish(collection, func) { - var name = baseUrl + '/record/' + collection.name; - // Mount collection listing URL using http-publish package - HTTP.publish({ - name: name, - defaultFormat: 'fileRecordFormat', - collection: collection, - collectionGet: true, - collectionPost: false, - documentGet: true, - documentPut: false, - documentDelete: false - }, func); - - FS.debug && console.log("Registered HTTP method GET URLs:\n\n" + name + '\n' + name + '/:id\n'); -}; - -/** - * @method FS.HTTP.unpublish - * @public - * @param {FS.Collection} collection - * @returns {undefined} - * - * Unpublishes a restpoint created by a call to `FS.HTTP.publish` - */ -FS.HTTP.unpublish = function fsHttpUnpublish(collection) { - // Mount collection listing URL using http-publish package - HTTP.unpublish(baseUrl + '/record/' + collection.name); -}; - -_existingMountPoints = {}; - -/** - * @method defaultSelectorFunction - * @private - * @returns { collection, file } - * - * This is the default selector function - */ -var defaultSelectorFunction = function() { - var self = this; - // Selector function - // - // This function will have to return the collection and the - // file. If file not found undefined is returned - if null is returned the - // search was not possible - var opts = FS.Utility.extend({}, self.query || {}, self.params || {}); - - // Get the collection name from the url - var collectionName = opts.collectionName; - - // Get the id from the url - var id = opts.id; - - // Get the collection - var collection = FS._collections[collectionName]; - - //if Mongo ObjectIds are used, then we need to use that in find statement - if(collection.options.idGeneration && collection.options.idGeneration === 'MONGO') { - // Get the file if possible else return null - var file = (id && collection)? collection.findOne({ _id: new Meteor.Collection.ObjectID(id)}): null; - } else { - var file = (id && collection)? collection.findOne({ _id: id }): null; - } - - - // Return the collection and the file - return { - collection: collection, - file: file, - storeName: opts.store, - download: opts.download, - filename: opts.filename - }; -}; - -/* - * @method FS.HTTP.mount - * @public - * @param {array of string} mountPoints mount points to map rest functinality on - * @param {function} selector_f [selector] function returns `{ collection, file }` for mount points to work with - * -*/ -FS.HTTP.mount = function(mountPoints, selector_f) { - // We take mount points as an array and we get a selector function - var selectorFunction = selector_f || defaultSelectorFunction; - - var accessPoint = { - 'stream': true, - 'auth': expirationAuth, - 'post': function(data) { - // Use the selector for finding the collection and file reference - var ref = selectorFunction.call(this); - - // We dont support post - this would be normal insert eg. of filerecord? - throw new Meteor.Error(501, "Not implemented", "Post is not supported"); - }, - 'put': function(data) { - // Use the selector for finding the collection and file reference - var ref = selectorFunction.call(this); - - // Make sure we have a collection reference - if (!ref.collection) - throw new Meteor.Error(404, "Not Found", "No collection found"); - - // Make sure we have a file reference - if (ref.file === null) { - // No id supplied so we will create a new FS.File instance and - // insert the supplied data. - return FS.HTTP.Handlers.PutInsert.apply(this, [ref]); - } else { - if (ref.file) { - return FS.HTTP.Handlers.PutUpdate.apply(this, [ref]); - } else { - throw new Meteor.Error(404, "Not Found", 'No file found'); - } - } - }, - 'get': function(data) { - // Use the selector for finding the collection and file reference - var ref = selectorFunction.call(this); - - // Make sure we have a collection reference - if (!ref.collection) - throw new Meteor.Error(404, "Not Found", "No collection found"); - - // Make sure we have a file reference - if (ref.file === null) { - // No id supplied so we will return the published list of files ala - // http.publish in json format - return FS.HTTP.Handlers.GetList.apply(this, [ref]); - } else { - if (ref.file) { - return FS.HTTP.Handlers.Get.apply(this, [ref]); - } else { - throw new Meteor.Error(404, "Not Found", 'No file found'); - } - } - }, - 'delete': function(data) { - // Use the selector for finding the collection and file reference - var ref = selectorFunction.call(this); - - // Make sure we have a collection reference - if (!ref.collection) - throw new Meteor.Error(404, "Not Found", "No collection found"); - - // Make sure we have a file reference - if (ref.file) { - return FS.HTTP.Handlers.Del.apply(this, [ref]); - } else { - throw new Meteor.Error(404, "Not Found", 'No file found'); - } - } - }; - - var accessPoints = {}; - - // Add debug message - FS.debug && console.log('Registered HTTP method URLs:'); - - FS.Utility.each(mountPoints, function(mountPoint) { - // Couple mountpoint and accesspoint - accessPoints[mountPoint] = accessPoint; - // Remember our mountpoints - _existingMountPoints[mountPoint] = mountPoint; - // Add debug message - FS.debug && console.log(mountPoint); - }); - - // XXX: HTTP:methods should unmount existing mounts in case of overwriting? - HTTP.methods(accessPoints); - -}; - -/** - * @method FS.HTTP.unmount - * @public - * @param {string | array of string} [mountPoints] Optional, if not specified all mountpoints are unmounted - * - */ -FS.HTTP.unmount = function(mountPoints) { - // The mountPoints is optional, can be string or array if undefined then - // _existingMountPoints will be used - var unmountList; - // Container for the mount points to unmount - var unmountPoints = {}; - - if (typeof mountPoints === 'undefined') { - // Use existing mount points - unmount all - unmountList = _existingMountPoints; - } else if (mountPoints === ''+mountPoints) { - // Got a string - unmountList = [mountPoints]; - } else if (mountPoints.length) { - // Got an array - unmountList = mountPoints; - } - - // If we have a list to unmount - if (unmountList) { - // Iterate over each item - FS.Utility.each(unmountList, function(mountPoint) { - // Check _existingMountPoints to make sure the mount point exists in our - // context / was created by the FS.HTTP.mount - if (_existingMountPoints[mountPoint]) { - // Mark as unmount - unmountPoints[mountPoint] = false; - // Release - delete _existingMountPoints[mountPoint]; - } - }); - FS.debug && console.log('FS.HTTP.unmount:'); - FS.debug && console.log(unmountPoints); - // Complete unmount - HTTP.methods(unmountPoints); - } -}; - -// ### FS.Collection maps on HTTP pr. default on the following restpoints: -// * -// baseUrl + '/files/:collectionName/:id/:filename', -// baseUrl + '/files/:collectionName/:id', -// baseUrl + '/files/:collectionName' -// -// Change/ replace the existing mount point by: -// ```js -// // unmount all existing -// FS.HTTP.unmount(); -// // Create new mount point -// FS.HTTP.mount([ -// '/cfs/files/:collectionName/:id/:filename', -// '/cfs/files/:collectionName/:id', -// '/cfs/files/:collectionName' -// ]); -// ``` -// -mountUrls = function mountUrls() { - // We unmount first in case we are calling this a second time - FS.HTTP.unmount(); - - FS.HTTP.mount([ - baseUrl + '/files/:collectionName/:id/:filename', - baseUrl + '/files/:collectionName/:id', - baseUrl + '/files/:collectionName' - ]); -}; - -// Returns the userId from URL token -var expirationAuth = function expirationAuth() { - var self = this; - - // Read the token from '/hello?token=base64' - var encodedToken = self.query.token; - - FS.debug && console.log("token: "+encodedToken); - - if (!encodedToken || !Meteor.users) return false; - - // Check the userToken before adding it to the db query - // Set the this.userId - var tokenString = FS.Utility.atob(encodedToken); - - var tokenObject; - try { - tokenObject = JSON.parse(tokenString); - } catch(err) { - throw new Meteor.Error(400, 'Bad Request'); - } - - // XXX: Do some check here of the object - var userToken = tokenObject.authToken; - if (userToken !== ''+userToken) { - throw new Meteor.Error(400, 'Bad Request'); - } - - // If we have an expiration token we should check that it's still valid - if (tokenObject.expiration != null) { - // check if its too old - var now = Date.now(); - if (tokenObject.expiration < now) { - FS.debug && console.log('Expired token: ' + tokenObject.expiration + ' is less than ' + now); - throw new Meteor.Error(500, 'Expired token'); - } - } - - // We are not on a secure line - so we have to look up the user... - var user = Meteor.users.findOne({ - $or: [ - {'services.resume.loginTokens.hashedToken': Accounts._hashLoginToken(userToken)}, - {'services.resume.loginTokens.token': userToken} - ] - }); - - // Set the userId in the scope - return user && user._id; -}; - -HTTP.methods( - {'/cfs/servertime': { - get: function(data) { - return Date.now().toString(); - } - } -}); - -// Unify client / server api -FS.HTTP.now = function() { - return Date.now(); -}; - -// Start up the basic mount points -Meteor.startup(function () { - mountUrls(); -}); diff --git a/packages/wekan-cfs-access-point/api.md b/packages/wekan-cfs-access-point/api.md deleted file mode 100644 index 18a92c7a3..000000000 --- a/packages/wekan-cfs-access-point/api.md +++ /dev/null @@ -1,271 +0,0 @@ -## wekan-cfs-access-point Public API ## - -CollectionFS, add ddp and http accesspoint capability - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -- - -### *FSHTTP*.setBaseUrl(newBaseUrl)  Anywhere ### - -*This method __setBaseUrl__ is defined in `FS.HTTP`* - -__Arguments__ - -* __newBaseUrl__ *{String}* - - Change the base URL for the HTTP GET and DELETE endpoints. - - -__Returns__ *{undefined}* - - -> ```FS.HTTP.setBaseUrl = function setBaseUrl(newBaseUrl) { ...``` [access-point-common.js:29](access-point-common.js#L29) - - -- - -### *fsFile*.url([options])  Anywhere ### - -*This method __url__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __options__ *{Object}* (Optional) - * __store__ *{String}* (Optional) - - Name of the store to get from. If not defined, the first store defined in `options.stores` for the collection on the client is used. - - * __auth__ *{Boolean}* (Optional, Default = null) - - Add authentication token to the URL query string? By default, a token for the current logged in user is added on the client. Set this to `false` to omit the token. Set this to a string to provide your own token. Set this to a number to specify an expiration time for the token in seconds. - - * __download__ *{Boolean}* (Optional, Default = false) - - Should headers be set to force a download? Typically this means that clicking the link with this URL will download the file to the user's Downloads folder instead of displaying the file in the browser. - - * __brokenIsFine__ *{Boolean}* (Optional, Default = false) - - Return the URL even if we know it's currently a broken link because the file hasn't been saved in the requested store yet. - - * __metadata__ *{Boolean}* (Optional, Default = false) - - Return the URL for the file metadata access point rather than the file itself. - - * __uploading__ *{String}* (Optional, Default = null) - - A URL to return while the file is being uploaded. - - * __storing__ *{String}* (Optional, Default = null) - - A URL to return while the file is being stored. - - * __filename__ *{String}* (Optional, Default = null) - - Override the filename that should appear at the end of the URL. By default it is the name of the file in the requested store. - - - -Returns the HTTP URL for getting the file or its metadata. - -> ```FS.File.prototype.url = function(options) { ...``` [access-point-common.js:72](access-point-common.js#L72) - - -- - -### *FSHTTPHandlers*.Del()  Server ### - -*This method __Del__ is defined in `FS.HTTP.Handlers`* - -__Returns__ *{any}* -response - - -HTTP DEL request handler - -> ```FS.HTTP.Handlers.Del = function httpDelHandler(ref) { ...``` [access-point-handlers.js:13](access-point-handlers.js#L13) - - -- - -### *FSHTTPHandlers*.GetList()  Server ### - -*This method __GetList__ is defined in `FS.HTTP.Handlers`* - -__Returns__ *{Object}* -response - - -HTTP GET file list request handler - -> ```FS.HTTP.Handlers.GetList = function httpGetListHandler() { ...``` [access-point-handlers.js:41](access-point-handlers.js#L41) - - -- - -### *FSHTTPHandlers*.Get()  Server ### - -*This method __Get__ is defined in `FS.HTTP.Handlers`* - -__Returns__ *{any}* -response - - -HTTP GET request handler - -> ```FS.HTTP.Handlers.Get = function httpGetHandler(ref) { ...``` [access-point-handlers.js:135](access-point-handlers.js#L135) - - -- - -### *FSHTTPHandlers*.PutInsert()  Server ### - -*This method __PutInsert__ is defined in `FS.HTTP.Handlers`* - -__Returns__ *{Object}* -response object with _id property - - -HTTP PUT file insert request handler - -> ```FS.HTTP.Handlers.PutInsert = function httpPutInsertHandler(ref) { ...``` [access-point-handlers.js:229](access-point-handlers.js#L229) - - -- - -### *FSHTTPHandlers*.PutUpdate()  Server ### - -*This method __PutUpdate__ is defined in `FS.HTTP.Handlers`* - -__Returns__ *{Object}* -response object with _id and chunk properties - - -HTTP PUT file update chunk request handler - -> ```FS.HTTP.Handlers.PutUpdate = function httpPutUpdateHandler(ref) { ...``` [access-point-handlers.js:264](access-point-handlers.js#L264) - - -- - -### *FSHTTP*.setHeadersForGet(headers, [collections])  Server ### - -*This method __setHeadersForGet__ is defined in `FS.HTTP`* - -__Arguments__ - -* __headers__ *{Array}* - - List of headers, where each is a two-item array in which item 1 is the header name and item 2 is the header value. - -* __collections__ *{Array|String}* (Optional) - - Which collections the headers should be added for. Omit this argument to add the header for all collections. - - -__Returns__ *{undefined}* - - -> ```FS.HTTP.setHeadersForGet = function setHeadersForGet(headers, collections) { ...``` [access-point-server.js:24](access-point-server.js#L24) - - -- - -### *FSHTTP*.publish(collection, func)  Server ### - -*This method __publish__ is defined in `FS.HTTP`* - -__Arguments__ - -* __collection__ *{[FS.Collection](#FS.Collection)}* -* __func__ *{Function}* - - Publish function that returns a cursor. - - -__Returns__ *{undefined}* - - -Publishes all documents returned by the cursor at a GET URL -with the format baseUrl/record/collectionName. The publish -function `this` is similar to normal `Meteor.publish`. - -> ```FS.HTTP.publish = function fsHttpPublish(collection, func) { ...``` [access-point-server.js:48](access-point-server.js#L48) - - -- - -### *FSHTTP*.unpublish(collection)  Server ### - -*This method __unpublish__ is defined in `FS.HTTP`* - -__Arguments__ - -* __collection__ *{[FS.Collection](#FS.Collection)}* - -__Returns__ *{undefined}* - - -Unpublishes a restpoint created by a call to `FS.HTTP.publish` - -> ```FS.HTTP.unpublish = function fsHttpUnpublish(collection) { ...``` [access-point-server.js:73](access-point-server.js#L73) - - -- - -### *FSHTTP*.mount(mountPoints, selector_f)  Server ### - -*This method __mount__ is defined in `FS.HTTP`* - -__Arguments__ - -* __mountPoints__ *{[array of string](#array of string)}* - - mount points to map rest functinality on - -* __selector_f__ *{function}* - - [selector] function returns `{ collection, file }` for mount points to work with - - - -> ```FS.HTTP.mount = function(mountPoints, selector_f) { ...``` [access-point-server.js:125](access-point-server.js#L125) - - -- - -### *FSHTTP*.unmount([mountPoints])  Server ### - -*This method __unmount__ is defined in `FS.HTTP`* - -__Arguments__ - -* __mountPoints__ *{[string ](#string )|[ array of string](# array of string)}* (Optional) - - Optional, if not specified all mountpoints are unmounted - - - - -> ```FS.HTTP.unmount = function(mountPoints) { ...``` [access-point-server.js:223](access-point-server.js#L223) - - - -- -### FS.Collection maps on HTTP pr. default on the following restpoints: -* -baseUrl + '/files/:collectionName/:id/:filename', -baseUrl + '/files/:collectionName/:id', -baseUrl + '/files/:collectionName' - -Change/ replace the existing mount point by: -```js -unmount all existing -FS.HTTP.unmount(); -Create new mount point -FS.HTTP.mount([ -'/cfs/files/:collectionName/:id/:filename', -'/cfs/files/:collectionName/:id', -'/cfs/files/:collectionName' -]); -``` diff --git a/packages/wekan-cfs-access-point/internal.api.md b/packages/wekan-cfs-access-point/internal.api.md deleted file mode 100644 index a7bf6477e..000000000 --- a/packages/wekan-cfs-access-point/internal.api.md +++ /dev/null @@ -1,332 +0,0 @@ -## Public and Private API ## - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -*** - -__File: ["access-point-common.js"](access-point-common.js) Where: {server|client}__ - -*** - -### *FSHTTP*.setBaseUrl(newBaseUrl)  Anywhere ### - -*This method __setBaseUrl__ is defined in `FS.HTTP`* - -__Arguments__ - -* __newBaseUrl__ *{String}* - - Change the base URL for the HTTP GET and DELETE endpoints. - - -__Returns__ *{undefined}* - - -> ```FS.HTTP.setBaseUrl = function setBaseUrl(newBaseUrl) { ...``` [access-point-common.js:29](access-point-common.js#L29) - - -- - -### *fsFile*.url([options])  Anywhere ### - -*This method __url__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __options__ *{Object}* (Optional) - * __store__ *{String}* (Optional) - - Name of the store to get from. If not defined, the first store defined in `options.stores` for the collection on the client is used. - - * __auth__ *{Boolean}* (Optional, Default = null) - - Add authentication token to the URL query string? By default, a token for the current logged in user is added on the client. Set this to `false` to omit the token. Set this to a string to provide your own token. Set this to a number to specify an expiration time for the token in seconds. - - * __download__ *{Boolean}* (Optional, Default = false) - - Should headers be set to force a download? Typically this means that clicking the link with this URL will download the file to the user's Downloads folder instead of displaying the file in the browser. - - * __brokenIsFine__ *{Boolean}* (Optional, Default = false) - - Return the URL even if we know it's currently a broken link because the file hasn't been saved in the requested store yet. - - * __metadata__ *{Boolean}* (Optional, Default = false) - - Return the URL for the file metadata access point rather than the file itself. - - * __uploading__ *{String}* (Optional, Default = null) - - A URL to return while the file is being uploaded. - - * __storing__ *{String}* (Optional, Default = null) - - A URL to return while the file is being stored. - - * __filename__ *{String}* (Optional, Default = null) - - Override the filename that should appear at the end of the URL. By default it is the name of the file in the requested store. - - - -Returns the HTTP URL for getting the file or its metadata. - -> ```FS.File.prototype.url = function(options) { ...``` [access-point-common.js:72](access-point-common.js#L72) - - -*** - -__File: ["access-point-handlers.js"](access-point-handlers.js) Where: {server}__ - -*** - -### *FSHTTPHandlers*.Del()  Server ### - -*This method __Del__ is defined in `FS.HTTP.Handlers`* - -__Returns__ *{any}* -response - - -HTTP DEL request handler - -> ```FS.HTTP.Handlers.Del = function httpDelHandler(ref) { ...``` [access-point-handlers.js:13](access-point-handlers.js#L13) - - -- - -### *self*.setStatusCode {any}  Server ### - -``` -From the DELETE spec: -A successful response SHOULD be 200 (OK) if the response includes an -entity describing the status, 202 (Accepted) if the action has not -yet been enacted, or 204 (No Content) if the action has been enacted -but the response does not include an entity. -``` -*This property __setStatusCode__ is defined in `self`* - -> ```self.setStatusCode(200);``` [access-point-handlers.js:27](access-point-handlers.js#L27) - - -- - -### *FSHTTPHandlers*.GetList()  Server ### - -*This method __GetList__ is defined in `FS.HTTP.Handlers`* - -__Returns__ *{Object}* -response - - -HTTP GET file list request handler - -> ```FS.HTTP.Handlers.GetList = function httpGetListHandler() { ...``` [access-point-handlers.js:41](access-point-handlers.js#L41) - - -- - -### requestRange {any}  Server ### - -``` -requestRange will parse the range set in request header - if not possible it -will throw fitting errors and autofill range for both partial and full ranges -throws error or returns the object: -{ -start -end -length -unit -partial -} -``` -*This property is private* - -> ```var requestRange = function(req, fileSize) { ...``` [access-point-handlers.js:60](access-point-handlers.js#L60) - - -- - -### *FSHTTPHandlers*.Get()  Server ### - -*This method __Get__ is defined in `FS.HTTP.Handlers`* - -__Returns__ *{any}* -response - - -HTTP GET request handler - -> ```FS.HTTP.Handlers.Get = function httpGetHandler(ref) { ...``` [access-point-handlers.js:135](access-point-handlers.js#L135) - - -- - -### *FSHTTPHandlers*.PutInsert()  Server ### - -*This method __PutInsert__ is defined in `FS.HTTP.Handlers`* - -__Returns__ *{Object}* -response object with _id property - - -HTTP PUT file insert request handler - -> ```FS.HTTP.Handlers.PutInsert = function httpPutInsertHandler(ref) { ...``` [access-point-handlers.js:229](access-point-handlers.js#L229) - - -- - -### *FSHTTPHandlers*.PutUpdate()  Server ### - -*This method __PutUpdate__ is defined in `FS.HTTP.Handlers`* - -__Returns__ *{Object}* -response object with _id and chunk properties - - -HTTP PUT file update chunk request handler - -> ```FS.HTTP.Handlers.PutUpdate = function httpPutUpdateHandler(ref) { ...``` [access-point-handlers.js:264](access-point-handlers.js#L264) - - -*** - -__File: ["access-point-server.js"](access-point-server.js) Where: {server}__ - -*** - -### *FSHTTP*.setHeadersForGet(headers, [collections])  Server ### - -*This method __setHeadersForGet__ is defined in `FS.HTTP`* - -__Arguments__ - -* __headers__ *{Array}* - - List of headers, where each is a two-item array in which item 1 is the header name and item 2 is the header value. - -* __collections__ *{Array|String}* (Optional) - - Which collections the headers should be added for. Omit this argument to add the header for all collections. - - -__Returns__ *{undefined}* - - -> ```FS.HTTP.setHeadersForGet = function setHeadersForGet(headers, collections) { ...``` [access-point-server.js:24](access-point-server.js#L24) - - -- - -### *FSHTTP*.publish(collection, func)  Server ### - -*This method __publish__ is defined in `FS.HTTP`* - -__Arguments__ - -* __collection__ *{[FS.Collection](#FS.Collection)}* -* __func__ *{Function}* - - Publish function that returns a cursor. - - -__Returns__ *{undefined}* - - -Publishes all documents returned by the cursor at a GET URL -with the format baseUrl/record/collectionName. The publish -function `this` is similar to normal `Meteor.publish`. - -> ```FS.HTTP.publish = function fsHttpPublish(collection, func) { ...``` [access-point-server.js:48](access-point-server.js#L48) - - -- - -### *FSHTTP*.unpublish(collection)  Server ### - -*This method __unpublish__ is defined in `FS.HTTP`* - -__Arguments__ - -* __collection__ *{[FS.Collection](#FS.Collection)}* - -__Returns__ *{undefined}* - - -Unpublishes a restpoint created by a call to `FS.HTTP.publish` - -> ```FS.HTTP.unpublish = function fsHttpUnpublish(collection) { ...``` [access-point-server.js:73](access-point-server.js#L73) - - -- - -### defaultSelectorFunction()  Server ### - -*This method is private* - -__Returns__ *{ collection, file }* - - -This is the default selector function - -> ```var defaultSelectorFunction = function() { ...``` [access-point-server.js:87](access-point-server.js#L87) - - -- - -### *FSHTTP*.mount(mountPoints, selector_f)  Server ### - -*This method __mount__ is defined in `FS.HTTP`* - -__Arguments__ - -* __mountPoints__ *{[array of string](#array of string)}* - - mount points to map rest functinality on - -* __selector_f__ *{function}* - - [selector] function returns `{ collection, file }` for mount points to work with - - - -> ```FS.HTTP.mount = function(mountPoints, selector_f) { ...``` [access-point-server.js:125](access-point-server.js#L125) - - -- - -### *FSHTTP*.unmount([mountPoints])  Server ### - -*This method __unmount__ is defined in `FS.HTTP`* - -__Arguments__ - -* __mountPoints__ *{[string ](#string )|[ array of string](# array of string)}* (Optional) - - Optional, if not specified all mountpoints are unmounted - - - - -> ```FS.HTTP.unmount = function(mountPoints) { ...``` [access-point-server.js:223](access-point-server.js#L223) - - - -- -### FS.Collection maps on HTTP pr. default on the following restpoints: -* -baseUrl + '/files/:collectionName/:id/:filename', -baseUrl + '/files/:collectionName/:id', -baseUrl + '/files/:collectionName' - -Change/ replace the existing mount point by: -```js -unmount all existing -FS.HTTP.unmount(); -Create new mount point -FS.HTTP.mount([ -'/cfs/files/:collectionName/:id/:filename', -'/cfs/files/:collectionName/:id', -'/cfs/files/:collectionName' -]); -``` diff --git a/packages/wekan-cfs-access-point/package.js b/packages/wekan-cfs-access-point/package.js deleted file mode 100644 index 913252e2a..000000000 --- a/packages/wekan-cfs-access-point/package.js +++ /dev/null @@ -1,65 +0,0 @@ -Package.describe({ - name: 'wekan-cfs-access-point', - version: '0.1.50', - summary: 'CollectionFS, add ddp and http accesspoint capability', - git: 'https://github.com/zcfs/Meteor-cfs-access-point.git' -}); - -Npm.depends({ - "content-disposition": "0.5.0" -}); - -Package.onUse(function(api) { - api.versionsFrom('1.0'); - - // This imply is needed for tests, and is technically probably correct anyway. - api.imply([ - 'wekan-cfs-base-package' - ]); - - api.use([ - //CFS packages - 'wekan-cfs-base-package@0.0.30', - 'wekan-cfs-file@0.1.16', - //Core packages - 'check', - 'ejson', - //Other packages - 'wekan-cfs-http-methods@0.0.29', - 'wekan-cfs-http-publish@0.0.13' - ]); - - api.addFiles([ - 'access-point-common.js', - 'access-point-handlers.js', - 'access-point-server.js' - ], 'server'); - - api.addFiles([ - 'access-point-common.js', - 'access-point-client.js' - ], 'client'); -}); - -Package.onTest(function (api) { - api.versionsFrom('1.0'); - - api.use([ - //CFS packages - 'wekan-cfs-access-point', - 'wekan-cfs-standard-packages@0.0.2', - 'wekan-cfs-gridfs@0.0.0', - //Core packages - 'test-helpers', - 'http', - 'tinytest', - 'underscore', - 'ejson', - 'ordered-dict', - 'random', - 'deps' - ]); - - api.addFiles('tests/client-tests.js', 'client'); - api.addFiles('tests/server-tests.js', 'server'); -}); diff --git a/packages/wekan-cfs-access-point/tests/client-tests.js b/packages/wekan-cfs-access-point/tests/client-tests.js deleted file mode 100644 index a0148ec17..000000000 --- a/packages/wekan-cfs-access-point/tests/client-tests.js +++ /dev/null @@ -1,125 +0,0 @@ -function equals(a, b) { - return !!(EJSON.stringify(a) === EJSON.stringify(b)); -} - -Tinytest.add('cfs-access-point - client - test environment', function(test) { - test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection'); - test.isTrue(typeof FS.HTTP !== 'undefined', 'test environment not initialized FS.HTTP'); -}); - -Images = new FS.Collection('images', { - stores: [ - new FS.Store.GridFS('gridList') - ] -}); - -Meteor.subscribe("img"); - -var id; - -Tinytest.addAsync('cfs-access-point - client - addTestImage', function(test, onComplete) { - Meteor.call('addTestImage', function(err, result) { - id = result; - test.equal(typeof id, "string", "Test image was not inserted properly"); - //Don't continue until the data has been stored - Deps.autorun(function (c) { - var img = Images.findOne(id); - if (img && img.hasCopy('gridList')) { - onComplete(); - c.stop(); - } - }); - }); -}); - -Tinytest.addAsync('cfs-access-point - client - GET list of files in collection', function(test, onComplete) { - - HTTP.get(Meteor.absoluteUrl('cfs/record/images'), function(err, result) { - // Test the length of array result - var len = result.data && result.data.length; - test.isTrue(!!len, 'Result was empty'); - // Get the object - var obj = result.data && result.data[0] || {}; - test.equal(obj._id, id, 'Didn\'t get the expected result'); - onComplete(); - }); - -}); - -Tinytest.addAsync('cfs-access-point - client - GET filerecord', function(test, onComplete) { - - HTTP.get(Meteor.absoluteUrl('cfs/record/images/' + id), function(err, result) { - // Get the object - var obj = result.data; - test.equal(typeof obj, "object", "Expected object data"); - test.equal(obj._id, id, 'Didn\'t get the expected result'); - onComplete(); - }); - -}); - -Tinytest.addAsync('cfs-access-point - client - GET file itself', function(test, onComplete) { - - HTTP.get(Meteor.absoluteUrl('cfs/files/images/' + id), function(err, result) { - test.isTrue(!!result.content, "Expected content in response"); - console.log(result); - test.equal(result.statusCode, 200, "Expected 200 OK response"); - onComplete(); - }); - -}); - -Tinytest.addAsync('cfs-access-point - client - PUT new file data (update)', function(test, onComplete) { -// TODO -// HTTP.put(Meteor.absoluteUrl('cfs/files/images/' + id), function(err, result) { -// test.equal(result.statusCode, 200, "Expected 200 OK response"); - onComplete(); -// }); - -}); - -Tinytest.addAsync('cfs-access-point - client - PUT insert a new file', function(test, onComplete) { -// TODO -// HTTP.put(Meteor.absoluteUrl('cfs/files/images'), function(err, result) { -// test.equal(result.statusCode, 200, "Expected 200 OK response"); - onComplete(); -// }); - -}); - -Tinytest.addAsync('cfs-access-point - client - DELETE filerecord and data', function(test, onComplete) { - - HTTP.del(Meteor.absoluteUrl('cfs/files/images/' + id), function(err, result) { - test.equal(result.statusCode, 200, "Expected 200 OK response"); - - // Make sure it's gone - HTTP.get(Meteor.absoluteUrl('cfs/record/images/' + id), function(err, result) { - test.isTrue(!!err, 'Expected 404 error'); - test.equal(result.statusCode, 404, "Expected 404 response"); - onComplete(); - }); - }); - -}); - -//TODO test FS.File.prototype.url method with various options - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-access-point/tests/server-tests.js b/packages/wekan-cfs-access-point/tests/server-tests.js deleted file mode 100644 index 4a23f1cb6..000000000 --- a/packages/wekan-cfs-access-point/tests/server-tests.js +++ /dev/null @@ -1,68 +0,0 @@ -function equals(a, b) { - return !!(EJSON.stringify(a) === EJSON.stringify(b)); -} - -FS.debug = true; - -Tinytest.add('cfs-access-point - server - test environment', function(test) { - test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection'); - test.isTrue(typeof FS.HTTP !== 'undefined', 'test environment not initialized FS.HTTP'); -}); - -Images = new FS.Collection('images', { - stores: [ - new FS.Store.GridFS('gridList') - ] -}); - -Images.allow({ - insert: function() { - return true; - }, - update: function() { - return true; - }, - remove: function() { - return true; - }, - download: function() { - return true; - } -}); - -Meteor.publish("img", function () { - return Images.find(); -}); - -FS.HTTP.publish(Images, function () { - return Images.find(); -}); - -Meteor.methods({ - addTestImage: function() { - Images.remove({}); - var url = "http://cdn.morguefile.com/imageData/public/files/b/bboomerindenial/preview/fldr_2009_04_01/file3301238617907.jpg"; - var fsFile = Images.insert(url); - return fsFile._id; - } -}); - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-base-package/.travis.yml b/packages/wekan-cfs-base-package/.travis.yml deleted file mode 100644 index 6a4640033..000000000 --- a/packages/wekan-cfs-base-package/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - "0.10" -before_install: - - "curl -L http://git.io/s0Zu-w | /bin/sh" \ No newline at end of file diff --git a/packages/wekan-cfs-base-package/LICENSE.md b/packages/wekan-cfs-base-package/LICENSE.md deleted file mode 100644 index 51e60c3d0..000000000 --- a/packages/wekan-cfs-base-package/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013-2015 [@raix](https://github.com/raix) and [@aldeed](https://github.com/aldeed), aka Morten N.O. Nørgaard Henriksen, mh@gi-software.com - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/wekan-cfs-base-package/README.md b/packages/wekan-cfs-base-package/README.md deleted file mode 100644 index 235ca9aa0..000000000 --- a/packages/wekan-cfs-base-package/README.md +++ /dev/null @@ -1,11 +0,0 @@ -wekan-cfs-base-package -========================= - -This is a Meteor package used by -[CollectionFS](https://github.com/zcfs/Meteor-CollectionFS). - -You don't need to manually add this package to your app. It is added when you -add the `wekan-cfs-standard-packages` package. - -This package provides the `FS` namespace and helper methods used by many -CollectionFS packages. \ No newline at end of file diff --git a/packages/wekan-cfs-base-package/api.md b/packages/wekan-cfs-base-package/api.md deleted file mode 100644 index cb7667945..000000000 --- a/packages/wekan-cfs-base-package/api.md +++ /dev/null @@ -1,213 +0,0 @@ -## cfs-base-package Public API ## - -CollectionFS, Base package - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -############################################################################# - -HELPERS - -############################################################################# -- - -### *fsUtility*.cloneFileRecord(rec, [options])  Anywhere ### - -*This method __cloneFileRecord__ is defined in `FS.Utility`* - -__Arguments__ - -* __rec__ *{[FS.File](#FS.File)|[FS.Collection filerecord](#FS.Collection filerecord)}* -* __options__ *{Object}* (Optional) - * __full__ *{Boolean}* (Optional, Default = false) - - Set `true` to prevent certain properties from being omitted from the clone. - - -__Returns__ *{Object}* -Cloned filerecord - - -Makes a shallow clone of `rec`, filtering out some properties that might be present if -it's an FS.File instance, but which we never want to be part of the stored -filerecord. - -This is a blacklist clone rather than a whitelist because we want the user to be able -to specify whatever additional properties they wish. - -In general, we expect the following whitelist properties used by the internal and -external APIs: - -_id, name, size, type, chunkCount, chunkSize, chunkSum, copies, createdAt, updatedAt, uploadedAt - -Those properties, and any additional properties added by the user, should be present -in the returned object, which is suitable for inserting into the backing collection or -extending an FS.File instance. - - -> ```FS.Utility.cloneFileRecord = function(rec, options) { ...``` [base-common.js:71](base-common.js#L71) - - -- - -### *fsUtility*.defaultCallback([err])  Anywhere ### - -*This method __defaultCallback__ is defined in `FS.Utility`* - -__Arguments__ - -* __err__ *{[Error](#Error)}* (Optional) - -__Returns__ *{undefined}* - - -Can be used as a default callback for client methods that need a callback. -Simply throws the provided error if there is one. - -> ```FS.Utility.defaultCallback = function defaultCallback(err) { ...``` [base-common.js:96](base-common.js#L96) - - -- - -### *fsUtility*.defaultCallback([f], [err])  Anywhere ### - -*This method __defaultCallback__ is defined in `FS.Utility`* - -__Arguments__ - -* __f__ *{Function}* (Optional) - - A callback function, if you have one. Can be undefined or null. - -* __err__ *{[Meteor.Error ](#Meteor.Error )|[ Error ](# Error )|[ String](# String)}* (Optional) - - Error or error message (string) - - -__Returns__ *{Any}* -the callback result if any - - -Handle Error, creates an Error instance with the given text. If callback is -a function, passes the error to that function. Otherwise throws it. Useful -for dealing with errors in methods that optionally accept a callback. - -> ```FS.Utility.handleError = function(f, err, result) { ...``` [base-common.js:120](base-common.js#L120) - - -- - -### *fsUtility*.noop()  Anywhere ### - -*This method __noop__ is defined in `FS.Utility`* - -Use this to hand a no operation / empty function - -> ```FS.Utility.noop = function() { ...``` [base-common.js:134](base-common.js#L134) - - -- - -### *fsUtility*.getFileExtension(name)  Anywhere ### - -*This method __getFileExtension__ is defined in `FS.Utility`* - -__Arguments__ - -* __name__ *{String}* - - A filename, filepath, or URL that may or may not have an extension. - - -__Returns__ *{String}* -The extension or an empty string if no extension found. - - -> ```FS.Utility.getFileExtension = function utilGetFileExtension(name) { ...``` [base-common.js:205](base-common.js#L205) - - -- - -### *fsUtility*.setFileExtension(name, ext)  Anywhere ### - -*This method __setFileExtension__ is defined in `FS.Utility`* - -__Arguments__ - -* __name__ *{String}* - - A filename that may or may not already have an extension. - -* __ext__ *{String}* - - An extension without leading period, which you want to be the new extension on `name`. - - -__Returns__ *{String}* -The filename with changed extension. - - -> ```FS.Utility.setFileExtension = function utilSetFileExtension(name, ext) { ...``` [base-common.js:222](base-common.js#L222) - - -- - -### *fsUtility*.binaryToBuffer(data)  Server ### - -*This method __binaryToBuffer__ is defined in `FS.Utility`* - -__Arguments__ - -* __data__ *{Uint8Array}* - -__Returns__ *{Buffer}* - - -Converts a Uint8Array instance to a Node Buffer instance - -> ```FS.Utility.binaryToBuffer = function(data) { ...``` [base-server.js:9](base-server.js#L9) - - -- - -### *fsUtility*.bufferToBinary(data)  Server ### - -*This method __bufferToBinary__ is defined in `FS.Utility`* - -__Arguments__ - -* __data__ *{Buffer}* - -__Returns__ *{Uint8Array}* - - -Converts a Node Buffer instance to a Uint8Array instance - -> ```FS.Utility.bufferToBinary = function(data) { ...``` [base-server.js:26](base-server.js#L26) - - -- - -### *fsUtility*.eachFile(e, f)  Client ### - -*This method __eachFile__ is defined in `FS.Utility`* - -__Arguments__ - -* __e__ *{[Event](#Event)}* - - Browser event - -* __f__ *{Function}* - - Function to run for each file found in the event. - - -__Returns__ *{undefined}* - - -Utility for iteration over files in event - -> ```FS.Utility.eachFile = function(e, f) { ...``` [base-client.js:37](base-client.js#L37) - - diff --git a/packages/wekan-cfs-base-package/base-client.js b/packages/wekan-cfs-base-package/base-client.js deleted file mode 100644 index 4d0d2ff59..000000000 --- a/packages/wekan-cfs-base-package/base-client.js +++ /dev/null @@ -1,51 +0,0 @@ - -//XXX not sure this is still working properly? -FS.Utility.connectionLogin = function(connection) { - // We check if the accounts package is installed, since we depend on - // `Meteor.userId()` - if (typeof Accounts !== 'undefined') { - // Monitor logout from main connection - Meteor.startup(function() { - Tracker.autorun(function() { - var userId = Meteor.userId(); - if (userId) { - connection.onReconnect = function() { - var token = Accounts._storedLoginToken(); - connection.apply('login', [{resume: token}], function(err, result) { - if (!err && result) { - connection.setUserId(result.id); - } - }); - }; - } else { - connection.onReconnect = null; - connection.setUserId(null); - } - }); - }); - - } -}; - -/** - * @method FS.Utility.eachFile - * @public - * @param {Event} e - Browser event - * @param {Function} f - Function to run for each file found in the event. - * @returns {undefined} - * - * Utility for iteration over files in event - */ -FS.Utility.eachFile = function(e, f) { - var evt = (e.originalEvent || e); - - var files = evt.target.files; - - if (!files || files.length === 0) { - files = evt.dataTransfer ? evt.dataTransfer.files : []; - } - - for (var i = 0; i < files.length; i++) { - f(files[i], i); - } -}; diff --git a/packages/wekan-cfs-base-package/base-common.js b/packages/wekan-cfs-base-package/base-common.js deleted file mode 100644 index 082621e7b..000000000 --- a/packages/wekan-cfs-base-package/base-common.js +++ /dev/null @@ -1,317 +0,0 @@ -// Exported namespace -FS = {}; - -// namespace for adapters; XXX should this be added by cfs-storage-adapter pkg instead? -FS.Store = { - GridFS: function () { - throw new Error('To use FS.Store.GridFS, you must add the "wekan-cfs-gridfs" package.'); - }, - FileSystem: function () { - throw new Error('To use FS.Store.FileSystem, you must add the "wekan-cfs-filesystem" package.'); - }, - S3: function () { - throw new Error('To use FS.Store.S3, you must add the "wekan-cfs-s3" package.'); - }, - WABS: function () { - throw new Error('To use FS.Store.WABS, you must add the "wekan-cfs-wabs" package.'); - }, - Dropbox: function () { - throw new Error('To use FS.Store.Dropbox, you must add the "wekan-cfs-dropbox" package.'); - } -}; - -// namespace for access points -FS.AccessPoint = {}; - -// namespace for utillities -FS.Utility = {}; - -// A general place for any package to store global config settings -FS.config = {}; - -// An internal collection reference -FS._collections = {}; - -// Test scope -_Utility = {}; - -// ############################################################################# -// -// HELPERS -// -// ############################################################################# - -/** @method _Utility.defaultZero - * @private - * @param {Any} val Returns number or 0 if value is a falsy - */ -_Utility.defaultZero = function(val) { - return +(val || 0); -}; - -/** - * @method FS.Utility.cloneFileRecord - * @public - * @param {FS.File|FS.Collection filerecord} rec - * @param {Object} [options] - * @param {Boolean} [options.full=false] Set `true` to prevent certain properties from being omitted from the clone. - * @returns {Object} Cloned filerecord - * - * Makes a shallow clone of `rec`, filtering out some properties that might be present if - * it's an FS.File instance, but which we never want to be part of the stored - * filerecord. - * - * This is a blacklist clone rather than a whitelist because we want the user to be able - * to specify whatever additional properties they wish. - * - * In general, we expect the following whitelist properties used by the internal and - * external APIs: - * - * _id, name, size, type, chunkCount, chunkSize, chunkSum, copies, createdAt, updatedAt, uploadedAt - * - * Those properties, and any additional properties added by the user, should be present - * in the returned object, which is suitable for inserting into the backing collection or - * extending an FS.File instance. - * - */ -FS.Utility.cloneFileRecord = function(rec, options) { - options = options || {}; - var result = {}; - // We use this method for two purposes. If using it to clone one FS.File into another, then - // we want a full clone. But if using it to get a filerecord object for inserting into the - // internal collection, then there are certain properties we want to omit so that they aren't - // stored in the collection. - var omit = options.full ? [] : ['collectionName', 'collection', 'data', 'createdByTransform']; - for (var prop in rec) { - if (rec.hasOwnProperty(prop) && !_.contains(omit, prop)) { - result[prop] = rec[prop]; - } - } - return result; -}; - -/** - * @method FS.Utility.defaultCallback - * @public - * @param {Error} [err] - * @returns {undefined} - * - * Can be used as a default callback for client methods that need a callback. - * Simply throws the provided error if there is one. - */ -FS.Utility.defaultCallback = function defaultCallback(err) { - if (err) { - // Show gentle error if Meteor error - if (err instanceof Meteor.Error) { - console.error(err.message); - } else { - // Normal error, just throw error - throw err; - } - - } -}; - -/** - * @method FS.Utility.defaultCallback - * @public - * @param {Function} [f] A callback function, if you have one. Can be undefined or null. - * @param {Meteor.Error | Error | String} [err] Error or error message (string) - * @returns {Any} the callback result if any - * - * Handle Error, creates an Error instance with the given text. If callback is - * a function, passes the error to that function. Otherwise throws it. Useful - * for dealing with errors in methods that optionally accept a callback. - */ -FS.Utility.handleError = function(f, err, result) { - // Set callback - var callback = (typeof f === 'function')? f : FS.Utility.defaultCallback; - // Set the err - var error = (err === ''+err)? new Error(err) : err; - // callback - return callback(error, result); -} - -/** - * @method FS.Utility.noop - * @public - * Use this to hand a no operation / empty function - */ -FS.Utility.noop = function() {}; - -/** - * @method validateAction - * @private - * @param {Object} validators - The validators object to use, with `deny` and `allow` properties. - * @param {FS.File} fileObj - Mounted or mountable file object to be passed to validators. - * @param {String} userId - The ID of the user who is attempting the action. - * @returns {undefined} - * - * Throws a "400-Bad Request" Meteor error if the file is not mounted or - * a "400-Access denied" Meteor error if the action is not allowed. - */ -FS.Utility.validateAction = function validateAction(validators, fileObj, userId) { - var denyValidators = validators.deny; - var allowValidators = validators.allow; - - // If insecure package is used and there are no validators defined, - // allow the action. - if (typeof Package === 'object' - && Package.insecure - && denyValidators.length + allowValidators.length === 0) { - return; - } - - // If already mounted, validators should receive a fileObj - // that is fully populated - if (fileObj.isMounted()) { - fileObj.getFileRecord(); - } - - // Any deny returns true means denied. - if (_.any(denyValidators, function(validator) { - return validator(userId, fileObj); - })) { - throw new Meteor.Error(403, "Access denied"); - } - // Any allow returns true means proceed. Throw error if they all fail. - if (_.all(allowValidators, function(validator) { - return !validator(userId, fileObj); - })) { - throw new Meteor.Error(403, "Access denied"); - } -}; - -/** - * @method FS.Utility.getFileName - * @private - * @param {String} name - A filename, filepath, or URL - * @returns {String} The filename without the URL, filepath, or query string - */ -FS.Utility.getFileName = function utilGetFileName(name) { - // in case it's a URL, strip off potential query string - // should have no effect on filepath - name = name.split('?')[0]; - // strip off beginning path or url - var lastSlash = name.lastIndexOf('/'); - if (lastSlash !== -1) { - name = name.slice(lastSlash + 1); - } - return name; -}; - -/** - * @method FS.Utility.getFileExtension - * @public - * @param {String} name - A filename, filepath, or URL that may or may not have an extension. - * @returns {String} The extension or an empty string if no extension found. - */ -FS.Utility.getFileExtension = function utilGetFileExtension(name) { - name = FS.Utility.getFileName(name); - // Seekout the last '.' if found - var found = name.lastIndexOf('.'); - // Return the extension if found else '' - // If found is -1, we return '' because there is no extension - // If found is 0, we return '' because it's a hidden file - return (found > 0 ? name.slice(found + 1).toLowerCase() : ''); -}; - -/** - * @method FS.Utility.setFileExtension - * @public - * @param {String} name - A filename that may or may not already have an extension. - * @param {String} ext - An extension without leading period, which you want to be the new extension on `name`. - * @returns {String} The filename with changed extension. - */ -FS.Utility.setFileExtension = function utilSetFileExtension(name, ext) { - if (!name || !name.length) { - return name; - } - var currentExt = FS.Utility.getFileExtension(name); - if (currentExt.length) { - name = name.slice(0, currentExt.length * -1) + ext; - } else { - name = name + '.' + ext; - } - return name; -}; - -/* - * Borrowed these from http package - */ -FS.Utility.encodeParams = function encodeParams(params) { - var buf = []; - _.each(params, function(value, key) { - if (buf.length) - buf.push('&'); - buf.push(FS.Utility.encodeString(key), '=', FS.Utility.encodeString(value)); - }); - return buf.join('').replace(/%20/g, '+'); -}; - -FS.Utility.encodeString = function encodeString(str) { - return encodeURIComponent(str).replace(/[!'()]/g, escape).replace(/\*/g, "%2A"); -}; - -/* - * btoa and atob shims for client and server - */ - -FS.Utility._btoa = function _fsUtility_btoa(str) { - var buffer; - - if (str instanceof Buffer) { - buffer = str; - } else { - buffer = new Buffer(str.toString(), 'binary'); - } - - return buffer.toString('base64'); -}; - -FS.Utility.btoa = function fsUtility_btoa(str) { - if (typeof btoa === 'function') { - // Client - return btoa(str); - } else if (typeof Buffer !== 'undefined') { - // Server - return FS.Utility._btoa(str); - } else { - throw new Error('FS.Utility.btoa: Cannot base64 encode on your system'); - } -}; - -FS.Utility._atob = function _fsUtility_atob(str) { - return new Buffer(str, 'base64').toString('binary'); -}; - -FS.Utility.atob = function fsUtility_atob(str) { - if (typeof atob === 'function') { - // Client - return atob(str); - } else if (typeof Buffer !== 'undefined') { - // Server - return FS.Utility._atob(str); - } else { - throw new Error('FS.Utility.atob: Cannot base64 encode on your system'); - } -}; - -// Api wrap for 3party libs like underscore -FS.Utility.extend = _.extend; - -FS.Utility.each = _.each; - -FS.Utility.isEmpty = _.isEmpty; - -FS.Utility.indexOf = _.indexOf; - -FS.Utility.isArray = _.isArray; - -FS.Utility.map = _.map; - -FS.Utility.once = _.once; - -FS.Utility.include = _.include; - -FS.Utility.size = _.size; diff --git a/packages/wekan-cfs-base-package/base-server.js b/packages/wekan-cfs-base-package/base-server.js deleted file mode 100644 index 7b9309b7d..000000000 --- a/packages/wekan-cfs-base-package/base-server.js +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @method FS.Utility.binaryToBuffer - * @public - * @param {Uint8Array} data - * @returns {Buffer} - * - * Converts a Uint8Array instance to a Node Buffer instance - */ -FS.Utility.binaryToBuffer = function(data) { - var len = data.length; - var buffer = new Buffer(len); - for (var i = 0; i < len; i++) { - buffer[i] = data[i]; - } - return buffer; -}; - -/** - * @method FS.Utility.bufferToBinary - * @public - * @param {Buffer} data - * @returns {Uint8Array} - * - * Converts a Node Buffer instance to a Uint8Array instance - */ -FS.Utility.bufferToBinary = function(data) { - var len = data.length; - var binary = EJSON.newBinary(len); - for (var i = 0; i < len; i++) { - binary[i] = data[i]; - } - return binary; -}; - -/** - * @method FS.Utility.safeCallback - * @public - * @param {Function} callback - * @returns {Function} - * - * Makes a callback safe for Meteor code - */ -FS.Utility.safeCallback = function (callback) { - return Meteor.bindEnvironment(callback, function(err) { throw err; }); -}; - -/** - * @method FS.Utility.safeStream - * @public - * @param {Stream} nodestream - * @returns {Stream} - * - * Adds `safeOn` and `safeOnce` methods to a NodeJS Stream - * object. These are the same as `on` and `once`, except - * that the callback is wrapped for use in Meteor. - */ -FS.Utility.safeStream = function(nodestream) { - if (!nodestream || typeof nodestream.on !== 'function') - throw new Error('FS.Utility.safeStream requires a NodeJS Stream'); - - // Create Meteor safe events - nodestream.safeOn = function(name, callback) { - return nodestream.on(name, FS.Utility.safeCallback(callback)); - }; - - // Create Meteor safe events - nodestream.safeOnce = function(name, callback) { - return nodestream.once(name, FS.Utility.safeCallback(callback)); - }; - - // Return the modified stream - modified anyway - return nodestream; -}; - -/** - * @method FS.Utility.eachFileFromPath - * @public - * @param {String} p - Server path - * @param {Function} f - Function to run for each file found in the path. - * @returns {undefined} - * - * Utility for iteration over files from path on server - */ -FS.Utility.eachFileFromPath = function(p, f) { - var fs = Npm.require('fs'); - var path = Npm.require('path'); - var files = fs.readdirSync(p); - files.map(function (file) { - return path.join(p, file); - }).filter(function (filePath) { - return fs.statSync(filePath).isFile() && path.basename(filePath)[0] !== '.'; - }).forEach(function (filePath) { - f(filePath); - }); -}; diff --git a/packages/wekan-cfs-base-package/internal.api.md b/packages/wekan-cfs-base-package/internal.api.md deleted file mode 100644 index 559c4e7a9..000000000 --- a/packages/wekan-cfs-base-package/internal.api.md +++ /dev/null @@ -1,293 +0,0 @@ -## Public and Private API ## - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -*** - -__File: ["base-common.js"](base-common.js) Where: {server|client}__ - -*** - -############################################################################# - -HELPERS - -############################################################################# -- - -### *_utility*.defaultZero(val)  Anywhere ### - -*This method is private* -*This method __defaultZero__ is defined in `_Utility`* - -__Arguments__ - -* __val__ *{Any}* - - Returns number or 0 if value is a falsy - - -> ```_Utility.defaultZero = function(val) { ...``` [base-common.js:42](base-common.js#L42) - - -- - -### *fsUtility*.cloneFileRecord(rec, [options])  Anywhere ### - -*This method __cloneFileRecord__ is defined in `FS.Utility`* - -__Arguments__ - -* __rec__ *{[FS.File](#FS.File)|[FS.Collection filerecord](#FS.Collection filerecord)}* -* __options__ *{Object}* (Optional) - * __full__ *{Boolean}* (Optional, Default = false) - - Set `true` to prevent certain properties from being omitted from the clone. - - -__Returns__ *{Object}* -Cloned filerecord - - -Makes a shallow clone of `rec`, filtering out some properties that might be present if -it's an FS.File instance, but which we never want to be part of the stored -filerecord. - -This is a blacklist clone rather than a whitelist because we want the user to be able -to specify whatever additional properties they wish. - -In general, we expect the following whitelist properties used by the internal and -external APIs: - -_id, name, size, type, chunkCount, chunkSize, chunkSum, copies, createdAt, updatedAt, uploadedAt - -Those properties, and any additional properties added by the user, should be present -in the returned object, which is suitable for inserting into the backing collection or -extending an FS.File instance. - - -> ```FS.Utility.cloneFileRecord = function(rec, options) { ...``` [base-common.js:71](base-common.js#L71) - - -- - -### *fsUtility*.defaultCallback([err])  Anywhere ### - -*This method __defaultCallback__ is defined in `FS.Utility`* - -__Arguments__ - -* __err__ *{[Error](#Error)}* (Optional) - -__Returns__ *{undefined}* - - -Can be used as a default callback for client methods that need a callback. -Simply throws the provided error if there is one. - -> ```FS.Utility.defaultCallback = function defaultCallback(err) { ...``` [base-common.js:96](base-common.js#L96) - - -- - -### *fsUtility*.defaultCallback([f], [err])  Anywhere ### - -*This method __defaultCallback__ is defined in `FS.Utility`* - -__Arguments__ - -* __f__ *{Function}* (Optional) - - A callback function, if you have one. Can be undefined or null. - -* __err__ *{[Meteor.Error ](#Meteor.Error )|[ Error ](# Error )|[ String](# String)}* (Optional) - - Error or error message (string) - - -__Returns__ *{Any}* -the callback result if any - - -Handle Error, creates an Error instance with the given text. If callback is -a function, passes the error to that function. Otherwise throws it. Useful -for dealing with errors in methods that optionally accept a callback. - -> ```FS.Utility.handleError = function(f, err, result) { ...``` [base-common.js:120](base-common.js#L120) - - -- - -### *fsUtility*.noop()  Anywhere ### - -*This method __noop__ is defined in `FS.Utility`* - -Use this to hand a no operation / empty function - -> ```FS.Utility.noop = function() { ...``` [base-common.js:134](base-common.js#L134) - - -- - -### validateAction(validators, fileObj, userId)  Anywhere ### - -*This method is private* - -__Arguments__ - -* __validators__ *{Object}* - - The validators object to use, with `deny` and `allow` properties. - -* __fileObj__ *{[FS.File](#FS.File)}* - - Mounted or mountable file object to be passed to validators. - -* __userId__ *{String}* - - The ID of the user who is attempting the action. - - -__Returns__ *{undefined}* - - -Throws a "400-Bad Request" Meteor error if the file is not mounted or -a "400-Access denied" Meteor error if the action is not allowed. - -> ```FS.Utility.validateAction = function validateAction(validators, fileObj, userId) { ...``` [base-common.js:147](base-common.js#L147) - - -- - -### *fsUtility*.getFileName(name)  Anywhere ### - -*This method is private* -*This method __getFileName__ is defined in `FS.Utility`* - -__Arguments__ - -* __name__ *{String}* - - A filename, filepath, or URL - - -__Returns__ *{String}* -The filename without the URL, filepath, or query string - - -> ```FS.Utility.getFileName = function utilGetFileName(name) { ...``` [base-common.js:187](base-common.js#L187) - - -- - -### *fsUtility*.getFileExtension(name)  Anywhere ### - -*This method __getFileExtension__ is defined in `FS.Utility`* - -__Arguments__ - -* __name__ *{String}* - - A filename, filepath, or URL that may or may not have an extension. - - -__Returns__ *{String}* -The extension or an empty string if no extension found. - - -> ```FS.Utility.getFileExtension = function utilGetFileExtension(name) { ...``` [base-common.js:205](base-common.js#L205) - - -- - -### *fsUtility*.setFileExtension(name, ext)  Anywhere ### - -*This method __setFileExtension__ is defined in `FS.Utility`* - -__Arguments__ - -* __name__ *{String}* - - A filename that may or may not already have an extension. - -* __ext__ *{String}* - - An extension without leading period, which you want to be the new extension on `name`. - - -__Returns__ *{String}* -The filename with changed extension. - - -> ```FS.Utility.setFileExtension = function utilSetFileExtension(name, ext) { ...``` [base-common.js:222](base-common.js#L222) - - -*** - -__File: ["base-server.js"](base-server.js) Where: {server}__ - -*** - -### *fsUtility*.binaryToBuffer(data)  Server ### - -*This method __binaryToBuffer__ is defined in `FS.Utility`* - -__Arguments__ - -* __data__ *{Uint8Array}* - -__Returns__ *{Buffer}* - - -Converts a Uint8Array instance to a Node Buffer instance - -> ```FS.Utility.binaryToBuffer = function(data) { ...``` [base-server.js:9](base-server.js#L9) - - -- - -### *fsUtility*.bufferToBinary(data)  Server ### - -*This method __bufferToBinary__ is defined in `FS.Utility`* - -__Arguments__ - -* __data__ *{Buffer}* - -__Returns__ *{Uint8Array}* - - -Converts a Node Buffer instance to a Uint8Array instance - -> ```FS.Utility.bufferToBinary = function(data) { ...``` [base-server.js:26](base-server.js#L26) - - -*** - -__File: ["base-client.js"](base-client.js) Where: {client}__ - -*** - -### *fsUtility*.eachFile(e, f)  Client ### - -*This method __eachFile__ is defined in `FS.Utility`* - -__Arguments__ - -* __e__ *{[Event](#Event)}* - - Browser event - -* __f__ *{Function}* - - Function to run for each file found in the event. - - -__Returns__ *{undefined}* - - -Utility for iteration over files in event - -> ```FS.Utility.eachFile = function(e, f) { ...``` [base-client.js:37](base-client.js#L37) - - diff --git a/packages/wekan-cfs-base-package/package.js b/packages/wekan-cfs-base-package/package.js deleted file mode 100644 index 82b3f712c..000000000 --- a/packages/wekan-cfs-base-package/package.js +++ /dev/null @@ -1,37 +0,0 @@ -Package.describe({ - version: '0.0.30', - name: 'wekan-cfs-base-package', - summary: 'CollectionFS, Base package', - git: 'https://github.com/zcfs/Meteor-cfs-base-package.git' -}); - -Package.onUse(function(api) { - api.versionsFrom('1.0'); - - api.use(['deps', 'underscore', 'ejson']); - - if (api.export) { - api.export('FS'); - api.export('_Utility', { testOnly: true }); - } - - api.addFiles([ - 'base-common.js', - 'base-server.js' - ], 'server'); - - api.addFiles([ - 'polyfill.base64.js', - 'base-common.js', - 'base-client.js' - ], 'client'); -}); - -// Package.on_test(function (api) { -// api.use(['wekan-cfs-base-package', 'cfs-file']); -// api.use('test-helpers', 'server'); -// api.use(['tinytest', 'underscore', 'ejson', 'ordered-dict', -// 'random', 'deps']); - -// api.add_files('tests/common-tests.js', ['client', 'server']); -// }); diff --git a/packages/wekan-cfs-base-package/polyfill.base64.js b/packages/wekan-cfs-base-package/polyfill.base64.js deleted file mode 100644 index 14bf52f75..000000000 --- a/packages/wekan-cfs-base-package/polyfill.base64.js +++ /dev/null @@ -1,179 +0,0 @@ -/* - * Copyright (c) 2010 Nick Galbreath - * http://code.google.com/p/stringencoders/source/browse/#svn/trunk/javascript - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, - * copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following - * conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES - * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT - * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - */ - -/* base64 encode/decode compatible with window.btoa/atob - * - * window.atob/btoa is a Firefox extension to convert binary data (the "b") - * to base64 (ascii, the "a"). - * - * It is also found in Safari and Chrome. It is not available in IE. - * - * if (!window.btoa) window.btoa = base64.encode - * if (!window.atob) window.atob = base64.decode - * - * The original spec's for atob/btoa are a bit lacking - * https://developer.mozilla.org/en/DOM/window.atob - * https://developer.mozilla.org/en/DOM/window.btoa - * - * window.btoa and base64.encode takes a string where charCodeAt is [0,255] - * If any character is not [0,255], then an DOMException(5) is thrown. - * - * window.atob and base64.decode take a base64-encoded string - * If the input length is not a multiple of 4, or contains invalid characters - * then an DOMException(5) is thrown. - */ -var base64 = {}; -base64.PADCHAR = '='; -base64.ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; - -base64.makeDOMException = function() { - // sadly in FF,Safari,Chrome you can't make a DOMException - var e, tmp; - - try { - return new DOMException(DOMException.INVALID_CHARACTER_ERR); - } catch (tmp) { - // not available, just passback a duck-typed equiv - // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Error - // https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Error/prototype - var ex = new Error("DOM Exception 5"); - - // ex.number and ex.description is IE-specific. - ex.code = ex.number = 5; - ex.name = ex.description = "INVALID_CHARACTER_ERR"; - - // Safari/Chrome output format - ex.toString = function() { return 'Error: ' + ex.name + ': ' + ex.message; }; - return ex; - } -} - -base64.getbyte64 = function(s,i) { - // This is oddly fast, except on Chrome/V8. - // Minimal or no improvement in performance by using a - // object with properties mapping chars to value (eg. 'A': 0) - var idx = base64.ALPHA.indexOf(s.charAt(i)); - if (idx === -1) { - throw base64.makeDOMException(); - } - return idx; -} - -base64.decode = function(s) { - // convert to string - s = '' + s; - var getbyte64 = base64.getbyte64; - var pads, i, b10; - var imax = s.length - if (imax === 0) { - return s; - } - - if (imax % 4 !== 0) { - throw base64.makeDOMException(); - } - - pads = 0 - if (s.charAt(imax - 1) === base64.PADCHAR) { - pads = 1; - if (s.charAt(imax - 2) === base64.PADCHAR) { - pads = 2; - } - // either way, we want to ignore this last block - imax -= 4; - } - - var x = []; - for (i = 0; i < imax; i += 4) { - b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12) | - (getbyte64(s,i+2) << 6) | getbyte64(s,i+3); - x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 0xff, b10 & 0xff)); - } - - switch (pads) { - case 1: - b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12) | (getbyte64(s,i+2) << 6); - x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 0xff)); - break; - case 2: - b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12); - x.push(String.fromCharCode(b10 >> 16)); - break; - } - return x.join(''); -} - -base64.getbyte = function(s,i) { - var x = s.charCodeAt(i); - if (x > 255) { - throw base64.makeDOMException(); - } - return x; -} - -base64.encode = function(s) { - if (arguments.length !== 1) { - throw new SyntaxError("Not enough arguments"); - } - var padchar = base64.PADCHAR; - var alpha = base64.ALPHA; - var getbyte = base64.getbyte; - - var i, b10; - var x = []; - - // convert to string - s = '' + s; - - var imax = s.length - s.length % 3; - - if (s.length === 0) { - return s; - } - for (i = 0; i < imax; i += 3) { - b10 = (getbyte(s,i) << 16) | (getbyte(s,i+1) << 8) | getbyte(s,i+2); - x.push(alpha.charAt(b10 >> 18)); - x.push(alpha.charAt((b10 >> 12) & 0x3F)); - x.push(alpha.charAt((b10 >> 6) & 0x3f)); - x.push(alpha.charAt(b10 & 0x3f)); - } - switch (s.length - imax) { - case 1: - b10 = getbyte(s,i) << 16; - x.push(alpha.charAt(b10 >> 18) + alpha.charAt((b10 >> 12) & 0x3F) + - padchar + padchar); - break; - case 2: - b10 = (getbyte(s,i) << 16) | (getbyte(s,i+1) << 8); - x.push(alpha.charAt(b10 >> 18) + alpha.charAt((b10 >> 12) & 0x3F) + - alpha.charAt((b10 >> 6) & 0x3f) + padchar); - break; - } - return x.join(''); -} - -if (!window.btoa) window.btoa = base64.encode -if (!window.atob) window.atob = base64.decode \ No newline at end of file diff --git a/packages/wekan-cfs-base-package/tests/common-tests.js b/packages/wekan-cfs-base-package/tests/common-tests.js deleted file mode 100644 index 310d3b66b..000000000 --- a/packages/wekan-cfs-base-package/tests/common-tests.js +++ /dev/null @@ -1,161 +0,0 @@ -function equals(a, b) { - return EJSON.stringify(a) === EJSON.stringify(b); -} - -Tinytest.add('cfs-base-package - test environment', function(test) { - test.isTrue(typeof FS !== 'undefined', - 'FS scope not declared'); - - test.isTrue(typeof FS.Store !== 'undefined', - 'FS scope "FS.Store" not declared'); - - test.isTrue(typeof FS.AccessPoint !== 'undefined', - 'FS scope "FS.AccessPoint" not declared'); - - test.isTrue(typeof FS.Utility !== 'undefined', - 'FS scope "FS.Utility" not declared'); - - test.isTrue(typeof FS._collections !== 'undefined', - 'FS scope "FS._collections" not declared'); - - test.isTrue(typeof _Utility !== 'undefined', - '_Utility test scope not declared'); -}); - -Tinytest.add('cfs-base-package - _Utility.defaultZero', function(test) { - test.equal(_Utility.defaultZero(), 0, 'Failes to return 0 when (undefined)'); - test.equal(_Utility.defaultZero(undefined), 0, 'Failes to return 0 when undefined'); - test.equal(_Utility.defaultZero(null), 0, 'Failes to return 0 when null'); - test.equal(_Utility.defaultZero(false), 0, 'Failes to return 0 when false'); - test.equal(_Utility.defaultZero(0), 0, 'Failes to return 0 when 0'); - test.equal(_Utility.defaultZero(-1), -1, 'Failes to return -1'); - test.equal(_Utility.defaultZero(1), 1, 'Failes to return 1'); - test.equal(_Utility.defaultZero(-0.1), -0.1, 'Failes to return -0.1'); - test.equal(_Utility.defaultZero(0.1), 0.1, 'Failes to return 0.1'); - test.equal(_Utility.defaultZero(''), 0, 'Failes to return ""'); - test.equal(_Utility.defaultZero({}), NaN, 'Failes to return NaN when object'); - test.equal(_Utility.defaultZero("dfdsfs"), NaN, 'Failes to return NaN when string'); - test.equal(_Utility.defaultZero("1"), 1, 'Failes to return 1 when string "1"'); -}); - -Tinytest.add('cfs-base-package - FS.Utility.cloneFileRecord', function(test) { - // Given an object with any props, should filter out 'collectionName', - // 'collection', 'data', and 'createdByTransform' - var result = FS.Utility.cloneFileRecord({a: 1, b: {c: 1}, d: [1, 2], collectionName: 'test', collection: {}, data: {}, createdByTransform: false}); - test.equal(result, {a: 1, b: {c: 1}, d: [1, 2]}); - - // Given an FS.File instance, should filter out 'collectionName', - // 'collection', 'data', and 'createdByTransform' and return a plain Object - var fileObj = new FS.File({a: 1, b: {c: 1}, d: [1, 2], name: 'name.png', type: 'image/png', size: 100, collectionName: 'test', collection: {}, data: {}, createdByTransform: false}); - test.isTrue(fileObj instanceof FS.File); - var result = FS.Utility.cloneFileRecord(fileObj); - test.isFalse(result instanceof FS.File); - test.isTrue(equals(result, {a: 1, b: {c: 1}, d: [1, 2], name: 'name.png', type: 'image/png', size: 100})); -}); - -Tinytest.add('cfs-base-package - FS.Utility.defaultCallback', function(test) { - // should throw an error passed in, but not a Meteor.Error - test.throws(function () { - var cb = FS.Utility.defaultCallback; - cb(new Error('test')); - }); - - var cb2 = FS.Utility.defaultCallback; - test.isUndefined(cb2(new Meteor.Error('test'))); -}); - -Tinytest.add('cfs-base-package - FS.Utility.handleError', function(test) { - test.isTrue(true); - // TODO -}); - -Tinytest.add('cfs-base-package - FS.Utility.binaryToBuffer', function(test) { - test.isTrue(true); - // TODO -}); - -Tinytest.add('cfs-base-package - FS.Utility.bufferToBinary', function(test) { - test.isTrue(true); - // TODO -}); - -Tinytest.add('cfs-base-package - FS.Utility.connectionLogin', function(test) { - test.isTrue(true); - // TODO -}); - -Tinytest.add('cfs-base-package - FS.Utility.getFileName', function(test) { - - function t(input, expected) { - var ext = FS.Utility.getFileName(input); - test.equal(ext, expected, 'Got incorrect filename'); - } - - t('bar.png', 'bar.png'); - t('foo/bar.png', 'bar.png'); - t('/foo/foo/bar.png', 'bar.png'); - t('http://foobar.com/file.png', 'file.png'); - t('http://foobar.com/file', 'file'); - t('http://foobar.com/file.png?a=b', 'file.png'); - t('http://foobar.com/.file?a=b', '.file'); - t('file', 'file'); - t('.file', '.file'); - t('foo/.file', '.file'); - t('/foo/foo/.file', '.file'); -}); - -Tinytest.add('cfs-base-package - FS.Utility.getFileExtension', function(test) { - - function t(input, expected) { - var ext = FS.Utility.getFileExtension(input); - test.equal(ext, expected, 'Got incorrect extension'); - } - - t('bar.png', 'png'); - t('foo/bar.png', 'png'); - t('/foo/foo/bar.png', 'png'); - t('http://foobar.com/file.png', 'png'); - t('http://foobar.com/file', ''); - t('http://foobar.com/file.png?a=b', 'png'); - t('http://foobar.com/file?a=b', ''); - t('file', ''); - t('.file', ''); - t('foo/.file', ''); - t('/foo/foo/.file', ''); -}); - -Tinytest.add('cfs-base-package - FS.Utility.setFileExtension', function(test) { - - function t(name, ext, expected) { - var newName = FS.Utility.setFileExtension(name, ext); - test.equal(newName, expected, 'Extension was not set correctly'); - } - - t('bar.png', 'jpeg', 'bar.jpeg'); - t('bar', 'jpeg', 'bar.jpeg'); - t('.bar', 'jpeg', '.bar.jpeg'); - t('', 'jpeg', ''); - t(null, 'jpeg', null); -}); - -//Test API: -//Tinytest.add('', function(test) {}); -//Tinytest.addAsync('', function(test, onComplete) {}); -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-collection-filters/.travis.yml b/packages/wekan-cfs-collection-filters/.travis.yml deleted file mode 100644 index 6a4640033..000000000 --- a/packages/wekan-cfs-collection-filters/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - "0.10" -before_install: - - "curl -L http://git.io/s0Zu-w | /bin/sh" \ No newline at end of file diff --git a/packages/wekan-cfs-collection-filters/LICENSE.md b/packages/wekan-cfs-collection-filters/LICENSE.md deleted file mode 100644 index b8d7fab60..000000000 --- a/packages/wekan-cfs-collection-filters/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013-2014 [@raix](https://github.com/raix) and [@aldeed](https://github.com/aldeed), aka Morten N.O. Nørgaard Henriksen, mh@gi-software.com - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/wekan-cfs-collection-filters/README.md b/packages/wekan-cfs-collection-filters/README.md deleted file mode 100644 index bf86e25e3..000000000 --- a/packages/wekan-cfs-collection-filters/README.md +++ /dev/null @@ -1,8 +0,0 @@ -wekan-cfs-collection-filters -========================= - -This is a Meteor package used by -[CollectionFS](https://github.com/zcfs/Meteor-CollectionFS). - -You don't need to manually add this package to your app. It is added when you -add the `wekan-cfs-standard-packages` package. \ No newline at end of file diff --git a/packages/wekan-cfs-collection-filters/api.md b/packages/wekan-cfs-collection-filters/api.md deleted file mode 100644 index 2013ed0a5..000000000 --- a/packages/wekan-cfs-collection-filters/api.md +++ /dev/null @@ -1,44 +0,0 @@ -## cfs-collection-filters Public API ## - -CollectionFS, adds FS.Collection filters - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -- - -### *fsCollection*.filters(filters)  Anywhere ### - -*This method __filters__ is defined in `prototype` of `FS.Collection`* - -__Arguments__ - -* __filters__ *{Object}* - - File filters for this collection. - - -__Returns__ *{undefined}* - - -> ```FS.Collection.prototype.filters = function fsColFilters(filters) { ...``` [filters.js:7](filters.js#L7) - - -- - -### *fsCollection*.allowsFile()  Anywhere ### - -*This method __allowsFile__ is defined in `prototype` of `FS.Collection`* - -__Returns__ *{boolean}* -True if the collection allows this file. - - -Checks based on any filters defined on the collection. If the -file is not valid according to the filters, this method returns false -and also calls the filter `onInvalid` method defined for the -collection, passing it an English error string that explains why it -failed. - -> ```FS.Collection.prototype.allowsFile = function fsColAllowsFile(fileObj) { ...``` [filters.js:108](filters.js#L108) - - diff --git a/packages/wekan-cfs-collection-filters/filters.js b/packages/wekan-cfs-collection-filters/filters.js deleted file mode 100644 index 52bae78a6..000000000 --- a/packages/wekan-cfs-collection-filters/filters.js +++ /dev/null @@ -1,191 +0,0 @@ -/** - * @method FS.Collection.prototype.filters - * @public - * @param {Object} filters - File filters for this collection. - * @returns {undefined} - */ -FS.Collection.prototype.filters = function fsColFilters(filters) { - var self = this; - - // Check filter option values and normalize them for quicker checking later - if (filters) { - // check/adjust allow/deny - FS.Utility.each(['allow', 'deny'], function (type) { - if (!filters[type]) { - filters[type] = {}; - } else if (typeof filters[type] !== "object") { - throw new Error(type + ' filter must be an object'); - } - }); - - // check/adjust maxSize - if (typeof filters.maxSize === "undefined") { - filters.maxSize = null; - } else if (filters.maxSize && typeof filters.maxSize !== "number") { - throw new Error('maxSize filter must be an number'); - } - - // check/adjust extensions - FS.Utility.each(['allow', 'deny'], function (type) { - if (!filters[type].extensions) { - filters[type].extensions = []; - } else if (!FS.Utility.isArray(filters[type].extensions)) { - throw new Error(type + '.extensions filter must be an array of extensions'); - } else { - //convert all to lowercase - for (var i = 0, ln = filters[type].extensions.length; i < ln; i++) { - filters[type].extensions[i] = filters[type].extensions[i].toLowerCase(); - } - } - }); - - // check/adjust content types - FS.Utility.each(['allow', 'deny'], function (type) { - if (!filters[type].contentTypes) { - filters[type].contentTypes = []; - } else if (!FS.Utility.isArray(filters[type].contentTypes)) { - throw new Error(type + '.contentTypes filter must be an array of content types'); - } - }); - - self.options.filter = filters; - } - - // Define deny functions to enforce file filters on the server - // for inserts and updates that initiate from untrusted code. - self.files.deny({ - insert: function(userId, fsFile) { - return !self.allowsFile(fsFile); - }, - update: function(userId, fsFile, fields, modifier) { - // TODO will need some kind of additional security here: - // Don't allow them to change the type, size, name, and - // anything else that would be security or data integrity issue. - // Such security should probably be added by cfs-collection package, not here. - return !self.allowsFile(fsFile); - }, - fetch: [] - }); - - // If insecure package is in use, we need to add allow rules that return - // true. Otherwise, it would seemingly turn off insecure mode. - if (Package && Package.insecure) { - self.allow({ - insert: function() { - return true; - }, - update: function() { - return true; - }, - remove: function() { - return true; - }, - download: function() { - return true; - }, - fetch: [], - transform: null - }); - } - // If insecure package is NOT in use, then adding the deny function - // does not have any effect on the main app's security paradigm. The - // user will still be required to add at least one allow function of her - // own for each operation for this collection. And the user may still add - // additional deny functions, but does not have to. -}; - -/** - * @method FS.Collection.prototype.allowsFile Does the collection allow the specified file? - * @public - * @returns {boolean} True if the collection allows this file. - * - * Checks based on any filters defined on the collection. If the - * file is not valid according to the filters, this method returns false - * and also calls the filter `onInvalid` method defined for the - * collection, passing it an English error string that explains why it - * failed. - */ -FS.Collection.prototype.allowsFile = function fsColAllowsFile(fileObj) { - var self = this; - - // Get filters - var filter = self.options.filter; - if (!filter) { - return true; - } - var saveAllFileExtensions = (filter.allow.extensions.length === 0); - var saveAllContentTypes = (filter.allow.contentTypes.length === 0); - - // Get info about the file - var filename = fileObj.name(); - var contentType = fileObj.type(); - if (!saveAllContentTypes && !contentType) { - filter.onInvalid && filter.onInvalid(filename + " has an unknown content type"); - return false; - } - var fileSize = fileObj.size(); - if (!fileSize || isNaN(fileSize)) { - filter.onInvalid && filter.onInvalid(filename + " has an unknown file size"); - return false; - } - - // Do extension checks only if we have a filename - if (filename) { - var ext = fileObj.getExtension(); - if (!((saveAllFileExtensions || - FS.Utility.indexOf(filter.allow.extensions, ext) !== -1) && - FS.Utility.indexOf(filter.deny.extensions, ext) === -1)) { - filter.onInvalid && filter.onInvalid(filename + ' has the extension "' + ext + '", which is not allowed'); - return false; - } - } - - // Do content type checks - if (!((saveAllContentTypes || - contentTypeInList(filter.allow.contentTypes, contentType)) && - !contentTypeInList(filter.deny.contentTypes, contentType))) { - filter.onInvalid && filter.onInvalid(filename + ' is of the type "' + contentType + '", which is not allowed'); - return false; - } - - // Do max size check - if (typeof filter.maxSize === "number" && fileSize > filter.maxSize) { - filter.onInvalid && filter.onInvalid(filename + " is too big"); - return false; - } - return true; -}; - -/** - * @method contentTypeInList Is the content type string in the list? - * @private - * @param {String[]} list - Array of content types - * @param {String} contentType - The content type - * @returns {Boolean} - * - * Returns true if the content type is in the list, or if it matches - * one of the special types in the list, e.g., "image/*". - */ -function contentTypeInList(list, contentType) { - var listType, found = false; - for (var i = 0, ln = list.length; i < ln; i++) { - listType = list[i]; - if (listType === contentType) { - found = true; - break; - } - if (listType === "image/*" && contentType.indexOf("image/") === 0) { - found = true; - break; - } - if (listType === "audio/*" && contentType.indexOf("audio/") === 0) { - found = true; - break; - } - if (listType === "video/*" && contentType.indexOf("video/") === 0) { - found = true; - break; - } - } - return found; -} diff --git a/packages/wekan-cfs-collection-filters/internal.api.md b/packages/wekan-cfs-collection-filters/internal.api.md deleted file mode 100644 index adecf64ac..000000000 --- a/packages/wekan-cfs-collection-filters/internal.api.md +++ /dev/null @@ -1,72 +0,0 @@ -## Public and Private API ## - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -*** - -__File: ["filters.js"](filters.js) Where: {client|server}__ - -*** - -### *fsCollection*.filters(filters)  Anywhere ### - -*This method __filters__ is defined in `prototype` of `FS.Collection`* - -__Arguments__ - -* __filters__ *{Object}* - - File filters for this collection. - - -__Returns__ *{undefined}* - - -> ```FS.Collection.prototype.filters = function fsColFilters(filters) { ...``` [filters.js:7](filters.js#L7) - - -- - -### *fsCollection*.allowsFile()  Anywhere ### - -*This method __allowsFile__ is defined in `prototype` of `FS.Collection`* - -__Returns__ *{boolean}* -True if the collection allows this file. - - -Checks based on any filters defined on the collection. If the -file is not valid according to the filters, this method returns false -and also calls the filter `onInvalid` method defined for the -collection, passing it an English error string that explains why it -failed. - -> ```FS.Collection.prototype.allowsFile = function fsColAllowsFile(fileObj) { ...``` [filters.js:108](filters.js#L108) - - -- - -### contentTypeInList(list, contentType)  undefined ### - -*This method is private* - -__Arguments__ - -* __list__ *{[String[]](#String[])}* - - Array of content types - -* __contentType__ *{String}* - - The content type - - -__Returns__ *{Boolean}* - - -Returns true if the content type is in the list, or if it matches -one of the special types in the list, e.g., "image/*". - -> ```function contentTypeInList(list, contentType) { ...``` [filters.js:169](filters.js#L169) - - diff --git a/packages/wekan-cfs-collection-filters/package.js b/packages/wekan-cfs-collection-filters/package.js deleted file mode 100644 index 5a1c8c385..000000000 --- a/packages/wekan-cfs-collection-filters/package.js +++ /dev/null @@ -1,29 +0,0 @@ -Package.describe({ - git: 'https://github.com/zcfs/Meteor-cfs-collection-filters.git', - name: 'wekan-cfs-collection-filters', - version: '0.2.4', - summary: 'CollectionFS, adds FS.Collection filters' -}); - -Package.onUse(function(api) { - api.versionsFrom('1.0'); - - api.use(['wekan-cfs-base-package@0.0.30', 'wekan-cfs-collection@0.5.4']); - - api.addFiles([ - 'filters.js' - ], 'client'); - - api.addFiles([ - 'filters.js' - ], 'server'); -}); - -// Package.on_test(function (api) { -// api.use('collectionfs'); -// api.use('test-helpers', 'server'); -// api.use(['tinytest']); - -// api.addFiles('tests/server-tests.js', 'server'); -// api.addFiles('tests/client-tests.js', 'client'); -// }); diff --git a/packages/wekan-cfs-collection-filters/tests/client-tests.js b/packages/wekan-cfs-collection-filters/tests/client-tests.js deleted file mode 100644 index 0ccc90047..000000000 --- a/packages/wekan-cfs-collection-filters/tests/client-tests.js +++ /dev/null @@ -1,27 +0,0 @@ -function equals(a, b) { - return !!(EJSON.stringify(a) === EJSON.stringify(b)); -} - -Tinytest.add('cfs-collection-filters - client - test environment', function(test) { - test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection'); -}); - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-collection-filters/tests/server-tests.js b/packages/wekan-cfs-collection-filters/tests/server-tests.js deleted file mode 100644 index bfaaf6ef9..000000000 --- a/packages/wekan-cfs-collection-filters/tests/server-tests.js +++ /dev/null @@ -1,27 +0,0 @@ -function equals(a, b) { - return !!(EJSON.stringify(a) === EJSON.stringify(b)); -} - -Tinytest.add('cfs-collection-filters - server - test environment', function(test) { - test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection'); -}); - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-collection/.travis.yml b/packages/wekan-cfs-collection/.travis.yml deleted file mode 100644 index 6a4640033..000000000 --- a/packages/wekan-cfs-collection/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - "0.10" -before_install: - - "curl -L http://git.io/s0Zu-w | /bin/sh" \ No newline at end of file diff --git a/packages/wekan-cfs-collection/CHANGELOG.md b/packages/wekan-cfs-collection/CHANGELOG.md deleted file mode 100644 index cfe39a6a0..000000000 --- a/packages/wekan-cfs-collection/CHANGELOG.md +++ /dev/null @@ -1,727 +0,0 @@ -# Changelog - -## vCurrent -## [v0.5.3] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.5.3) -#### 20/12/14 by Morten Henriksen -- add changelog - -- Bump to version 0.5.3 - -## [v0.5.2] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.5.2) -#### 17/12/14 by Morten Henriksen -- Bump to version 0.5.2 - -## [v0.5.1] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.5.1) -#### 17/12/14 by Morten Henriksen -- mbr update, remove versions.json - -- Bump to version 0.5.1 - -## [v0.5.0] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.5.0) -#### 17/12/14 by Morten Henriksen -- Merge branch 'devel' of https://github.com/zcfs/Meteor-CollectionFS into devel - -- mbr update versions and fix warnings - -- update pkg, dependencies, etc. - -- Fix #483 - -- *Merged pull-request:* "mrt graphicsmagick instructions to meteor 0.9+" [#442](https://github.com/zcfs/Meteor-CollectionFS/issues/442) ([yogiben](https://github.com/yogiben)) - -- mrt graphicsmagick instructions to meteor 0.9+ - -- mention underlying collection - -- *Merged pull-request:* "Added server-side Buffer example to README.md" [#405](https://github.com/zcfs/Meteor-CollectionFS/issues/405) ([abuddenb](https://github.com/abuddenb)) - -- change prop names - -- Merge branch 'devel' of https://github.com/zcfs/Meteor-CollectionFS into devel - -- add "Display an Uploaded Image" example - -- addition to steps - -- correct 0.9.0 steps - -- Merge branch 'devel' of github.com:abuddenb/Meteor-CollectionFS into devel - -- Added server-side Buffer example to README.md - -Patches by GitHub users [@yogiben](https://github.com/yogiben), [@abuddenb](https://github.com/abuddenb). - -## [v0.4.9] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.9) -#### 27/08/14 by Eric Dobbertin -- add 0.9.0 instructions - -- change package name to lowercase - -- Added server-side Buffer example to README.md - -- *Merged pull-request:* "Updated README.md to reflect that FS.File - Objects can't be stored in t..." [#395](https://github.com/zcfs/Meteor-CollectionFS/issues/395) ([DanielDornhardt](https://github.com/DanielDornhardt)) - -- Updated README.md to reflect that FS.File - Objects can't be stored in the Server MongoDB at the moment. - -- document key - -- update the descriptions of collections - -- document beforeWrite - -- add download button example - -- *Merged pull-request:* "Update README.md" [#354](https://github.com/zcfs/Meteor-CollectionFS/issues/354) ([karabijavad](https://github.com/karabijavad)) - -- should say to use cfs-graphicsmagick pkg - -- fix typo - -- *Merged pull-request:* "Added "Storing FS.File references in your objects" chapter to README" [#311](https://github.com/zcfs/Meteor-CollectionFS/issues/311) ([Sanjo](https://github.com/Sanjo)) - -- Added "Storing FS.File references in your objects" chapter to README - -- a few more API updates - -- updates for changed FS.File API - -- additions and clarifications - -- *Merged pull-request:* "Custom Metadata misleading example" [#282](https://github.com/zcfs/Meteor-CollectionFS/issues/282) ([czeslaaw](https://github.com/czeslaaw)) - -- Custom Metadata misleading example - -Patches by GitHub users [@DanielDornhardt](https://github.com/DanielDornhardt), [@karabijavad](https://github.com/karabijavad), [@Sanjo](https://github.com/Sanjo), [@czeslaaw](https://github.com/czeslaaw). - -## [v0.4.8] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.8) -#### 09/04/14 by Eric Dobbertin -- Add cfs-collection-filters pkg by default - -- Use FS.Utility.setFileExtension in example - -## [v0.4.7] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.7) -#### 05/04/14 by Morten Henriksen -- corrections, and move image examples here so we can deprecate cfs-imagemagick - -## [v0.4.6] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.6) -#### 02/04/14 by Morten Henriksen -- *Fixed bug:* "Documentation Issues" [#241](https://github.com/zcfs/Meteor-CollectionFS/issues/241) - -- point to cfs-graphicsmagick readme for transform examples - -## [v0.4.5] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.5) -#### 31/03/14 by Eric Dobbertin -- use latest releases - -- Add yet a note about mrt and collectionFS in the readme - -## [v0.4.4] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.4) -#### 25/03/14 by Morten Henriksen -- attempt to get everything up to date - -- Add notice about mrt having troubles figuring out deps - -- *Merged pull-request:* "Removed redundant installation instructions." [#212](https://github.com/zcfs/Meteor-CollectionFS/issues/212) ([lleonard188](https://github.com/lleonard188)) - -- up to date - -- read me update - -- add test note - -Patches by GitHub user [@lleonard188](https://github.com/lleonard188). - -## [v0.4.3] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.3) -#### 23/03/14 by Morten Henriksen -- use collectionFS travis version force update - -## [v0.4.2] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.2) -#### 22/03/14 by Morten Henriksen -- change deps - -- Add read me about transformWrite - -## [v0.4.1] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.1) -#### 21/03/14 by Morten Henriksen -- update reference to devel branch - -- Merge branch 'devel' of https://github.com/zcfs/Meteor-CollectionFS into devel - -- don't need to install transfer - -- mark deprecated api docs - -- test strikeout md - -- no need to imply cfs-transfer since it doesn't do anything at the moment - -- Remove ejson-file imply - -## [v0.4.0] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.0) -#### 06/03/14 by Eric Dobbertin -- add section for documenting example code for common tasks, and add some of the examples; @raix feel free to add more - -- add http upload package to smart.json - -- Merge origin/devel into devel - -- need to imply the http upload package because it's the default now - -- update HTTP access point override docs - -- update docs to use `devel` branch - -- list component packages in smart.json - -- Merge origin/devel into devel-merge - -- add the ejson-file and correct doc - -- refactor everything into packages - -## [devel-merge-old] (https://github.com/zcfs/Meteor-CollectionFS/tree/devel-merge-old) -#### 12/02/14 by Eric Dobbertin -- update to latest FileSaver.js - -- one of many refactores - -- add optimization section - -- add section explaining client vs server insert - -- prevent autopublish for the SA collections - -- remove arg that isn't used or passed - -- changes to support client SA, plus clean/reorg SA code to have less duplication - -- merge the concepts of "store" and "copy", update docs, switch to FS.Store namespace - -- use wait:true to avoid Meteor issue - -- extend allow when insecure package is installed - -- document and improve code flow a bit - -- faster to use onResultReceived callback - -- use onload instead of onloadend because we want only successful loads - -- remove some console logging - -- fix issue where stuff wasn't uploading because we weren't calling getFileRecord() in the access point methods - -- make allowed file extension checks not be case sensitive - -- remove DDP "/del" access point since it's not used or necessary - -- Remove collection-hooks dependency; use deny instead. Also some cleanup and code docs - -- replace `mmmagic` dependency with a `mime` dependency; hopefully fixes issues we've seen with meteor deploy - -- refactor to expose saveCopy to API; then change fileworker observes to be per-copy, calling saveCopy and allowing better control of which copies to create at which times - -- use observes for all store saving and temp store deleting; add/adjust some api doc comments (didn't regenerate yet) - -- improve fileIsAllowed check order and messages - -- Add check for the Accounts package - -- *Fixed bug:* "no userId passed to download allow validator" [#120](https://github.com/zcfs/Meteor-CollectionFS/issues/120) - -- always append access token to url when a user is logged in; makes usage simpler to do opt-out rather than opt-in - -- Don't queue ddp method calls - -- Merge changes - -- Optimize buffer handling - -- Switch to MicroQueue - -- improve memory management, attempt client side resume implementation, other minor fixes - -- fix several issues, make downloading work, improve a few bits of code - -- do the isImage test correctly; add some API docs - -- isEmpty will be true for null or undefined - -- rewrite getExtension so it works for unmounted files, too - -- add strong reactive-list dependency for powerqueue - -- minor fixes and code improvements; track uploading files by both collection and ID since one queue handles all collections - -- Base the upload queue on PowerQueue sub queues - -- Add sa note - -- limit use of db - -- Refactor and documentation - -- use mmmagic 0.3.5 - -- *Fixed bug:* "Option to set Cache-Control and Max-Age" [#117](https://github.com/zcfs/Meteor-CollectionFS/issues/117) - -- fix stuff that's broken - -## [v0.3.7] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.3.7) -#### 08/01/14 by Morten Henriksen -- *Fixed bug:* "How to store files on the server side?" [#29](https://github.com/zcfs/Meteor-CollectionFS/issues/29) - -- rework ejson and remove fsFile.reload - -- explain complete upload process in ADVANCED docs - -- Adds join to smart.json (its a weak dependency #119) - -- link to api docs for acceptDropsOn - -- typo/formatting fixes - -- docs + insert callback returns `FS.File` instead of `id` - -- Add docs and `FS.File.fetch` - -- Add support for `Join` - -- end with line - -- smaller headlines in docs - -- init api docs - -- Refactor and documentation - -- FS.Collection.insert should return the `FS.File` object - -- remove some comments and such - -- document custom connections - -- add livedata ref to access DDP obj - -- use separate ddp connection with option to pass in custom - -- public folder and gm/im - -- fix null options - -- *Fixed bug:* "no userId passed to download allow validator" [#120](https://github.com/zcfs/Meteor-CollectionFS/issues/120) - -- make useHTTP true by default - -- skip auth checks if Package.insecure - -- remove `callback` arg from fsFile.get since it's not used or necessary; fix partial gets such that they actually use getBytes, greatly speeding up downloads of large files - -- reorg code and speed up downloads - -- split TransferQueue into DownloadTransferQueue and UploadTransferQueue - -- improvements to make use of new PowerQueue features - -- fix issue with previous commit - -- add accessPoints option - -- Pull out temporary chunk code into a separate tempStore.js file, within a TempStore object. This makes it easier to maintain. Also updated the file worker code to correctly find temporary chunks that can be removed and delete those files. - -- add security section - -- Internally, change all "master" stuff to be the same as "copies". External API is still the same, but master options are copied to a special copy named "_master" so that all the other code can be cleaner. This may be a step toward being able to blur or eliminate the master/copy distinction, although there are still some benefits to having a master. - -- Add instructions for installing for testing - -- refactor code to be a bit cleaner - -- add functions for getting an FS.File or setting FS.File data from a URL on the server - -- clean up and improve some transfer code - -- update console log message to be more correct - -- ensure that fsFile.bytesUploaded is always set correctly - -- fix some issues with recent commits - -- *Merged pull-request:* "Updates the filter example area so that it works" [#109](https://github.com/zcfs/Meteor-CollectionFS/issues/109) ([cramhead](https://github.com/cramhead)) - -- add .npm to gitignore - -- Remove .npm folder - -- Clean clone just a bit - -- Refactor fsCollection and argParser - -- Comment on filter options - -- Add download url - -- refactor access point - -- add put/get/del security based on allow/deny functions - -- Updates the filter example area so that it works - -- update for API change - -- more client-side speed improvements and allow passing File/Blob to FS.File constructor again - -- fix data mixup - -- fix upload slowness and blocking - -- change API to adjust issue with data loading callbacks - -- revise FS.File API where data handling is concerned; fix some issues with callback handling in client-side methods; upshot should be faster, smoother uploads and downloads - -- change names and put everything in exported FS namespace - -- fix get/download of copies - -- *Fixed bug:* "Files after certain size aren't saved properly. " [#104](https://github.com/zcfs/Meteor-CollectionFS/issues/104) - -- add fileobject metadata and acceptDropsOn - -- add some methods to load FO data from URL - -- Correct allow/deny examples - -- call put callback correctly - -- add correct temporary installation instructions - -- use correct filename when saving download - -- filtering fixes - -- removed some unused stuff - -- adjust some comments - -- switch api.remove to api.del for consistency with the other methods - -- add hasCopy method - -- new api; tons of changes - -- use generic queue for server file handling - -- update progress in the correct place - -- minor changes to comments - -- fix gridfs get method - -- incorporate #82 - -- make filtering work (added collection-hooks dependency for core package) - -- change UploadsCollection to CollectionFS; change former CollectionFS to GridFS and don't export it (used only by the gridfs storage adaptor); clean up some other areas and update readmes - -- *Fixed bug:* "retrieveBlob failure" [#93](https://github.com/zcfs/Meteor-CollectionFS/issues/93) - -- implement http methods URLs - -- Merge branch 'devel' of https://github.com/zcfs/Meteor-CollectionFS.git into devel - -- significant revisions to move downloading support to the UploadsCollection and make collectionFS/gridFS a pure storage adaptor - -- Merge branch 'pr/94' into devel - -- split and revise readmes - -- rename packages and organize package.js - -- error handling improvements - -- better failure handling for removeCopy - -- handlebars helper to display blob image in CFS package - -- remove all encoding info - -- refactor to fix multiple-file simultaneous uploads - -- don't use _id in filesystem destination since it's not set anyway - -- remove FileObject.file and instead save file as Blob (.blob) when FileObject.fromFile is called - -- revise API a bit - -- stop using strings and encoding and pass everything as Uint8Array (fixes downloading corruption) - -- only attempt to delete file if it exists - -- remove unused file - -- complete refactoring; temporary for testing/tweaking and then will split into multiple packages - -- *Merged pull-request:* "Implemented max parallel transfers" [#62](https://github.com/zcfs/Meteor-CollectionFS/issues/62) ([floo51](https://github.com/floo51)) - -Patches by GitHub users [@cramhead](https://github.com/cramhead), [@floo51](https://github.com/floo51). - -## [v0.3.6] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.3.6) -#### 10/10/13 by Morten Henriksen -- Edit ideas about storage adapters and filehandlers - -- Add MIT License - -- Add paypal and weak deps - -- Added the org. filemanager demo/example - -## [v0.3.5] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.3.5) -#### 20/09/13 by Morten Henriksen -## [v0.3.4] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.3.4) -#### 20/09/13 by Morten Henriksen -- Extract the examples from collectionFS - -- Added examples from @mxab - -## [v0.3.3] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.3.3) -#### 18/09/13 by Morten Henriksen -- added travis badge - -- Added travis badge - -- Added basic environment - -- Added metadata getter to docs - -## [v0.3.2] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.3.2) -#### 17/09/13 by Morten Henriksen -## [v0.3.1] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.3.1) -#### 16/09/13 by Morten Henriksen -- Added some details about http.publishing of collections - -- added check in filehandlers - -- Updated som docs - -- js hint added scope - -- jshint clean up - -- *Fixed bug:* "Exception from setTimeout callback: { stack: [Getter] }" [#64](https://github.com/zcfs/Meteor-CollectionFS/issues/64) - -- Merge branch 'devel' - -- Bump version to preview of 0.3.0 - -- Implemented max parallel transfers - -- Revert "began refractoring" - -- Revert "Run jshint through files" - -- Revert "Preparing file object methods for better api" - -- Revert "added fileobject files to package" - -- added fileobject files to package - -- Preparing file object methods for better api - -- Run jshint through files - -- *Merged pull-request:* "Improvements and Fixes to built-in helpers, storeFiles, and acceptDropsOn" [#51](https://github.com/zcfs/Meteor-CollectionFS/issues/51) ([aldeed](https://github.com/aldeed)) - -- Add generic events system, switch to "enums" for invalid event types, and change "fileFilter" to "filter" throughout. Update README to reflect these changes. - -- Update readme to reflect storeFiles and acceptDropsOn changes, plus add documentation for all of the new built-in handlebars helpers - -- commit some files that should be committed - -- -Improve and fix built-in handlebars helpers -Prefix all built-in helpers with "cfs" -Update new example app to reflect helper changes, and improve and fix it a bit, too - -- Merge remote-tracking branch 'upstream/master' - -- update documentation of storeFiles and acceptDropsOn - -- Added credit to @eprochasson - -- *Merged pull-request:* "Should fix issue #45" [#50](https://github.com/zcfs/Meteor-CollectionFS/issues/50) ([eprochasson](https://github.com/eprochasson)) - -- *Fixed bug:* "file handlers not showing up in local demo" [#45](https://github.com/zcfs/Meteor-CollectionFS/issues/45) - -- *Merged pull-request:* "Update README.md" [#49](https://github.com/zcfs/Meteor-CollectionFS/issues/49) ([eprochasson](https://github.com/eprochasson)) - -- Added meteor style guide for jshint - -- fix package file - -- fixes and improvements to storeFiles() and acceptDropsOn() - -- Use a different saveAs shim - -- Merge branch 'master' of https://github.com/aldeed/Meteor-CollectionFS - -- Fixes and changes to support cfs changes - -- -"cfs" prefix, new helpers, improvements and fixes -include saveAs shim in the package so that download button helper can reliably call it - -- Add dependencies and files - -- Document storeFiles() and acceptDropsOn() - -- *Merged pull-request:* "Built-ins, fixes, etc." [#48](https://github.com/zcfs/Meteor-CollectionFS/issues/48) ([aldeed](https://github.com/aldeed)) - -- Add the new files to the package manifest - -- Add underscore as dependency. It seems that Meteor may soon remove underscore from the core. - -- Minor changes to support fileHanders() and fileFilter() function changes - -- Copy in numeral.js for use by the built-in handlebar helper that displays file size in human readable format. This means the helper supports any of the format strings supported by numeral.js for file sizes. - -- -Add fileFilter() function to specify allowed and disallowed files per collectionFS, based on extensions and/or content types -Add fileIsAllowed() function to easily check whether a particular file is allowed based on the rules set up by fileFilter() -Change all of the passthrough functions (find, findOne, update, remove, allow, deny) to pass through all function arguments more simply and more safely. This allows, for example, using find() instead of find({}). -Change fileHandlers() to extend the object whenever called, which means you can safely call it more than once -Add several utility functions for use in either client or server code - -- -Add storeFiles API -Check that files are allowed by fileFilter before saving -Add acceptDropsOn API -Use .depend() instead of Deps throughout -Pull out _getProgress calc to use in two places -Add isUploading API -Improve isDownloading code - -- New file to hold built-in handlebars helpers, including several initial helpers - -- New file manager example app showing how to use new features, built-in handlebars helpers, etc. - -- *Merged pull-request:* "Minor doc correction" [#47](https://github.com/zcfs/Meteor-CollectionFS/issues/47) ([aldeed](https://github.com/aldeed)) - -- *Merged pull-request:* "Documentation Improvement" [#46](https://github.com/zcfs/Meteor-CollectionFS/issues/46) ([aldeed](https://github.com/aldeed)) - -- Extensively revised README - -Patches by GitHub users [@aldeed](https://github.com/aldeed), [@eprochasson](https://github.com/eprochasson). - -## [v0.2.3] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.2.3) -#### 04/05/13 by Morten Henriksen -- *Fixed bug:* "Binary File Transfers Corrupted? Truncated?" [#41](https://github.com/zcfs/Meteor-CollectionFS/issues/41) - -## [v0.2.2] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.2.2) -#### 03/05/13 by Morten Henriksen -- updated scope for serverConsole - -- *Fixed bug:* "Error when using fresh meteor install" [#40](https://github.com/zcfs/Meteor-CollectionFS/issues/40) - -- more text edits - -- Minor text edits - -- Add credit to README - -- *Merged pull-request:* "Option for file encoding" [#36](https://github.com/zcfs/Meteor-CollectionFS/issues/36) ([nhibner](https://github.com/nhibner)) - -- Typo fix. - -- Updated documentation (added encoding to the fileRecord structure). - -- File encoding is stored in the fileRecord. - -- Allow the user to specify an encoding for the buffer when storing on the server. - -- *Merged pull-request:* "Fix backwards incompatibility" [#33](https://github.com/zcfs/Meteor-CollectionFS/issues/33) ([mitar](https://github.com/mitar)) - -- Fix backwards incompatibility. - -Patches by GitHub users [@nhibner](https://github.com/nhibner), [@mitar](https://github.com/mitar). - -## [v0.2.1] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.2.1) -#### 08/04/13 by Morten Henriksen -- Minor fixes, added dragndrop, minor refractoring - -- Only work on completed files - -## [v0.2.0] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.2.0) -#### 06/04/13 by Morten Henriksen -- Bump to 0.2.0 - Nice - -- Big speed and refractoring - -## [v0.1.9] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.9) -#### 31/03/13 by Morten Henriksen -- Added some more doc, deprecated autosubscribe to autopublish instead - -## [v0.1.8] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.8) -#### 31/03/13 by Morten Henriksen -- Added maxFilehandlers to the doc - -## [devel-#27-fixed] (https://github.com/zcfs/Meteor-CollectionFS/tree/devel-#27-fixed) -#### 31/03/13 by Morten Henriksen -- Added documentation by @petrocket - -- Got filehandlers up and running in bundles - -- Make a seperate thread + connection foreach collectionFS - -## [v0.1.7] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.7) -#### 14/03/13 by Morten Henriksen -## [v0.1.6] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.6) -#### 13/01/13 by Morten Henriksen -- Converted .length to string to cope with Meteor use of underscore - -## [devel-server-cache] (https://github.com/zcfs/Meteor-CollectionFS/tree/devel-server-cache) -#### 11/01/13 by Morten Henriksen -## [v0.1.5] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.5) -#### 11/01/13 by Morten Henriksen -- On going tests - db updates gone, requires refresh to commit changes to db - guess some que not working - -- removed setTimeout when spawn == 1 - -## [v0.1.4] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.4) -#### 08/01/13 by Morten Henriksen -## [v0.1.3] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.3) -#### 08/01/13 by Morten Henriksen -## [v0.1.2] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.2) -#### 08/01/13 by Morten Henriksen -## [v0.1.1] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.1) -#### 08/01/13 by Morten Henriksen -- Big one, added fileHandler to create cashed versions of the file - -- added made with Meteor in fileHandler example - -- corrected param bug in find and findOne - -- minor fix and update - -- Corrected install guide to use Meteorite - -## [v0.1.0] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.0) -#### 07/01/13 by Morten Henriksen -## [v0.1] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1) -#### 07/01/13 by Morten Henriksen -- updated file strukture and example - -- Restructure to package system - -- Refractoring filenames and edit package.js - -- Package.js added - -- Added smart.json for Atmosphere packages - Not tested! - -- Readme styling corrected - -- Added comments to the upload, storeFile - -- StoreFile should return fileId or null - -- Added notes about security - -- Added only owner can resume, makes sense for now - -- Added how to make a download... - -- Changed project title git - -- And some more corrections - -- More readme text - -- Added some short reference - -- some more md - -- Initial commit - diff --git a/packages/wekan-cfs-collection/LICENSE.md b/packages/wekan-cfs-collection/LICENSE.md deleted file mode 100644 index 1a3820821..000000000 --- a/packages/wekan-cfs-collection/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 [@raix](https://github.com/raix) and [@aldeed](https://github.com/aldeed), aka Morten N.O. Nørgaard Henriksen, mh@gi-software.com - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/wekan-cfs-collection/README.md b/packages/wekan-cfs-collection/README.md deleted file mode 100644 index 8699de9a4..000000000 --- a/packages/wekan-cfs-collection/README.md +++ /dev/null @@ -1,8 +0,0 @@ -wekan-cfs-collection -========================= - -This is a Meteor package used by -[CollectionFS](https://github.com/zcfs/Meteor-CollectionFS). - -You don't need to manually add this package to your app. It is added when you -add the `wekan-cfs-standard-packages` package. \ No newline at end of file diff --git a/packages/wekan-cfs-collection/api.common.js b/packages/wekan-cfs-collection/api.common.js deleted file mode 100644 index 42e4f1714..000000000 --- a/packages/wekan-cfs-collection/api.common.js +++ /dev/null @@ -1,260 +0,0 @@ -/** @method FS.Collection.prototype.insert Insert `File` or `FS.File` or remote URL into collection - * @public - * @param {File|Blob|Buffer|ArrayBuffer|Uint8Array|String} fileRef File, FS.File, or other data to insert - * @param {function} [callback] Callback `function(error, fileObj)` - * @returns {FS.File|undefined} The `file object` - * [Meteor docs](http://docs.meteor.com/#insert) - */ -FS.Collection.prototype.insert = function(fileRef, callback) { - var self = this; - - if (Meteor.isClient && !callback) { - callback = FS.Utility.defaultCallback; - } - - // XXX: - // We should out factor beginStorage to FS.File.beginStorage - // the client side storage adapters should be the one providing - // the upload either via http/ddp or direct upload - // Could be cool to have a streaming api on the client side - // having a createReadStream etc. on the client too... - function beginStorage(fileObj) { - - // If on client, begin uploading the data - if (Meteor.isClient) { - self.options.uploader && self.options.uploader(fileObj); - } - - // If on the server, save the binary to a single chunk temp file, - // so that it is available when FileWorker calls saveCopies. - // This will also trigger file handling from collection observes. - else if (Meteor.isServer) { - fileObj.createReadStream().pipe(FS.TempStore.createWriteStream(fileObj)); - } - } - - // XXX: would be great if this function could be simplyfied - if even possible? - function checkAndInsert(fileObj) { - // Check filters. This is called in deny functions, too, but we call here to catch - // server inserts and to catch client inserts early, allowing us to call `onInvalid` on - // the client and save a trip to the server. - if (!self.allowsFile(fileObj)) { - return FS.Utility.handleError(callback, 'FS.Collection insert: file does not pass collection filters'); - } - - // Set collection name - fileObj.collectionName = self.name; - - // Insert the file into db - // We call cloneFileRecord as an easy way of extracting the properties - // that need saving. - if (callback) { - fileObj._id = self.files.insert(FS.Utility.cloneFileRecord(fileObj), function(err, id) { - if (err) { - if (fileObj._id) { - delete fileObj._id; - } - } else { - // Set _id, just to be safe, since this could be before or after the insert method returns - fileObj._id = id; - // Pass to uploader or stream data to the temp store - beginStorage(fileObj); - } - callback(err, err ? void 0 : fileObj); - }); - } else { - fileObj._id = self.files.insert(FS.Utility.cloneFileRecord(fileObj)); - // Pass to uploader or stream data to the temp store - beginStorage(fileObj); - } - return fileObj; - } - - // Parse, adjust fileRef - if (fileRef instanceof FS.File) { - return checkAndInsert(fileRef); - } else { - // For convenience, allow File, Blob, Buffer, data URI, filepath, URL, etc. to be passed as first arg, - // and we will attach that to a new fileobj for them - var fileObj = new FS.File(fileRef); - if (callback) { - fileObj.attachData(fileRef, function attachDataCallback(error) { - if (error) { - callback(error); - } else { - checkAndInsert(fileObj); - } - }); - } else { - // We ensure there's a callback on the client, so if there isn't one at this point, - // we must be on the server expecting synchronous behavior. - fileObj.attachData(fileRef); - checkAndInsert(fileObj); - } - return fileObj; - } -}; - -/** @method FS.Collection.prototype.update Update the file record - * @public - * @param {FS.File|object} selector - * @param {object} modifier - * @param {object} [options] - * @param {function} [callback] - * [Meteor docs](http://docs.meteor.com/#update) - */ -FS.Collection.prototype.update = function(selector, modifier, options, callback) { - var self = this; - if (selector instanceof FS.File) { - // Make sure the file belongs to this FS.Collection - if (selector.collectionName === self.files._name) { - return selector.update(modifier, options, callback); - } else { - // Tried to save a file in the wrong FS.Collection - throw new Error('FS.Collection cannot update file belongs to: "' + selector.collectionName + '" not: "' + self.files._name + '"'); - } - } - - return self.files.update(selector, modifier, options, callback); -}; - -/** @method FS.Collection.prototype.remove Remove the file from the collection - * @public - * @param {FS.File|object} selector - * @param {Function} [callback] - * [Meteor docs](http://docs.meteor.com/#remove) - */ -FS.Collection.prototype.remove = function(selector, callback) { - var self = this; - if (selector instanceof FS.File) { - - // Make sure the file belongs to this FS.Collection - if (selector.collectionName === self.files._name) { - return selector.remove(callback); - } else { - // Tried to remove a file from the wrong FS.Collection - throw new Error('FS.Collection cannot remove file belongs to: "' + selector.collectionName + '" not: "' + self.files._name + '"'); - } - } - - //doesn't work correctly on the client without a callback - callback = callback || FS.Utility.defaultCallback; - return self.files.remove(selector, callback); -}; - -/** @method FS.Collection.prototype.findOne - * @public - * @param {[selector](http://docs.meteor.com/#selectors)} selector - * [Meteor docs](http://docs.meteor.com/#findone) - * Example: - ```js - var images = new FS.Collection( ... ); - // Get the file object - var fo = images.findOne({ _id: 'NpnskCt6ippN6CgD8' }); - ``` - */ -// Call findOne on files collection -FS.Collection.prototype.findOne = function(selector) { - var self = this; - return self.files.findOne.apply(self.files, arguments); -}; - -/** @method FS.Collection.prototype.find - * @public - * @param {[selector](http://docs.meteor.com/#selectors)} selector - * [Meteor docs](http://docs.meteor.com/#find) - * Example: - ```js - var images = new FS.Collection( ... ); - // Get the all file objects - var files = images.find({ _id: 'NpnskCt6ippN6CgD8' }).fetch(); - ``` - */ -FS.Collection.prototype.find = function(selector) { - var self = this; - return self.files.find.apply(self.files, arguments); -}; - -/** @method FS.Collection.prototype.allow - * @public - * @param {object} options - * @param {function} options.download Function that checks if the file contents may be downloaded - * @param {function} options.insert - * @param {function} options.update - * @param {function} options.remove Functions that look at a proposed modification to the database and return true if it should be allowed - * @param {[string]} [options.fetch] Optional performance enhancement. Limits the fields that will be fetched from the database for inspection by your update and remove functions - * [Meteor docs](http://docs.meteor.com/#allow) - * Example: - ```js - var images = new FS.Collection( ... ); - // Get the all file objects - var files = images.allow({ - insert: function(userId, doc) { return true; }, - update: function(userId, doc, fields, modifier) { return true; }, - remove: function(userId, doc) { return true; }, - download: function(userId, fileObj) { return true; }, - }); - ``` - */ -FS.Collection.prototype.allow = function(options) { - var self = this; - - // Pull out the custom "download" functions - if (options.download) { - if (!(options.download instanceof Function)) { - throw new Error("allow: Value for `download` must be a function"); - } - self._validators.download.allow.push(options.download); - delete options.download; - } - - return self.files.allow.call(self.files, options); -}; - -/** @method FS.Collection.prototype.deny - * @public - * @param {object} options - * @param {function} options.download Function that checks if the file contents may be downloaded - * @param {function} options.insert - * @param {function} options.update - * @param {function} options.remove Functions that look at a proposed modification to the database and return true if it should be denyed - * @param {[string]} [options.fetch] Optional performance enhancement. Limits the fields that will be fetched from the database for inspection by your update and remove functions - * [Meteor docs](http://docs.meteor.com/#deny) - * Example: - ```js - var images = new FS.Collection( ... ); - // Get the all file objects - var files = images.deny({ - insert: function(userId, doc) { return true; }, - update: function(userId, doc, fields, modifier) { return true; }, - remove: function(userId, doc) { return true; }, - download: function(userId, fileObj) { return true; }, - }); - ``` - */ -FS.Collection.prototype.deny = function(options) { - var self = this; - - // Pull out the custom "download" functions - if (options.download) { - if (!(options.download instanceof Function)) { - throw new Error("deny: Value for `download` must be a function"); - } - self._validators.download.deny.push(options.download); - delete options.download; - } - - return self.files.deny.call(self.files, options); -}; - -// TODO: Upsert? - -/** - * We provide a default implementation that doesn't do anything. - * Can be changed by user or packages, such as the default cfs-collection-filters pkg. - * @param {FS.File} fileObj File object - * @return {Boolean} Should we allow insertion of this file? - */ -FS.Collection.prototype.allowsFile = function fsColAllowsFile(fileObj) { - return true; -}; diff --git a/packages/wekan-cfs-collection/api.md b/packages/wekan-cfs-collection/api.md deleted file mode 100644 index 01a005090..000000000 --- a/packages/wekan-cfs-collection/api.md +++ /dev/null @@ -1,180 +0,0 @@ -## cfs-collection Public API ## - -CollectionFS, FS.Collection object - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -- - -### *fsCollection*.insert(fileRef, [callback])  Anywhere ### - -*This method __insert__ is defined in `prototype` of `FS.Collection`* - -__Arguments__ - -* __fileRef__ *{[FS.File](#FS.File)|[File](#File)}* - - File data reference - -* __callback__ *{function}* (Optional) - - Callback `function(error, fileObj)` - - -__Returns__ *{FS.File}* -The `file object` -[Meteor docs](http://docs.meteor.com/#insert) - -> ```FS.Collection.prototype.insert = function(fileRef, callback) { ...``` [api.common.js:8](api.common.js#L8) - - -- - -### *fsCollection*.update(selector, modifier, [options], [callback])  Anywhere ### - -*This method __update__ is defined in `prototype` of `FS.Collection`* - -__Arguments__ - -* __selector__ *{[FS.File](#FS.File)|object}* -* __modifier__ *{object}* -* __options__ *{object}* (Optional) -* __callback__ *{function}* (Optional) -[Meteor docs](http://docs.meteor.com/#update) - -> ```FS.Collection.prototype.update = function(selector, modifier, options, callback) { ...``` [api.common.js:71](api.common.js#L71) - - -- - -### *fsCollection*.remove(selector, [callback])  Anywhere ### - -*This method __remove__ is defined in `prototype` of `FS.Collection`* - -__Arguments__ - -* __selector__ *{[FS.File](#FS.File)|object}* -* __callback__ *{Function}* (Optional) -[Meteor docs](http://docs.meteor.com/#remove) - -> ```FS.Collection.prototype.remove = function(selector, callback) { ...``` [api.common.js:92](api.common.js#L92) - - -- - -### *fsCollection*.findOne(selector)  Anywhere ### - -*This method __findOne__ is defined in `prototype` of `FS.Collection`* - -__Arguments__ - -* __selector__ *{[selector](http://docs.meteor.com/#selectors)}* -[Meteor docs](http://docs.meteor.com/#findone) -Example: -```js -var images = new FS.Collection( ... ); -// Get the file object -var fo = images.findOne({ _id: 'NpnskCt6ippN6CgD8' }); -``` - -> ```FS.Collection.prototype.findOne = function(selector) { ...``` [api.common.js:122](api.common.js#L122) - - -- - -### *fsCollection*.find(selector)  Anywhere ### - -*This method __find__ is defined in `prototype` of `FS.Collection`* - -__Arguments__ - -* __selector__ *{[selector](http://docs.meteor.com/#selectors)}* -[Meteor docs](http://docs.meteor.com/#find) -Example: -```js -var images = new FS.Collection( ... ); -// Get the all file objects -var files = images.find({ _id: 'NpnskCt6ippN6CgD8' }).fetch(); -``` - -> ```FS.Collection.prototype.find = function(selector) { ...``` [api.common.js:138](api.common.js#L138) - - -- - -### *fsCollection*.allow(options)  Anywhere ### - -*This method __allow__ is defined in `prototype` of `FS.Collection`* - -__Arguments__ - -* __options__ *{object}* - * __download__ *{function}* - - Function that checks if the file contents may be downloaded - - * __insert__ *{function}* - * __update__ *{function}* - * __remove__ *{function}* - - Functions that look at a proposed modification to the database and return true if it should be allowed - - * __fetch__ *{[string]}* (Optional) - - Optional performance enhancement. Limits the fields that will be fetched from the database for inspection by your update and remove functions - -[Meteor docs](http://docs.meteor.com/#allow) -Example: -```js -var images = new FS.Collection( ... ); -// Get the all file objects -var files = images.allow({ -insert: function(userId, doc) { return true; }, -update: function(userId, doc, fields, modifier) { return true; }, -remove: function(userId, doc) { return true; }, -download: function(userId, fileObj) { return true; }, -}); -``` - -> ```FS.Collection.prototype.allow = function(options) { ...``` [api.common.js:164](api.common.js#L164) - - -- - -### *fsCollection*.deny(options)  Anywhere ### - -*This method __deny__ is defined in `prototype` of `FS.Collection`* - -__Arguments__ - -* __options__ *{object}* - * __download__ *{function}* - - Function that checks if the file contents may be downloaded - - * __insert__ *{function}* - * __update__ *{function}* - * __remove__ *{function}* - - Functions that look at a proposed modification to the database and return true if it should be denyed - - * __fetch__ *{[string]}* (Optional) - - Optional performance enhancement. Limits the fields that will be fetched from the database for inspection by your update and remove functions - -[Meteor docs](http://docs.meteor.com/#deny) -Example: -```js -var images = new FS.Collection( ... ); -// Get the all file objects -var files = images.deny({ -insert: function(userId, doc) { return true; }, -update: function(userId, doc, fields, modifier) { return true; }, -remove: function(userId, doc) { return true; }, -download: function(userId, fileObj) { return true; }, -}); -``` - -> ```FS.Collection.prototype.deny = function(options) { ...``` [api.common.js:200](api.common.js#L200) - - diff --git a/packages/wekan-cfs-collection/common.js b/packages/wekan-cfs-collection/common.js deleted file mode 100644 index 7e9942261..000000000 --- a/packages/wekan-cfs-collection/common.js +++ /dev/null @@ -1,171 +0,0 @@ -/** - * - * @constructor - * @param {string} name A name for the collection - * @param {Object} options - * @param {FS.StorageAdapter[]} options.stores An array of stores in which files should be saved. At least one is required. - * @param {Object} [options.filter] Filter definitions - * @param {Number} [options.chunkSize=2MB] Override the chunk size in bytes for uploads - * @param {Function} [options.uploader] A function to pass FS.File instances after inserting, which will begin uploading them. By default, `FS.HTTP.uploadQueue.uploadFile` is used if the `cfs-upload-http` package is present, or `FS.DDP.uploadQueue.uploadFile` is used if the `cfs-upload-ddp` package is present. You can override with your own, or set to `null` to prevent automatic uploading. - * @returns {undefined} - */ -FS.Collection = function(name, options) { - var self = this; - - self.storesLookup = {}; - - self.primaryStore = {}; - - self.options = { - filter: null, //optional - stores: [], //required - chunkSize: null - }; - - // Define a default uploader based on which upload packages are present, - // preferring HTTP. You may override with your own function or - // set to null to skip automatic uploading of data after file insert/update. - if (FS.HTTP && FS.HTTP.uploadQueue) { - self.options.uploader = FS.HTTP.uploadQueue.uploadFile; - } else if (FS.DDP && FS.DDP.uploadQueue) { - self.options.uploader = FS.DDP.uploadQueue.uploadFile; - } - - // Extend and overwrite options - FS.Utility.extend(self.options, options || {}); - - // Set the FS.Collection name - self.name = name; - - // Make sure at least one store has been supplied. - // Usually the stores aren't used on the client, but we need them defined - // so that we can access their names and use the first one as the default. - if (FS.Utility.isEmpty(self.options.stores)) { - throw new Error("You must specify at least one store. Please consult the documentation."); - } - - FS.Utility.each(self.options.stores, function(store, i) { - // Set the primary store - if (i === 0) { - self.primaryStore = store; - } - - // Check for duplicate naming - if (typeof self.storesLookup[store.name] !== 'undefined') { - throw new Error('FS.Collection store names must be uniq, duplicate found: ' + store.name); - } - - // Set the lookup - self.storesLookup[store.name] = store; - - if (Meteor.isServer) { - - // Emit events based on store events - store.on('stored', function (storeName, fileObj) { - // This is weird, but currently there is a bug where each store will emit the - // events for all other stores, too, so we need to make sure that this event - // is truly for this store. - if (storeName !== store.name) - return; - // When a file is successfully stored into the store, we emit a "stored" event on the FS.Collection only if the file belongs to this collection - if (fileObj.collectionName === name) { - var emitted = self.emit('stored', fileObj, store.name); - if (FS.debug && !emitted) { - console.log(fileObj.name({store: store.name}) + ' was successfully saved to the ' + store.name + ' store. You are seeing this informational message because you enabled debugging and you have not defined any listeners for the "stored" event on the ' + name + ' collection.'); - } - } - fileObj.emit('stored', store.name); - }); - - store.on('error', function (storeName, error, fileObj) { - // This is weird, but currently there is a bug where each store will emit the - // events for all other stores, too, so we need to make sure that this event - // is truly for this store. - if (storeName !== store.name) - return; - // When a file has an error while being stored into the temp store, we emit an "error" event on the FS.Collection only if the file belongs to this collection - if (fileObj.collectionName === name) { - error = new Error('Error storing file to the ' + store.name + ' store: ' + error.message); - var emitted = self.emit('error', error, fileObj, store.name); - if (FS.debug && !emitted) { - console.log(error.message); - } - } - fileObj.emit('error', store.name); - }); - - } - }); - - var _filesOptions = { - transform: function(doc) { - // This should keep the filerecord in the file object updated in reactive - // context - var result = new FS.File(doc, true); - result.collectionName = name; - return result; - } - }; - - if(self.options.idGeneration) _filesOptions.idGeneration = self.options.idGeneration; - - // Enable specifying an alternate driver, to change where the filerecord is stored - // Drivers can be created with MongoInternals.RemoteCollectionDriver() - if(self.options._driver){ - _filesOptions._driver = self.options._driver; - } - - // Create the 'cfs.' ++ ".filerecord" and use fsFile - var collectionName = 'cfs.' + name + '.filerecord'; - self.files = new Mongo.Collection(collectionName, _filesOptions); - - // For storing custom allow/deny functions - self._validators = { - download: {allow: [], deny: []} - }; - - // Set up filters - // XXX Should we deprecate the filter option now that this is done with a separate pkg, or just keep it? - if (self.filters) { - self.filters(self.options.filter); - } - - // Save the collection reference (we want it without the 'cfs.' prefix and '.filerecord' suffix) - FS._collections[name] = this; - - // Set up observers - Meteor.isServer && FS.FileWorker && FS.FileWorker.observe(this); - - // Emit "removed" event on collection - self.files.find().observe({ - removed: function(fileObj) { - self.emit('removed', fileObj); - } - }); - - // Emit events based on TempStore events - if (FS.TempStore) { - FS.TempStore.on('stored', function (fileObj, result) { - // When a file is successfully stored into the temp store, we emit an "uploaded" event on the FS.Collection only if the file belongs to this collection - if (fileObj.collectionName === name) { - var emitted = self.emit('uploaded', fileObj); - if (FS.debug && !emitted) { - console.log(fileObj.name() + ' was successfully uploaded. You are seeing this informational message because you enabled debugging and you have not defined any listeners for the "uploaded" event on the ' + name + ' collection.'); - } - } - }); - - FS.TempStore.on('error', function (error, fileObj) { - // When a file has an error while being stored into the temp store, we emit an "error" event on the FS.Collection only if the file belongs to this collection - if (fileObj.collectionName === name) { - self.emit('error', new Error('Error storing uploaded file to TempStore: ' + error.message), fileObj); - } - }); - } else if (Meteor.isServer) { - throw new Error("FS.Collection constructor: FS.TempStore must be defined before constructing any FS.Collections.") - } - -}; - -// An FS.Collection can emit events -FS.Collection.prototype = new EventEmitter(); diff --git a/packages/wekan-cfs-collection/internal.api.md b/packages/wekan-cfs-collection/internal.api.md deleted file mode 100644 index 6a9708fac..000000000 --- a/packages/wekan-cfs-collection/internal.api.md +++ /dev/null @@ -1,390 +0,0 @@ -## Public and Private API ## - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -*** - -__File: ["common.js"](common.js) Where: {client|server}__ - -*** - -############################################################################# - -COLLECTION FS - -############################################################################# -- - -### new *fs*.Collection(name, options)  Anywhere ### - -*This method __Collection__ is defined in `FS`* - -__Arguments__ - -* __name__ *{string}* - - A name for the collection - -* __options__ *{Object}* - * __stores__ *{[FS.StorageAdapter[]](#FS.StorageAdapter[])}* - - An array of stores in which files should be saved. At least one is required. - - * __filter__ *{Object}* (Optional) - - Filter definitions - - * __chunkSize__ *{Number}* (Optional, Default = 131072) - - Override the chunk size in bytes for uploads and downloads - - -__Returns__ *{undefined}* - - - -> ```FS.Collection = function(name, options) { ...``` [common.js:17](common.js#L17) - - -*** - -__File: ["api.common.js"](api.common.js) Where: {client|server}__ - -*** - -### *fsCollection*.insert(fileRef, [callback])  Anywhere ### - -*This method __insert__ is defined in `prototype` of `FS.Collection`* - -__Arguments__ - -* __fileRef__ *{[FS.File](#FS.File)|[File](#File)}* - - File data reference - -* __callback__ *{function}* (Optional) - - Callback `function(error, fileObj)` - - -__Returns__ *{FS.File}* -The `file object` -[Meteor docs](http://docs.meteor.com/#insert) - -> ```FS.Collection.prototype.insert = function(fileRef, callback) { ...``` [api.common.js:8](api.common.js#L8) - - -- - -### *fsCollection*.update(selector, modifier, [options], [callback])  Anywhere ### - -*This method __update__ is defined in `prototype` of `FS.Collection`* - -__Arguments__ - -* __selector__ *{[FS.File](#FS.File)|object}* -* __modifier__ *{object}* -* __options__ *{object}* (Optional) -* __callback__ *{function}* (Optional) -[Meteor docs](http://docs.meteor.com/#update) - -> ```FS.Collection.prototype.update = function(selector, modifier, options, callback) { ...``` [api.common.js:71](api.common.js#L71) - - -- - -### *fsCollection*.remove(selector, [callback])  Anywhere ### - -*This method __remove__ is defined in `prototype` of `FS.Collection`* - -__Arguments__ - -* __selector__ *{[FS.File](#FS.File)|object}* -* __callback__ *{Function}* (Optional) -[Meteor docs](http://docs.meteor.com/#remove) - -> ```FS.Collection.prototype.remove = function(selector, callback) { ...``` [api.common.js:92](api.common.js#L92) - - -- - -### *fsCollection*.findOne(selector)  Anywhere ### - -*This method __findOne__ is defined in `prototype` of `FS.Collection`* - -__Arguments__ - -* __selector__ *{[selector](http://docs.meteor.com/#selectors)}* -[Meteor docs](http://docs.meteor.com/#findone) -Example: -```js -var images = new FS.Collection( ... ); -// Get the file object -var fo = images.findOne({ _id: 'NpnskCt6ippN6CgD8' }); -``` - -> ```FS.Collection.prototype.findOne = function(selector) { ...``` [api.common.js:122](api.common.js#L122) - - -- - -### *fsCollection*.find(selector)  Anywhere ### - -*This method __find__ is defined in `prototype` of `FS.Collection`* - -__Arguments__ - -* __selector__ *{[selector](http://docs.meteor.com/#selectors)}* -[Meteor docs](http://docs.meteor.com/#find) -Example: -```js -var images = new FS.Collection( ... ); -// Get the all file objects -var files = images.find({ _id: 'NpnskCt6ippN6CgD8' }).fetch(); -``` - -> ```FS.Collection.prototype.find = function(selector) { ...``` [api.common.js:138](api.common.js#L138) - - -- - -### *fsCollection*.allow(options)  Anywhere ### - -*This method __allow__ is defined in `prototype` of `FS.Collection`* - -__Arguments__ - -* __options__ *{object}* - * __download__ *{function}* - - Function that checks if the file contents may be downloaded - - * __insert__ *{function}* - * __update__ *{function}* - * __remove__ *{function}* - - Functions that look at a proposed modification to the database and return true if it should be allowed - - * __fetch__ *{[string]}* (Optional) - - Optional performance enhancement. Limits the fields that will be fetched from the database for inspection by your update and remove functions - -[Meteor docs](http://docs.meteor.com/#allow) -Example: -```js -var images = new FS.Collection( ... ); -// Get the all file objects -var files = images.allow({ -insert: function(userId, doc) { return true; }, -update: function(userId, doc, fields, modifier) { return true; }, -remove: function(userId, doc) { return true; }, -download: function(userId, fileObj) { return true; }, -}); -``` - -> ```FS.Collection.prototype.allow = function(options) { ...``` [api.common.js:164](api.common.js#L164) - - -- - -### *fsCollection*.deny(options)  Anywhere ### - -*This method __deny__ is defined in `prototype` of `FS.Collection`* - -__Arguments__ - -* __options__ *{object}* - * __download__ *{function}* - - Function that checks if the file contents may be downloaded - - * __insert__ *{function}* - * __update__ *{function}* - * __remove__ *{function}* - - Functions that look at a proposed modification to the database and return true if it should be denyed - - * __fetch__ *{[string]}* (Optional) - - Optional performance enhancement. Limits the fields that will be fetched from the database for inspection by your update and remove functions - -[Meteor docs](http://docs.meteor.com/#deny) -Example: -```js -var images = new FS.Collection( ... ); -// Get the all file objects -var files = images.deny({ -insert: function(userId, doc) { return true; }, -update: function(userId, doc, fields, modifier) { return true; }, -remove: function(userId, doc) { return true; }, -download: function(userId, fileObj) { return true; }, -}); -``` - -> ```FS.Collection.prototype.deny = function(options) { ...``` [api.common.js:200](api.common.js#L200) - - -*** - -__File: ["api.client.js"](api.client.js) Where: {client}__ - -*** - -### _eventCallback(templateName, selector, dataContext, evt, temp, fsFile)  Client ### - -*This method is private* - -__Arguments__ - -* __templateName__ *{string}* - - Name of template to apply events on - -* __selector__ *{string}* - - The element selector eg. "#uploadField" - -* __dataContext__ *{object}* - - The event datacontext - -* __evt__ *{object}* - - The event object { error, file } - -* __temp__ *{object}* - - The template instance - -* __fsFile__ *{[FS.File](#FS.File)}* - - File that triggered the event - - -> ```var _eventCallback = function fsEventCallback(templateName, selector, dataContext, evt, temp, fsFile) { ...``` [api.client.js:10](api.client.js#L10) - - -- - -### _eachFile(files, metadata, callback)  Client ### - -*This method is private* - -__Arguments__ - -* __files__ *{array}* - - List of files to iterate over - -* __metadata__ *{object}* - - Data to attach to the files - -* __callback__ *{function}* - - Function to pass the prepared `FS.File` object - - -> ```var _eachFile = function(files, metadata, callback) { ...``` [api.client.js:36](api.client.js#L36) - - -- - -### *fsCollection*.acceptDropsOn(templateName, selector, [metadata])  Client ### - -*This method __acceptDropsOn__ is defined in `FS.Collection`* - -__Arguments__ - -* __templateName__ *{string}* - - Name of template to apply events on - -* __selector__ *{string}* - - The element selector eg. "#uploadField" - -* __metadata__ *{object|function}* (Optional) - - Data/getter to attach to the file objects - - -Using this method adds an `uploaded` and `uploadFailed` event to the -template events. The event object contains `{ error, file }` - -Example: -```css -.dropzone { -border: 2px dashed silver; -height: 5em; -padding-top: 3em; --webkit-border-radius: 8px; --moz-border-radius: 8px; --ms-border-radius: 8px; --o-border-radius: 8px; -border-radius: 8px; -} -``` -```html - -``` -```js -Template.hello.events({ -'uploaded #dropzone': function(event, temp) { -console.log('Event Uploaded: ' + event.file._id); -} -}); -images.acceptDropsOn('hello', '#dropzone'); -``` - -> ```FS.Collection.prototype.acceptDropsOn = function(templateName, selector, metadata) { ...``` [api.client.js:99](api.client.js#L99) - - -- - -### *fsCollection*.acceptUploadFrom(templateName, selector, [metadata])  Client ### - -*This method __acceptUploadFrom__ is defined in `FS.Collection`* - -__Arguments__ - -* __templateName__ *{string}* - - Name of template to apply events on - -* __selector__ *{string}* - - The element selector eg. "#uploadField" - -* __metadata__ *{object|function}* (Optional) - - Data/getter to attach to the file objects - - -Using this method adds an `uploaded` and `uploadFailed` event to the -template events. The event object contains `{ error, file }` - -Example: -```html - -``` -```js -Template.hello.events({ -'uploaded #files': function(event, temp) { -console.log('Event Uploaded: ' + event.file._id); -} -}); -images.acceptUploadFrom('hello', '#files'); -``` - -> ```FS.Collection.prototype.acceptUploadFrom = function(templateName, selector, metadata) { ...``` [api.client.js:156](api.client.js#L156) - - diff --git a/packages/wekan-cfs-collection/package.js b/packages/wekan-cfs-collection/package.js deleted file mode 100644 index 1af88d564..000000000 --- a/packages/wekan-cfs-collection/package.js +++ /dev/null @@ -1,43 +0,0 @@ -Package.describe({ - name: 'wekan-cfs-collection', - version: '0.5.5', - summary: 'CollectionFS, FS.Collection object', - git: 'https://github.com/zcfs/Meteor-cfs-collection.git' -}); - -Package.onUse(function(api) { - api.versionsFrom('1.0'); - - api.use([ - // CFS - 'wekan-cfs-base-package@0.0.30', - 'wekan-cfs-tempstore@0.1.4', - // Core - 'deps', - 'check', - 'livedata', - 'mongo-livedata', - // Other - 'raix:eventemitter@0.1.1' - ]); - - // Weak dependencies for uploaders - api.use(['wekan-cfs-upload-http@0.0.20', 'wekan-cfs-upload-ddp@0.0.17'], { weak: true }); - - api.addFiles([ - 'common.js', - 'api.common.js' - ], 'client'); - - api.addFiles([ - 'common.js', - 'api.common.js' - ], 'server'); -}); - -Package.onTest(function (api) { - api.use(['wekan-cfs-standard-packages', 'wekan-cfs-gridfs', 'tinytest', 'underscore', 'test-helpers']); - - api.addFiles('tests/server-tests.js', 'server'); - api.addFiles('tests/client-tests.js', 'client'); -}); diff --git a/packages/wekan-cfs-collection/tests/client-tests.js b/packages/wekan-cfs-collection/tests/client-tests.js deleted file mode 100644 index bf29338c7..000000000 --- a/packages/wekan-cfs-collection/tests/client-tests.js +++ /dev/null @@ -1,33 +0,0 @@ -function equals(a, b) { - return !!(EJSON.stringify(a) === EJSON.stringify(b)); -} - -Tinytest.add('cfs-collection - test environment', function(test) { - test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection'); -}); - -/* - * TODO FS.Collection Client Tests - * - */ - - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-collection/tests/server-tests.js b/packages/wekan-cfs-collection/tests/server-tests.js deleted file mode 100644 index 3f6297022..000000000 --- a/packages/wekan-cfs-collection/tests/server-tests.js +++ /dev/null @@ -1,96 +0,0 @@ -function equals(a, b) { - return !!(EJSON.stringify(a) === EJSON.stringify(b)); -} - -var fileCollection = new FS.Collection('files', { - stores: [ - new FS.Store.GridFS('files') - ] -}); - -Tinytest.add('cfs-collection - test environment', function(test) { - test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection'); -}); - -Tinytest.add('cfs-collection - insert URL - sync - one', function (test) { - // XXX should switch to a local URL we host - - // One - try { - fileCollection.insert("http://cdn.morguefile.com/imageData/public/files/b/bboomerindenial/preview/fldr_2009_04_01/file3301238617907.jpg"); - test.isTrue(true); - } catch (err) { - test.isFalse(!!err, "URL insert failed"); - } - -}); - -Tinytest.add('cfs-collection - insert URL - sync - loop', function (test) { - // XXX should switch to a local URL we host - - try { - for (var i = 0, len = 10; i < len; i++) { - fileCollection.insert("http://cdn.morguefile.com/imageData/public/files/b/bboomerindenial/preview/fldr_2009_04_01/file3301238617907.jpg"); - } - test.isTrue(true); - } catch (err) { - test.isFalse(!!err, "URL insert failed"); - } -}); - -Tinytest.addAsync('cfs-collection - insert URL - async - one', function (test, next) { - // XXX should switch to a local URL we host - - // One - try { - fileCollection.insert("http://cdn.morguefile.com/imageData/public/files/b/bboomerindenial/preview/fldr_2009_04_01/file3301238617907.jpg", function (error, result) { - test.isNull(error); - test.instanceOf(result, FS.File); - next(); - }); - } catch (err) { - test.isFalse(!!err, "URL insert failed"); - next(); - } -}); - -Tinytest.addAsync('cfs-collection - insert URL - async - loop', function (test, next) { - // XXX should switch to a local URL we host - - try { - var done = 0; - for (var i = 0, len = 10; i < len; i++) { - fileCollection.insert("http://cdn.morguefile.com/imageData/public/files/b/bboomerindenial/preview/fldr_2009_04_01/file3301238617907.jpg", function (error, result) { - test.isNull(error); - test.instanceOf(result, FS.File); - done++; - if (done === 10) { - next(); - } - }); - } - } catch (err) { - test.isFalse(!!err, "URL insert failed"); - next(); - } -}); - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-data-man/.travis.yml b/packages/wekan-cfs-data-man/.travis.yml deleted file mode 100644 index 6a4640033..000000000 --- a/packages/wekan-cfs-data-man/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - "0.10" -before_install: - - "curl -L http://git.io/s0Zu-w | /bin/sh" \ No newline at end of file diff --git a/packages/wekan-cfs-data-man/LICENSE.md b/packages/wekan-cfs-data-man/LICENSE.md deleted file mode 100644 index f0f70cafa..000000000 --- a/packages/wekan-cfs-data-man/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014 [@raix](https://github.com/raix), aka Morten N.O. Nørgaard Henriksen, mh@gi-software.com, and [@aldeed](https://github.com/aldeed), aka Eric Dobbertin - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/wekan-cfs-data-man/README.md b/packages/wekan-cfs-data-man/README.md deleted file mode 100644 index a124f46e3..000000000 --- a/packages/wekan-cfs-data-man/README.md +++ /dev/null @@ -1,8 +0,0 @@ -wekan-cfs-data-man [![Build Status](https://travis-ci.org/CollectionFS/Meteor-data-man.svg?branch=master)](https://travis-ci.org/CollectionFS/Meteor-data-man) -========================= - -Who can handle your arbitrary data? The DataMan can. - -This is a package used by CollectionFS to attach data to file objects. Could be used for other things, though. - -[Public API](api.md) diff --git a/packages/wekan-cfs-data-man/api.md b/packages/wekan-cfs-data-man/api.md deleted file mode 100644 index 1e29ebe07..000000000 --- a/packages/wekan-cfs-data-man/api.md +++ /dev/null @@ -1,309 +0,0 @@ -## data-man Public API ## - -A data manager, allowing you to attach various types of data and get it back in various other types - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -- - -### new DataMan(data, [type])  Client ### - - -__Arguments__ - -* __data__ *{[File](#File)|[Blob](#Blob)|ArrayBuffer|Uint8Array|String}* - - The data that you want to manipulate. - -* __type__ *{String}* (Optional) - - The data content (MIME) type, if known. Required if the first argument is an ArrayBuffer, Uint8Array, or URL - - - -> ```DataMan = function DataMan(data, type) { ...``` [client/data-man-api.js:8](client/data-man-api.js#L8) - - -- - -### *dataman*.getBlob(callback)  Client ### - -*This method __getBlob__ is defined in `prototype` of `DataMan`* - -__Arguments__ - -* __callback__ *{Function}* - - callback(error, blob) - - -__Returns__ *{undefined}* - - -Passes a Blob representing this data to a callback. - -> ```DataMan.prototype.getBlob = function dataManGetBlob(callback) { ...``` [client/data-man-api.js:52](client/data-man-api.js#L52) - - -- - -### *dataman*.getBinary([start], [end], callback)  Client ### - -*This method __getBinary__ is defined in `prototype` of `DataMan`* - -__Arguments__ - -* __start__ *{Number}* (Optional) - - First byte position to read. - -* __end__ *{Number}* (Optional) - - Last byte position to read. - -* __callback__ *{Function}* - - callback(error, binaryData) - - -__Returns__ *{undefined}* - - -Passes a Uint8Array representing this data to a callback. - -> ```DataMan.prototype.getBinary = function dataManGetBinary(start, end, callback) { ...``` [client/data-man-api.js:84](client/data-man-api.js#L84) - - -- - -### *dataman*.saveAs([filename])  Client ### - -*This method __saveAs__ is defined in `prototype` of `DataMan`* - -__Arguments__ - -* __filename__ *{String}* (Optional) - -__Returns__ *{undefined}* - -Tells the browser to save the data like a normal downloaded file, -using the provided filename. - - -> ```DataMan.prototype.saveAs = function dataManSaveAs(filename) { ...``` [client/data-man-api.js:146](client/data-man-api.js#L146) - - -- - -### *dataman*.getDataUri(callback)  Client ### - -*This method __getDataUri__ is defined in `prototype` of `DataMan`* - -__Arguments__ - -* __callback__ *{function}* - - callback(err, dataUri) - - - -> ```DataMan.prototype.getDataUri = function dataManGetDataUri(callback) { ...``` [client/data-man-api.js:166](client/data-man-api.js#L166) - - -- - -### *dataman*.type()  Client ### - -*This method __type__ is defined in `prototype` of `DataMan`* - - -Returns the type of the data. - -> ```DataMan.prototype.type = function dataManType() { ...``` [client/data-man-api.js:227](client/data-man-api.js#L227) - - -- - -### new DataMan(data, [type])  Server ### - - -__Arguments__ - -* __data__ *{Buffer|ArrayBuffer|Uint8Array|String}* - - The data that you want to manipulate. - -* __type__ *{String}* (Optional) - - The data content (MIME) type, if known. Required if the first argument is a Buffer, ArrayBuffer, Uint8Array, or URL - - - -> ```DataMan = function DataMan(data, type) { ...``` [server/data-man-api.js:10](server/data-man-api.js#L10) - - -- - -### *dataman*.getBuffer([callback])  Server ### - -*This method __getBuffer__ is defined in `prototype` of `DataMan`* - -__Arguments__ - -* __callback__ *{function}* (Optional) - - callback(err, buffer) - - -__Returns__ *{Buffer|undefined}* - - -Returns a Buffer representing this data, or passes the Buffer to a callback. - -> ```DataMan.prototype.getBuffer = function dataManGetBuffer(callback) { ...``` [server/data-man-api.js:54](server/data-man-api.js#L54) - - -- - -### *dataman*.saveToFile()  Server ### - -*This method __saveToFile__ is defined in `prototype` of `DataMan`* - -__Returns__ *{undefined}* - - -Saves this data to a filepath on the local filesystem. - -> ```DataMan.prototype.saveToFile = function dataManSaveToFile(filePath) { ...``` [server/data-man-api.js:66](server/data-man-api.js#L66) - - -- - -### *dataman*.getDataUri([callback])  Server ### - -*This method __getDataUri__ is defined in `prototype` of `DataMan`* - -__Arguments__ - -* __callback__ *{function}* (Optional) - - callback(err, dataUri) - - - -If no callback, returns the data URI. - -> ```DataMan.prototype.getDataUri = function dataManGetDataUri(callback) { ...``` [server/data-man-api.js:84](server/data-man-api.js#L84) - - -- - -### *dataman*.createReadStream()  Server ### - -*This method __createReadStream__ is defined in `prototype` of `DataMan`* - - -Returns a read stream for the data. - -> ```DataMan.prototype.createReadStream = function dataManCreateReadStream() { ...``` [server/data-man-api.js:95](server/data-man-api.js#L95) - - -- - -### *dataman*.size([callback])  Server ### - -*This method __size__ is defined in `prototype` of `DataMan`* - -__Arguments__ - -* __callback__ *{function}* (Optional) - - callback(err, size) - - - -If no callback, returns the size in bytes of the data. - -> ```DataMan.prototype.size = function dataManSize(callback) { ...``` [server/data-man-api.js:106](server/data-man-api.js#L106) - - -- - -### *dataman*.type()  Server ### - -*This method __type__ is defined in `prototype` of `DataMan`* - - -Returns the type of the data. - -> ```DataMan.prototype.type = function dataManType() { ...``` [server/data-man-api.js:117](server/data-man-api.js#L117) - - -- - -### new *dataman*.Buffer(buffer, type)  Server ### - -*This method __Buffer__ is defined in `DataMan`* - -__Arguments__ - -* __buffer__ *{Buffer}* -* __type__ *{String}* - - The data content (MIME) type. - - - -> ```DataMan.Buffer = function DataManBuffer(buffer, type) { ...``` [server/data-man-buffer.js:10](server/data-man-buffer.js#L10) - - -- - -### new *dataman*.DataURI(dataUri)  Server ### - -*This method __DataURI__ is defined in `DataMan`* - -__Arguments__ - -* __dataUri__ *{String}* - - -> ```DataMan.DataURI = function DataManDataURI(dataUri) { ...``` [server/data-man-datauri.js:7](server/data-man-datauri.js#L7) - - -- - -### new *dataman*.FilePath(filepath, [type])  Server ### - -*This method __FilePath__ is defined in `DataMan`* - -__Arguments__ - -* __filepath__ *{String}* -* __type__ *{String}* (Optional) - - The data content (MIME) type. Will lookup from file if not passed. - - - -> ```DataMan.FilePath = function DataManFilePath(filepath, type) { ...``` [server/data-man-filepath.js:11](server/data-man-filepath.js#L11) - - -- - -### new *dataman*.URL(url, type)  Server ### - -*This method __URL__ is defined in `DataMan`* - -__Arguments__ - -* __url__ *{String}* -* __type__ *{String}* - - The data content (MIME) type. - - - -> ```DataMan.URL = function DataManURL(url, type) { ...``` [server/data-man-url.js:10](server/data-man-url.js#L10) - - diff --git a/packages/wekan-cfs-data-man/client/Blob.js b/packages/wekan-cfs-data-man/client/Blob.js deleted file mode 100644 index 7e5e42de7..000000000 --- a/packages/wekan-cfs-data-man/client/Blob.js +++ /dev/null @@ -1,166 +0,0 @@ -/* Blob.js - * A Blob implementation. - * 2013-12-27 - * - * By Eli Grey, http://eligrey.com - * By Devin Samarin, https://github.com/eboyjr - * License: X11/MIT - * See LICENSE.md - */ - -/*global self, unescape */ -/*jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, - plusplus: true */ - -/*! @source http://purl.eligrey.com/github/Blob.js/blob/master/Blob.js */ - -if (!(typeof Blob === "function" || typeof Blob === "object") || typeof URL === "undefined") -if ((typeof Blob === "function" || typeof Blob === "object") && typeof webkitURL !== "undefined") self.URL = webkitURL; -else var Blob = (function (view) { - "use strict"; - - var BlobBuilder = view.BlobBuilder || view.WebKitBlobBuilder || view.MozBlobBuilder || view.MSBlobBuilder || (function(view) { - var - get_class = function(object) { - return Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1]; - } - , FakeBlobBuilder = function BlobBuilder() { - this.data = []; - } - , FakeBlob = function Blob(data, type, encoding) { - this.data = data; - this.size = data.length; - this.type = type; - this.encoding = encoding; - } - , FBB_proto = FakeBlobBuilder.prototype - , FB_proto = FakeBlob.prototype - , FileReaderSync = view.FileReaderSync - , FileException = function(type) { - this.code = this[this.name = type]; - } - , file_ex_codes = ( - "NOT_FOUND_ERR SECURITY_ERR ABORT_ERR NOT_READABLE_ERR ENCODING_ERR " - + "NO_MODIFICATION_ALLOWED_ERR INVALID_STATE_ERR SYNTAX_ERR" - ).split(" ") - , file_ex_code = file_ex_codes.length - , real_URL = view.URL || view.webkitURL || view - , real_create_object_URL = real_URL.createObjectURL - , real_revoke_object_URL = real_URL.revokeObjectURL - , URL = real_URL - , btoa = view.btoa - , atob = view.atob - - , ArrayBuffer = view.ArrayBuffer - , Uint8Array = view.Uint8Array - ; - FakeBlob.fake = FB_proto.fake = true; - while (file_ex_code--) { - FileException.prototype[file_ex_codes[file_ex_code]] = file_ex_code + 1; - } - if (!real_URL.createObjectURL) { - URL = view.URL = {}; - } - URL.createObjectURL = function(blob) { - var - type = blob.type - , data_URI_header - ; - if (type === null) { - type = "application/octet-stream"; - } - if (blob instanceof FakeBlob) { - data_URI_header = "data:" + type; - if (blob.encoding === "base64") { - return data_URI_header + ";base64," + blob.data; - } else if (blob.encoding === "URI") { - return data_URI_header + "," + decodeURIComponent(blob.data); - } if (btoa) { - return data_URI_header + ";base64," + btoa(blob.data); - } else { - return data_URI_header + "," + encodeURIComponent(blob.data); - } - } else if (real_create_object_URL) { - return real_create_object_URL.call(real_URL, blob); - } - }; - URL.revokeObjectURL = function(object_URL) { - if (object_URL.substring(0, 5) !== "data:" && real_revoke_object_URL) { - real_revoke_object_URL.call(real_URL, object_URL); - } - }; - FBB_proto.append = function(data/*, endings*/) { - var bb = this.data; - // decode data to a binary string - if (Uint8Array && (data instanceof ArrayBuffer || data instanceof Uint8Array)) { - var - str = "" - , buf = new Uint8Array(data) - , i = 0 - , buf_len = buf.length - ; - for (; i < buf_len; i++) { - str += String.fromCharCode(buf[i]); - } - bb.push(str); - } else if (get_class(data) === "Blob" || get_class(data) === "File") { - if (FileReaderSync) { - var fr = new FileReaderSync; - bb.push(fr.readAsBinaryString(data)); - } else { - // async FileReader won't work as BlobBuilder is sync - throw new FileException("NOT_READABLE_ERR"); - } - } else if (data instanceof FakeBlob) { - if (data.encoding === "base64" && atob) { - bb.push(atob(data.data)); - } else if (data.encoding === "URI") { - bb.push(decodeURIComponent(data.data)); - } else if (data.encoding === "raw") { - bb.push(data.data); - } - } else { - if (typeof data !== "string") { - data += ""; // convert unsupported types to strings - } - // decode UTF-16 to binary string - bb.push(unescape(encodeURIComponent(data))); - } - }; - FBB_proto.getBlob = function(type) { - if (!arguments.length) { - type = null; - } - return new FakeBlob(this.data.join(""), type, "raw"); - }; - FBB_proto.toString = function() { - return "[object BlobBuilder]"; - }; - FB_proto.slice = function(start, end, type) { - var args = arguments.length; - if (args < 3) { - type = null; - } - return new FakeBlob( - this.data.slice(start, args > 1 ? end : this.data.length) - , type - , this.encoding - ); - }; - FB_proto.toString = function() { - return "[object Blob]"; - }; - return FakeBlobBuilder; - }(view)); - - return function Blob(blobParts, options) { - var type = options ? (options.type || "") : ""; - var builder = new BlobBuilder(); - if (blobParts) { - for (var i = 0, len = blobParts.length; i < len; i++) { - builder.append(blobParts[i]); - } - } - return builder.getBlob(type); - }; -}(typeof self !== "undefined" && self || typeof window !== "undefined" && window || this.content || this)); diff --git a/packages/wekan-cfs-data-man/client/data-man-api.js b/packages/wekan-cfs-data-man/client/data-man-api.js deleted file mode 100644 index 709fba654..000000000 --- a/packages/wekan-cfs-data-man/client/data-man-api.js +++ /dev/null @@ -1,302 +0,0 @@ -/** - * @method DataMan - * @public - * @constructor - * @param {File|Blob|ArrayBuffer|Uint8Array|String} data The data that you want to manipulate. - * @param {String} [type] The data content (MIME) type, if known. Required if the first argument is an ArrayBuffer, Uint8Array, or URL - */ -DataMan = function DataMan(data, type) { - var self = this; - - if (!data) { - throw new Error("DataMan constructor requires a data argument"); - } - - // The end result of all this is that we will have one of the following set: - // - self.blob - // - self.url - // Unless we already have in-memory data, we don't load anything into memory - // and instead rely on obtaining a read stream when the time comes. - if (typeof File !== "undefined" && data instanceof File) { - self.blob = data; // File inherits from Blob so this is OK - self._type = data.type; - } else if (typeof Blob !== "undefined" && data instanceof Blob) { - self.blob = data; - self._type = data.type; - } else if (typeof ArrayBuffer !== "undefined" && data instanceof ArrayBuffer || EJSON.isBinary(data)) { - if (typeof Blob === "undefined") { - throw new Error("Browser must support Blobs to handle an ArrayBuffer or Uint8Array"); - } - if (!type) { - throw new Error("DataMan constructor requires a type argument when passed an ArrayBuffer or Uint8Array"); - } - self.blob = new Blob([data], {type: type}); - self._type = type; - } else if (typeof data === "string") { - if (data.slice(0, 5) === "data:") { - self._type = data.slice(5, data.indexOf(';')); - self.blob = dataURItoBlob(data, self._type); - } else if (data.slice(0, 5) === "http:" || data.slice(0, 6) === "https:") { - if (!type) { - throw new Error("DataMan constructor requires a type argument when passed a URL"); - } - self.url = data; - self._type = type; - } else { - throw new Error("DataMan constructor received unrecognized data string"); - } - } else { - throw new Error("DataMan constructor received data that it doesn't support"); - } -}; - -/** - * @method DataMan.prototype.getBlob - * @public - * @param {Function} [callback] - callback(error, blob) - * @returns {undefined|Blob} - * - * Passes a Blob representing this data to a callback or returns - * the Blob if no callback is provided. A callback is required - * if getting a Blob for a URL. - */ -DataMan.prototype.getBlob = function dataManGetBlob(callback) { - var self = this; - - if (callback) { - if (self.blob) { - callback(null, self.blob); - } else if (self.url) { - var xhr = new XMLHttpRequest(); - xhr.open('GET', self.url, true); - xhr.responseType = "blob"; - xhr.onload = function(data) { - self.blob = xhr.response; - callback(null, self.blob); - }; - xhr.onerror = function(err) { - callback(err); - }; - xhr.send(); - } - } else { - if (self.url) - throw new Error('DataMan.getBlob requires a callback when managing a URL'); - return self.blob; - } -}; - -/** - * @method DataMan.prototype.getBinary - * @public - * @param {Number} [start] - First byte position to read. - * @param {Number} [end] - Last byte position to read. - * @param {Function} callback - callback(error, binaryData) - * @returns {undefined} - * - * Passes a Uint8Array representing this data to a callback. - */ -DataMan.prototype.getBinary = function dataManGetBinary(start, end, callback) { - var self = this; - - if (typeof start === "function") { - callback = start; - } - callback = callback || defaultCallback; - - function read(blob) { - if (typeof FileReader === "undefined") { - callback(new Error("Browser does not support FileReader")); - return; - } - - var reader = new FileReader(); - reader.onload = function(evt) { - callback(null, new Uint8Array(evt.target.result)); - }; - reader.onerror = function(err) { - callback(err); - }; - reader.readAsArrayBuffer(blob); - } - - self.getBlob(function (error, blob) { - if (error) { - callback(error); - } else { - if (typeof start === "number" && typeof end === "number") { - var size = blob.size; - // Return the requested chunk of binary data - if (start >= size) { - callback(new Error("DataMan.getBinary: start position beyond end of data (" + size + ")")); - return; - } - end = Math.min(size, end); - - var slice = blob.slice || blob.webkitSlice || blob.mozSlice; - if (typeof slice === 'undefined') { - callback(new Error('Browser does not support File.slice')); - return; - } - - read(slice.call(blob, start, end, self._type)); - } else { - // Return the entire binary data - read(blob); - } - } - }); - -}; - -/** @method DataMan.prototype.saveAs - * @public - * @param {String} [filename] - * @return {undefined} - * - * Tells the browser to save the data like a normal downloaded file, - * using the provided filename. - * - */ -DataMan.prototype.saveAs = function dataManSaveAs(filename) { - var self = this; - - if (typeof window === "undefined") - throw new Error("window must be defined to use saveLocal"); - - if (!window.saveAs) { - console.warn('DataMan.saveAs: window.saveAs not supported by this browser - add cfs-filesaver package'); - return; - } - - self.getBlob(function (error, blob) { - if (error) { - throw error; - } else { - window.saveAs(blob, filename); - } - }); -}; - -/** - * @method DataMan.prototype.getDataUri - * @public - * @param {function} callback callback(err, dataUri) - */ -DataMan.prototype.getDataUri = function dataManGetDataUri(callback) { - // XXX: We could consider using: URL.createObjectURL(blob); - // This will create a reference to the blob data instead of a clone - // This is part of the File API - as the rest - Not sure how to generally - // support from IE10, FF26, Chrome 31, safari 7, opera 19, ios 6, android 4 - - var self = this; - - if (typeof callback !== 'function') - throw new Error("getDataUri requires callback function"); - - if (typeof FileReader === "undefined") { - callback(new Error("Browser does not support FileReader")); - return; - } - - var fileReader = new FileReader(); - fileReader.onload = function(event) { - var dataUri = event.target.result; - callback(null, dataUri); - }; - fileReader.onerror = function(err) { - callback(err); - }; - - self.getBlob(function (error, blob) { - if (error) { - callback(error); - } else { - fileReader.readAsDataURL(blob); - } - }); -}; - -/** - * @method DataMan.prototype.size - * @public - * @param {function} [callback] callback(err, size) - * - * Passes the size of the data to the callback, if provided, - * or returns it. A callback is required to get the size of a URL on the client. - */ -DataMan.prototype.size = function dataManSize(callback) { - var self = this; - - if (callback) { - if (typeof self._size === "number") { - callback(null, self._size); - } else { - self.getBlob(function (error, blob) { - if (error) { - callback(error); - } else { - self._size = blob.size; - callback(null, self._size); - } - }); - } - } else { - if (self.url) { - throw new Error("On the client, DataMan.size requires a callback when getting size for a URL on the client"); - } else if (typeof self._size === "number") { - return self._size; - } else { - var blob = self.getBlob(); - self._size = blob.size; - return self._size; - } - } -}; - -/** - * @method DataMan.prototype.type - * @public - * - * Returns the type of the data. - */ -DataMan.prototype.type = function dataManType() { - return this._type; -}; - -/** - * @method dataURItoBlob - * @private - * @param {String} dataURI The data URI - * @param {String} dataTYPE The content type - * @returns {Blob} A new Blob instance - * - * Converts a data URI to a Blob. - */ -function dataURItoBlob(dataURI, dataTYPE) { - var str = atob(dataURI.split(',')[1]), array = []; - for(var i = 0; i < str.length; i++) array.push(str.charCodeAt(i)); - return new Blob([new Uint8Array(array)], {type: dataTYPE}); -} - -/** - * @method defaultCallback - * @private - * @param {Error} [err] - * @returns {undefined} - * - * Can be used as a default callback for client methods that need a callback. - * Simply throws the provided error if there is one. - */ -function defaultCallback(err) { - if (err) { - // Show gentle error if Meteor error - if (err instanceof Meteor.Error) { - console.error(err.message); - } else { - // Normal error, just throw error - throw err; - } - - } -} diff --git a/packages/wekan-cfs-data-man/internal.api.md b/packages/wekan-cfs-data-man/internal.api.md deleted file mode 100644 index dd86af961..000000000 --- a/packages/wekan-cfs-data-man/internal.api.md +++ /dev/null @@ -1,674 +0,0 @@ -## Public and Private API ## - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -*** - -__File: ["client/Blob.js"](client/Blob.js) Where: {client}__ - -*** - -### if {any}  Client ### - -``` -Blob.js -A Blob implementation. -2013-06-20 -By Eli Grey, http: -By Devin Samarin, https: -License: X11/MIT -See LICENSE.md -``` - - -> ```if ((typeof Blob !== ``` [client/Blob.js:17](client/Blob.js#L17) - - -- - -### if {any}  Client ### - -``` -global unescape jslint bitwise: true, regexp: true, confusion: true, es5: true, vars: true, white: true, -plusplus: true -``` - -> ```if ((typeof Blob !== ``` [client/Blob.js:17](client/Blob.js#L17) - - -*** - -__File: ["client/data-man-api.js"](client/data-man-api.js) Where: {client}__ - -*** - -### new DataMan(data, [type])  Client ### - - -__Arguments__ - -* __data__ *{[File](#File)|[Blob](#Blob)|ArrayBuffer|Uint8Array|String}* - - The data that you want to manipulate. - -* __type__ *{String}* (Optional) - - The data content (MIME) type, if known. Required if the first argument is an ArrayBuffer, Uint8Array, or URL - - - -> ```DataMan = function DataMan(data, type) { ...``` [client/data-man-api.js:8](client/data-man-api.js#L8) - - -- - -### *dataman*.getBlob(callback)  Client ### - -*This method __getBlob__ is defined in `prototype` of `DataMan`* - -__Arguments__ - -* __callback__ *{Function}* - - callback(error, blob) - - -__Returns__ *{undefined}* - - -Passes a Blob representing this data to a callback. - -> ```DataMan.prototype.getBlob = function dataManGetBlob(callback) { ...``` [client/data-man-api.js:52](client/data-man-api.js#L52) - - -- - -### *dataman*.getBinary([start], [end], callback)  Client ### - -*This method __getBinary__ is defined in `prototype` of `DataMan`* - -__Arguments__ - -* __start__ *{Number}* (Optional) - - First byte position to read. - -* __end__ *{Number}* (Optional) - - Last byte position to read. - -* __callback__ *{Function}* - - callback(error, binaryData) - - -__Returns__ *{undefined}* - - -Passes a Uint8Array representing this data to a callback. - -> ```DataMan.prototype.getBinary = function dataManGetBinary(start, end, callback) { ...``` [client/data-man-api.js:84](client/data-man-api.js#L84) - - -- - -### *dataman*.saveAs([filename])  Client ### - -*This method __saveAs__ is defined in `prototype` of `DataMan`* - -__Arguments__ - -* __filename__ *{String}* (Optional) - -__Returns__ *{undefined}* - -Tells the browser to save the data like a normal downloaded file, -using the provided filename. - - -> ```DataMan.prototype.saveAs = function dataManSaveAs(filename) { ...``` [client/data-man-api.js:146](client/data-man-api.js#L146) - - -- - -### *dataman*.getDataUri(callback)  Client ### - -*This method __getDataUri__ is defined in `prototype` of `DataMan`* - -__Arguments__ - -* __callback__ *{function}* - - callback(err, dataUri) - - - -> ```DataMan.prototype.getDataUri = function dataManGetDataUri(callback) { ...``` [client/data-man-api.js:166](client/data-man-api.js#L166) - - -- - -### *dataman*.type()  Client ### - -*This method __type__ is defined in `prototype` of `DataMan`* - - -Returns the type of the data. - -> ```DataMan.prototype.type = function dataManType() { ...``` [client/data-man-api.js:227](client/data-man-api.js#L227) - - -- - -### dataURItoBlob(dataURI, dataTYPE)  undefined ### - -*This method is private* - -__Arguments__ - -* __dataURI__ *{String}* - - The data URI - -* __dataTYPE__ *{String}* - - The content type - - -__Returns__ *{Blob}* -A new Blob instance - - -Converts a data URI to a Blob. - -> ```function dataURItoBlob(dataURI, dataTYPE) { ...``` [client/data-man-api.js:240](client/data-man-api.js#L240) - - -- - -### defaultCallback([err])  undefined ### - -*This method is private* - -__Arguments__ - -* __err__ *{[Error](#Error)}* (Optional) - -__Returns__ *{undefined}* - - -Can be used as a default callback for client methods that need a callback. -Simply throws the provided error if there is one. - -> ```function defaultCallback(err) { ...``` [client/data-man-api.js:255](client/data-man-api.js#L255) - - -*** - -__File: ["server/data-man-api.js"](server/data-man-api.js) Where: {server}__ - -*** - -### new DataMan(data, [type])  Server ### - - -__Arguments__ - -* __data__ *{Buffer|ArrayBuffer|Uint8Array|String}* - - The data that you want to manipulate. - -* __type__ *{String}* (Optional) - - The data content (MIME) type, if known. Required if the first argument is a Buffer, ArrayBuffer, Uint8Array, or URL - - - -> ```DataMan = function DataMan(data, type) { ...``` [server/data-man-api.js:10](server/data-man-api.js#L10) - - -- - -### *dataman*.getBuffer([callback])  Server ### - -*This method __getBuffer__ is defined in `prototype` of `DataMan`* - -__Arguments__ - -* __callback__ *{function}* (Optional) - - callback(err, buffer) - - -__Returns__ *{Buffer|undefined}* - - -Returns a Buffer representing this data, or passes the Buffer to a callback. - -> ```DataMan.prototype.getBuffer = function dataManGetBuffer(callback) { ...``` [server/data-man-api.js:54](server/data-man-api.js#L54) - - -- - -### *dataman*.saveToFile()  Server ### - -*This method __saveToFile__ is defined in `prototype` of `DataMan`* - -__Returns__ *{undefined}* - - -Saves this data to a filepath on the local filesystem. - -> ```DataMan.prototype.saveToFile = function dataManSaveToFile(filePath) { ...``` [server/data-man-api.js:66](server/data-man-api.js#L66) - - -- - -### *dataman*.getDataUri([callback])  Server ### - -*This method __getDataUri__ is defined in `prototype` of `DataMan`* - -__Arguments__ - -* __callback__ *{function}* (Optional) - - callback(err, dataUri) - - - -If no callback, returns the data URI. - -> ```DataMan.prototype.getDataUri = function dataManGetDataUri(callback) { ...``` [server/data-man-api.js:84](server/data-man-api.js#L84) - - -- - -### *dataman*.createReadStream()  Server ### - -*This method __createReadStream__ is defined in `prototype` of `DataMan`* - - -Returns a read stream for the data. - -> ```DataMan.prototype.createReadStream = function dataManCreateReadStream() { ...``` [server/data-man-api.js:95](server/data-man-api.js#L95) - - -- - -### *dataman*.size([callback])  Server ### - -*This method __size__ is defined in `prototype` of `DataMan`* - -__Arguments__ - -* __callback__ *{function}* (Optional) - - callback(err, size) - - - -If no callback, returns the size in bytes of the data. - -> ```DataMan.prototype.size = function dataManSize(callback) { ...``` [server/data-man-api.js:106](server/data-man-api.js#L106) - - -- - -### *dataman*.type()  Server ### - -*This method __type__ is defined in `prototype` of `DataMan`* - - -Returns the type of the data. - -> ```DataMan.prototype.type = function dataManType() { ...``` [server/data-man-api.js:117](server/data-man-api.js#L117) - - -*** - -__File: ["server/data-man-buffer.js"](server/data-man-buffer.js) Where: {server}__ - -*** - -### new *dataman*.Buffer(buffer, type)  Server ### - -*This method __Buffer__ is defined in `DataMan`* - -__Arguments__ - -* __buffer__ *{Buffer}* -* __type__ *{String}* - - The data content (MIME) type. - - - -> ```DataMan.Buffer = function DataManBuffer(buffer, type) { ...``` [server/data-man-buffer.js:10](server/data-man-buffer.js#L10) - - -- - -### *datamanBuffer*.getBuffer(callback)  Server ### - -*This method is private* -*This method __getBuffer__ is defined in `prototype` of `DataMan.Buffer`* - -__Arguments__ - -* __callback__ *{function}* - - callback(err, buffer) - - -__Returns__ *{Buffer|undefined}* - - -Passes a Buffer representing the data to a callback. - -> ```DataMan.Buffer.prototype.getBuffer = function dataManBufferGetBuffer(callback) { ...``` [server/data-man-buffer.js:24](server/data-man-buffer.js#L24) - - -- - -### *datamanBuffer*.getDataUri(callback)  Server ### - -*This method is private* -*This method __getDataUri__ is defined in `prototype` of `DataMan.Buffer`* - -__Arguments__ - -* __callback__ *{function}* - - callback(err, dataUri) - - - -Passes a data URI representing the data in the buffer to a callback. - -> ```DataMan.Buffer.prototype.getDataUri = function dataManBufferGetDataUri(callback) { ...``` [server/data-man-buffer.js:35](server/data-man-buffer.js#L35) - - -- - -### *datamanBuffer*.createReadStream()  Server ### - -*This method is private* -*This method __createReadStream__ is defined in `prototype` of `DataMan.Buffer`* - - -Returns a read stream for the data. - -> ```DataMan.Buffer.prototype.createReadStream = function dataManBufferCreateReadStream() { ...``` [server/data-man-buffer.js:51](server/data-man-buffer.js#L51) - - -- - -### *datamanBuffer*.size(callback)  Server ### - -*This method is private* -*This method __size__ is defined in `prototype` of `DataMan.Buffer`* - -__Arguments__ - -* __callback__ *{function}* - - callback(err, size) - - - -Passes the size in bytes of the data in the buffer to a callback. - -> ```DataMan.Buffer.prototype.size = function dataManBufferSize(callback) { ...``` [server/data-man-buffer.js:62](server/data-man-buffer.js#L62) - - -- - -### *datamanBuffer*.type()  Server ### - -*This method is private* -*This method __type__ is defined in `prototype` of `DataMan.Buffer`* - - -Returns the type of the data. - -> ```DataMan.Buffer.prototype.type = function dataManBufferType() { ...``` [server/data-man-buffer.js:80](server/data-man-buffer.js#L80) - - -*** - -__File: ["server/data-man-datauri.js"](server/data-man-datauri.js) Where: {server}__ - -*** - -### new *dataman*.DataURI(dataUri)  Server ### - -*This method __DataURI__ is defined in `DataMan`* - -__Arguments__ - -* __dataUri__ *{String}* - - -> ```DataMan.DataURI = function DataManDataURI(dataUri) { ...``` [server/data-man-datauri.js:7](server/data-man-datauri.js#L7) - - -*** - -__File: ["server/data-man-filepath.js"](server/data-man-filepath.js) Where: {server}__ - -*** - -### new *dataman*.FilePath(filepath, [type])  Server ### - -*This method __FilePath__ is defined in `DataMan`* - -__Arguments__ - -* __filepath__ *{String}* -* __type__ *{String}* (Optional) - - The data content (MIME) type. Will lookup from file if not passed. - - - -> ```DataMan.FilePath = function DataManFilePath(filepath, type) { ...``` [server/data-man-filepath.js:11](server/data-man-filepath.js#L11) - - -- - -### *datamanFilepath*.getBuffer(callback)  Server ### - -*This method is private* -*This method __getBuffer__ is defined in `prototype` of `DataMan.FilePath`* - -__Arguments__ - -* __callback__ *{function}* - - callback(err, buffer) - - -__Returns__ *{Buffer|undefined}* - - -Passes a Buffer representing the data to a callback. - -> ```DataMan.FilePath.prototype.getBuffer = function dataManFilePathGetBuffer(callback) { ...``` [server/data-man-filepath.js:25](server/data-man-filepath.js#L25) - - -- - -### *datamanFilepath*.getDataUri(callback)  Server ### - -*This method is private* -*This method __getDataUri__ is defined in `prototype` of `DataMan.FilePath`* - -__Arguments__ - -* __callback__ *{function}* - - callback(err, dataUri) - - - -Passes a data URI representing the data to a callback. - -> ```DataMan.FilePath.prototype.getDataUri = function dataManFilePathGetDataUri(callback) { ...``` [server/data-man-filepath.js:43](server/data-man-filepath.js#L43) - - -- - -### *datamanFilepath*.createReadStream()  Server ### - -*This method is private* -*This method __createReadStream__ is defined in `prototype` of `DataMan.FilePath`* - - -Returns a read stream for the data. - -> ```DataMan.FilePath.prototype.createReadStream = function dataManFilePathCreateReadStream() { ...``` [server/data-man-filepath.js:67](server/data-man-filepath.js#L67) - - -- - -### *datamanFilepath*.size(callback)  Server ### - -*This method is private* -*This method __size__ is defined in `prototype` of `DataMan.FilePath`* - -__Arguments__ - -* __callback__ *{function}* - - callback(err, size) - - - -Passes the size in bytes of the data to a callback. - -> ```DataMan.FilePath.prototype.size = function dataManFilePathSize(callback) { ...``` [server/data-man-filepath.js:79](server/data-man-filepath.js#L79) - - -- - -### *datamanFilepath*.type()  Server ### - -*This method is private* -*This method __type__ is defined in `prototype` of `DataMan.FilePath`* - - -Returns the type of the data. - -> ```DataMan.FilePath.prototype.type = function dataManFilePathType() { ...``` [server/data-man-filepath.js:104](server/data-man-filepath.js#L104) - - -*** - -__File: ["server/data-man-url.js"](server/data-man-url.js) Where: {server}__ - -*** - -### new *dataman*.URL(url, type)  Server ### - -*This method __URL__ is defined in `DataMan`* - -__Arguments__ - -* __url__ *{String}* -* __type__ *{String}* - - The data content (MIME) type. - - - -> ```DataMan.URL = function DataManURL(url, type) { ...``` [server/data-man-url.js:10](server/data-man-url.js#L10) - - -- - -### *datamanUrl*.getBuffer(callback)  Server ### - -*This method is private* -*This method __getBuffer__ is defined in `prototype` of `DataMan.URL`* - -__Arguments__ - -* __callback__ *{function}* - - callback(err, buffer) - - -__Returns__ *{Buffer|undefined}* - - -Passes a Buffer representing the data at the URL to a callback. - -> ```DataMan.URL.prototype.getBuffer = function dataManUrlGetBuffer(callback) { ...``` [server/data-man-url.js:24](server/data-man-url.js#L24) - - -- - -### *datamanUrl*.getDataUri(callback)  Server ### - -*This method is private* -*This method __getDataUri__ is defined in `prototype` of `DataMan.URL`* - -__Arguments__ - -* __callback__ *{function}* - - callback(err, dataUri) - - - -Passes a data URI representing the data at the URL to a callback. - -> ```DataMan.URL.prototype.getDataUri = function dataManUrlGetDataUri(callback) { ...``` [server/data-man-url.js:57](server/data-man-url.js#L57) - - -- - -### *datamanUrl*.createReadStream()  Server ### - -*This method is private* -*This method __createReadStream__ is defined in `prototype` of `DataMan.URL`* - - -Returns a read stream for the data. - -> ```DataMan.URL.prototype.createReadStream = function dataManUrlCreateReadStream() { ...``` [server/data-man-url.js:85](server/data-man-url.js#L85) - - -- - -### *datamanUrl*.size(callback)  Server ### - -*This method is private* -*This method __size__ is defined in `prototype` of `DataMan.URL`* - -__Arguments__ - -* __callback__ *{function}* - - callback(err, size) - - - -Returns the size in bytes of the data at the URL. - -> ```DataMan.URL.prototype.size = function dataManUrlSize(callback) { ...``` [server/data-man-url.js:97](server/data-man-url.js#L97) - - -- - -### *datamanUrl*.type()  Server ### - -*This method is private* -*This method __type__ is defined in `prototype` of `DataMan.URL`* - - -Returns the type of the data. - -> ```DataMan.URL.prototype.type = function dataManUrlType() { ...``` [server/data-man-url.js:121](server/data-man-url.js#L121) - - diff --git a/packages/wekan-cfs-data-man/package.js b/packages/wekan-cfs-data-man/package.js deleted file mode 100644 index f0c9062fc..000000000 --- a/packages/wekan-cfs-data-man/package.js +++ /dev/null @@ -1,48 +0,0 @@ -Package.describe({ - name: 'wekan-cfs-data-man', - version: '0.0.6', - summary: 'A data manager, allowing you to attach various types of data and get it back in various other types', - git: 'https://github.com/zcfs/Meteor-data-man.git' -}); - -Npm.depends({ - mime: "1.2.11", - 'buffer-stream-reader': "0.1.1", - //request: "2.44.0", - // We use a specific commit from a fork of "request" package for now; we need fix for - // https://github.com/mikeal/request/issues/887 (https://github.com/zcfs/Meteor-CollectionFS/issues/347) - request: "https://github.com/wekan/request", - temp: "0.7.0" // for tests only -}); - -Package.onUse(function(api) { - api.versionsFrom('1.0'); - - api.use(['ejson']); - - api.use(['wekan-cfs-filesaver@0.0.6'], {weak: true}); - - api.export('DataMan'); - - api.addFiles([ - 'client/Blob.js', //polyfill for browsers without Blob constructor; currently necessary for phantomjs support, too - 'client/data-man-api.js' - ], 'client'); - - api.addFiles([ - 'server/data-man-api.js', - 'server/data-man-buffer.js', - 'server/data-man-datauri.js', - 'server/data-man-filepath.js', - 'server/data-man-url.js', - 'server/data-man-readstream.js' - ], 'server'); - -}); - -Package.onTest(function (api) { - api.use(['wekan-cfs-data-man', 'http', 'tinytest', 'test-helpers', 'wekan-cfs-http-methods@0.0.29']); - - api.addFiles(['tests/common.js', 'tests/client-tests.js'], 'client'); - api.addFiles(['tests/common.js', 'tests/server-tests.js'], 'server'); -}); diff --git a/packages/wekan-cfs-data-man/server/data-man-api.js b/packages/wekan-cfs-data-man/server/data-man-api.js deleted file mode 100644 index 58bd2bdf0..000000000 --- a/packages/wekan-cfs-data-man/server/data-man-api.js +++ /dev/null @@ -1,176 +0,0 @@ -/* global DataMan:true, Buffer */ - -var fs = Npm.require("fs"); -var Readable = Npm.require('stream').Readable; - -/** - * @method DataMan - * @public - * @constructor - * @param {Buffer|ArrayBuffer|Uint8Array|String} data The data that you want to manipulate. - * @param {String} [type] The data content (MIME) type, if known. Required if the first argument is a Buffer, ArrayBuffer, Uint8Array, or URL - * @param {Object} [options] Currently used only to pass options for the GET request when `data` is a URL. - */ -DataMan = function DataMan(data, type, options) { - var self = this, buffer; - - if (!data) { - throw new Error("DataMan constructor requires a data argument"); - } - - // The end result of all this is that we will have this.source set to a correct - // data type handler. We are simply detecting what the data arg is. - // - // Unless we already have in-memory data, we don't load anything into memory - // and instead rely on obtaining a read stream when the time comes. - if (typeof Buffer !== "undefined" && data instanceof Buffer) { - if (!type) { - throw new Error("DataMan constructor requires a type argument when passed a Buffer"); - } - self.source = new DataMan.Buffer(data, type); - } else if (typeof ArrayBuffer !== "undefined" && data instanceof ArrayBuffer) { - if (typeof Buffer === "undefined") { - throw new Error("Buffer support required to handle an ArrayBuffer"); - } - if (!type) { - throw new Error("DataMan constructor requires a type argument when passed an ArrayBuffer"); - } - buffer = new Buffer(new Uint8Array(data)); - self.source = new DataMan.Buffer(buffer, type); - } else if (EJSON.isBinary(data)) { - if (typeof Buffer === "undefined") { - throw new Error("Buffer support required to handle an ArrayBuffer"); - } - if (!type) { - throw new Error("DataMan constructor requires a type argument when passed a Uint8Array"); - } - buffer = new Buffer(data); - self.source = new DataMan.Buffer(buffer, type); - } else if (typeof Readable !== "undefined" && data instanceof Readable) { - if (!type) { - throw new Error("DataMan constructor requires a type argument when passed a stream.Readable"); - } - self.source = new DataMan.ReadStream(data, type); - } else if (typeof data === "string") { - if (data.slice(0, 5) === "data:") { - self.source = new DataMan.DataURI(data); - } else if (data.slice(0, 5) === "http:" || data.slice(0, 6) === "https:") { - if (!type) { - throw new Error("DataMan constructor requires a type argument when passed a URL"); - } - self.source = new DataMan.URL(data, type, options); - } else { - // assume it's a filepath - self.source = new DataMan.FilePath(data, type); - } - } else { - throw new Error("DataMan constructor received data that it doesn't support"); - } -}; - -/** - * @method DataMan.prototype.getBuffer - * @public - * @param {function} [callback] callback(err, buffer) - * @returns {Buffer|undefined} - * - * Returns a Buffer representing this data, or passes the Buffer to a callback. - */ -DataMan.prototype.getBuffer = function dataManGetBuffer(callback) { - var self = this; - return callback ? self.source.getBuffer(callback) : Meteor.wrapAsync(bind(self.source.getBuffer, self.source))(); -}; - -function _saveToFile(readStream, filePath, callback) { - var writeStream = fs.createWriteStream(filePath); - writeStream.on('close', Meteor.bindEnvironment(function () { - callback(); - }, function (error) { callback(error); })); - writeStream.on('error', Meteor.bindEnvironment(function (error) { - callback(error); - }, function (error) { callback(error); })); - readStream.pipe(writeStream); -} - -/** - * @method DataMan.prototype.saveToFile - * @public - * @param {String} filePath - * @param {Function} callback - * @returns {undefined} - * - * Saves this data to a filepath on the local filesystem. - */ -DataMan.prototype.saveToFile = function dataManSaveToFile(filePath, callback) { - var readStream = this.createReadStream(); - return callback ? _saveToFile(readStream, filePath, callback) : Meteor.wrapAsync(_saveToFile)(readStream, filePath); -}; - -/** - * @method DataMan.prototype.getDataUri - * @public - * @param {function} [callback] callback(err, dataUri) - * - * If no callback, returns the data URI. - */ -DataMan.prototype.getDataUri = function dataManGetDataUri(callback) { - var self = this; - return callback ? self.source.getDataUri(callback) : Meteor.wrapAsync(bind(self.source.getDataUri, self.source))(); -}; - -/** - * @method DataMan.prototype.createReadStream - * @public - * - * Returns a read stream for the data. - */ -DataMan.prototype.createReadStream = function dataManCreateReadStream() { - return this.source.createReadStream(); -}; - -/** - * @method DataMan.prototype.size - * @public - * @param {function} [callback] callback(err, size) - * - * If no callback, returns the size in bytes of the data. - */ -DataMan.prototype.size = function dataManSize(callback) { - var self = this; - return callback ? self.source.size(callback) : Meteor.wrapAsync(bind(self.source.size, self.source))(); -}; - -/** - * @method DataMan.prototype.type - * @public - * - * Returns the type of the data. - */ -DataMan.prototype.type = function dataManType() { - return this.source.type(); -}; - -/* - * "bind" shim; from underscorejs, but we avoid a dependency - */ -var slice = Array.prototype.slice; -var nativeBind = Function.prototype.bind; -var ctor = function(){}; -function isFunction(obj) { - return Object.prototype.toString.call(obj) == '[object Function]'; -} -function bind(func, context) { - var args, bound; - if (nativeBind && func.bind === nativeBind) return nativeBind.apply(func, slice.call(arguments, 1)); - if (!isFunction(func)) throw new TypeError; - args = slice.call(arguments, 2); - return bound = function() { - if (!(this instanceof bound)) return func.apply(context, args.concat(slice.call(arguments))); - ctor.prototype = func.prototype; - var self = new ctor; - ctor.prototype = null; - var result = func.apply(self, args.concat(slice.call(arguments))); - if (Object(result) === result) return result; - return self; - }; -} diff --git a/packages/wekan-cfs-data-man/server/data-man-buffer.js b/packages/wekan-cfs-data-man/server/data-man-buffer.js deleted file mode 100644 index 2b4c47f25..000000000 --- a/packages/wekan-cfs-data-man/server/data-man-buffer.js +++ /dev/null @@ -1,82 +0,0 @@ -var bufferStreamReader = Npm.require('buffer-stream-reader'); - -/** - * @method DataMan.Buffer - * @public - * @constructor - * @param {Buffer} buffer - * @param {String} type The data content (MIME) type. - */ -DataMan.Buffer = function DataManBuffer(buffer, type) { - var self = this; - self.buffer = buffer; - self._type = type; -}; - -/** - * @method DataMan.Buffer.prototype.getBuffer - * @private - * @param {function} callback callback(err, buffer) - * @returns {Buffer|undefined} - * - * Passes a Buffer representing the data to a callback. - */ -DataMan.Buffer.prototype.getBuffer = function dataManBufferGetBuffer(callback) { - callback(null, this.buffer); -}; - -/** - * @method DataMan.Buffer.prototype.getDataUri - * @private - * @param {function} callback callback(err, dataUri) - * - * Passes a data URI representing the data in the buffer to a callback. - */ -DataMan.Buffer.prototype.getDataUri = function dataManBufferGetDataUri(callback) { - var self = this; - if (!self._type) { - callback(new Error("DataMan.getDataUri couldn't get a contentType")); - } else { - var dataUri = "data:" + self._type + ";base64," + self.buffer.toString("base64"); - callback(null, dataUri); - } -}; - -/** - * @method DataMan.Buffer.prototype.createReadStream - * @private - * - * Returns a read stream for the data. - */ -DataMan.Buffer.prototype.createReadStream = function dataManBufferCreateReadStream() { - return new bufferStreamReader(this.buffer); -}; - -/** - * @method DataMan.Buffer.prototype.size - * @param {function} callback callback(err, size) - * @private - * - * Passes the size in bytes of the data in the buffer to a callback. - */ -DataMan.Buffer.prototype.size = function dataManBufferSize(callback) { - var self = this; - - if (typeof self._size === "number") { - callback(null, self._size); - return; - } - - self._size = self.buffer.length; - callback(null, self._size); -}; - -/** - * @method DataMan.Buffer.prototype.type - * @private - * - * Returns the type of the data. - */ -DataMan.Buffer.prototype.type = function dataManBufferType() { - return this._type; -}; diff --git a/packages/wekan-cfs-data-man/server/data-man-datauri.js b/packages/wekan-cfs-data-man/server/data-man-datauri.js deleted file mode 100644 index 59e241efb..000000000 --- a/packages/wekan-cfs-data-man/server/data-man-datauri.js +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @method DataMan.DataURI - * @public - * @constructor - * @param {String} dataUri - */ -DataMan.DataURI = function DataManDataURI(dataUri) { - var self = this; - var pieces = dataUri.match(/^data:(.*);base64,(.*)$/); - var buffer = new Buffer(pieces[2], 'base64'); - return new DataMan.Buffer(buffer, pieces[1]); -}; - -DataMan.DataURI.prototype = DataMan.Buffer.prototype; diff --git a/packages/wekan-cfs-data-man/server/data-man-filepath.js b/packages/wekan-cfs-data-man/server/data-man-filepath.js deleted file mode 100644 index 2f3131708..000000000 --- a/packages/wekan-cfs-data-man/server/data-man-filepath.js +++ /dev/null @@ -1,108 +0,0 @@ -var mime = Npm.require('mime'); -var fs = Npm.require("fs"); - -/** - * @method DataMan.FilePath - * @public - * @constructor - * @param {String} filepath - * @param {String} [type] The data content (MIME) type. Will lookup from file if not passed. - */ -DataMan.FilePath = function DataManFilePath(filepath, type) { - var self = this; - self.filepath = filepath; - self._type = type || mime.lookup(filepath); -}; - -/** - * @method DataMan.FilePath.prototype.getBuffer - * @private - * @param {function} callback callback(err, buffer) - * @returns {Buffer|undefined} - * - * Passes a Buffer representing the data to a callback. - */ -DataMan.FilePath.prototype.getBuffer = function dataManFilePathGetBuffer(callback) { - var self = this; - - // Call node readFile - fs.readFile(self.filepath, Meteor.bindEnvironment(function(err, buffer) { - callback(err, buffer); - }, function(err) { - callback(err); - })); -}; - -/** - * @method DataMan.FilePath.prototype.getDataUri - * @private - * @param {function} callback callback(err, dataUri) - * - * Passes a data URI representing the data to a callback. - */ -DataMan.FilePath.prototype.getDataUri = function dataManFilePathGetDataUri(callback) { - var self = this; - - self.getBuffer(function (error, buffer) { - if (error) { - callback(error); - } else { - if (!self._type) { - callback(new Error("DataMan.getDataUri couldn't get a contentType")); - } else { - var dataUri = "data:" + self._type + ";base64," + buffer.toString("base64"); - buffer = null; - callback(null, dataUri); - } - } - }); -}; - -/** - * @method DataMan.FilePath.prototype.createReadStream - * @private - * - * Returns a read stream for the data. - */ -DataMan.FilePath.prototype.createReadStream = function dataManFilePathCreateReadStream() { - // Stream from filesystem - return fs.createReadStream(this.filepath); -}; - -/** - * @method DataMan.FilePath.prototype.size - * @param {function} callback callback(err, size) - * @private - * - * Passes the size in bytes of the data to a callback. - */ -DataMan.FilePath.prototype.size = function dataManFilePathSize(callback) { - var self = this; - - if (typeof self._size === "number") { - callback(null, self._size); - return; - } - - // We can get the size without buffering - fs.stat(self.filepath, Meteor.bindEnvironment(function (error, stats) { - if (stats && typeof stats.size === "number") { - self._size = stats.size; - callback(null, self._size); - } else { - callback(error); - } - }, function (error) { - callback(error); - })); -}; - -/** - * @method DataMan.FilePath.prototype.type - * @private - * - * Returns the type of the data. - */ -DataMan.FilePath.prototype.type = function dataManFilePathType() { - return this._type; -}; diff --git a/packages/wekan-cfs-data-man/server/data-man-readstream.js b/packages/wekan-cfs-data-man/server/data-man-readstream.js deleted file mode 100644 index fbfb20391..000000000 --- a/packages/wekan-cfs-data-man/server/data-man-readstream.js +++ /dev/null @@ -1,80 +0,0 @@ -/* global DataMan */ - -var PassThrough = Npm.require('stream').PassThrough; - -/** - * @method DataMan.ReadStream - * @public - * @constructor - * @param {ReadStream} stream - * @param {String} type The data content (MIME) type. - */ -DataMan.ReadStream = function DataManBuffer(stream, type) { - var self = this; - - // Create a bufferable / paused new stream... - var pt = new PassThrough(); - - // Pipe provided read stream into pass-through stream - stream.pipe(pt); - - // Set pass-through stream reference - self.stream = pt; - - // Set type as provided - self._type = type; -}; - -/** - * @method DataMan.ReadStream.prototype.getBuffer - * @private - * @param {function} callback callback(err, buffer) - * @returns {undefined} - * - * Passes a Buffer representing the data to a callback. - */ -DataMan.ReadStream.prototype.getBuffer = function dataManReadStreamGetBuffer(/*callback*/) { - // TODO implement as passthrough stream? -}; - -/** - * @method DataMan.ReadStream.prototype.getDataUri - * @private - * @param {function} callback callback(err, dataUri) - * - * Passes a data URI representing the data in the stream to a callback. - */ -DataMan.ReadStream.prototype.getDataUri = function dataManReadStreamGetDataUri(/*callback*/) { - // TODO implement as passthrough stream? -}; - -/** - * @method DataMan.ReadStream.prototype.createReadStream - * @private - * - * Returns a read stream for the data. - */ -DataMan.ReadStream.prototype.createReadStream = function dataManReadStreamCreateReadStream() { - return this.stream; -}; - -/** - * @method DataMan.ReadStream.prototype.size - * @param {function} callback callback(err, size) - * @private - * - * Passes the size in bytes of the data in the stream to a callback. - */ -DataMan.ReadStream.prototype.size = function dataManReadStreamSize(callback) { - callback(0); // will determine from stream later -}; - -/** - * @method DataMan.ReadStream.prototype.type - * @private - * - * Returns the type of the data. - */ -DataMan.ReadStream.prototype.type = function dataManReadStreamType() { - return this._type; -}; diff --git a/packages/wekan-cfs-data-man/server/data-man-url.js b/packages/wekan-cfs-data-man/server/data-man-url.js deleted file mode 100644 index 08e61f46f..000000000 --- a/packages/wekan-cfs-data-man/server/data-man-url.js +++ /dev/null @@ -1,133 +0,0 @@ -var request = Npm.require("request"); - -/** - * @method DataMan.URL - * @public - * @constructor - * @param {String} url - * @param {String} type The data content (MIME) type. - */ -DataMan.URL = function DataManURL(url, type, options) { - var self = this; - options = options || {}; - - self.url = url; - self._type = type; - - // This is some code borrowed from the http package. Hopefully - // we can eventually use HTTP pkg directly instead of 'request' - // once it supports streams and buffers and such. (`request` takes - // and `auth` option, too, but not of the same form as `HTTP`.) - if (options.auth) { - if (options.auth.indexOf(':') < 0) - throw new Error('auth option should be of the form "username:password"'); - options.headers = options.headers || {}; - options.headers['Authorization'] = "Basic "+ - (new Buffer(options.auth, "ascii")).toString("base64"); - delete options.auth; - } - - self.urlOpts = options; -}; - -/** - * @method DataMan.URL.prototype.getBuffer - * @private - * @param {function} callback callback(err, buffer) - * @returns {Buffer|undefined} - * - * Passes a Buffer representing the data at the URL to a callback. - */ -DataMan.URL.prototype.getBuffer = function dataManUrlGetBuffer(callback) { - var self = this; - - request(_.extend({ - url: self.url, - method: "GET", - encoding: null, - jar: false - }, self.urlOpts), Meteor.bindEnvironment(function(err, res, body) { - if (err) { - callback(err); - } else { - self._type = res.headers['content-type']; - callback(null, body); - } - }, function(err) { - callback(err); - })); -}; - -/** - * @method DataMan.URL.prototype.getDataUri - * @private - * @param {function} callback callback(err, dataUri) - * - * Passes a data URI representing the data at the URL to a callback. - */ -DataMan.URL.prototype.getDataUri = function dataManUrlGetDataUri(callback) { - var self = this; - - self.getBuffer(function (error, buffer) { - if (error) { - callback(error); - } else { - if (!self._type) { - callback(new Error("DataMan.getDataUri couldn't get a contentType")); - } else { - var dataUri = "data:" + self._type + ";base64," + buffer.toString("base64"); - callback(null, dataUri); - } - } - }); -}; - -/** - * @method DataMan.URL.prototype.createReadStream - * @private - * - * Returns a read stream for the data. - */ -DataMan.URL.prototype.createReadStream = function dataManUrlCreateReadStream() { - var self = this; - // Stream from URL - return request(_.extend({ - url: self.url, - method: "GET" - }, self.urlOpts)); -}; - -/** - * @method DataMan.URL.prototype.size - * @param {function} callback callback(err, size) - * @private - * - * Returns the size in bytes of the data at the URL. - */ -DataMan.URL.prototype.size = function dataManUrlSize(callback) { - var self = this; - - if (typeof self._size === "number") { - callback(null, self._size); - return; - } - - self.getBuffer(function (error, buffer) { - if (error) { - callback(error); - } else { - self._size = buffer.length; - callback(null, self._size); - } - }); -}; - -/** - * @method DataMan.URL.prototype.type - * @private - * - * Returns the type of the data. - */ -DataMan.URL.prototype.type = function dataManUrlType() { - return this._type; -}; diff --git a/packages/wekan-cfs-data-man/tests/client-tests.js b/packages/wekan-cfs-data-man/tests/client-tests.js deleted file mode 100644 index 60e64d3ba..000000000 --- a/packages/wekan-cfs-data-man/tests/client-tests.js +++ /dev/null @@ -1,296 +0,0 @@ -var blobData; -var arrayBufferData; -var binaryData; -var dataUriData; -var urlData; - -// Init with Blob -Tinytest.addAsync('cfs-data - client - Init with Blob', function(test, onComplete) { - var blob = new Blob(['Hello World'], {type : 'text/plain'}); - blobData = new DataMan(blob); - test.instanceOf(blobData.blob, Blob); - test.equal(blobData.type(), "text/plain"); - onComplete(); -}); - -// Init with ArrayBuffer -Tinytest.addAsync('cfs-data - client - Init with ArrayBuffer', function(test, onComplete) { - arrayBufferData = new DataMan(str2ab('Hello World'), "text/plain"); - // Should be converted upon init to a Blob - test.instanceOf(arrayBufferData.blob, Blob); - test.equal(arrayBufferData.type(), "text/plain"); - onComplete(); -}); - -// Init with Binary -Tinytest.addAsync('cfs-data - client - Init with Binary', function(test, onComplete) { - binaryData = new DataMan(new Uint8Array(str2ab('Hello World')), "text/plain"); - // Should be converted upon init to a Blob - test.instanceOf(arrayBufferData.blob, Blob); - test.equal(binaryData.type(), "text/plain"); - onComplete(); -}); - -// Init with data URI string -Tinytest.addAsync('cfs-data - client - Init with data URI string', function(test, onComplete) { - var dataUri = 'data:text/plain;base64,SGVsbG8gV29ybGQ='; //'Hello World' - dataUriData = new DataMan(dataUri); - // Should be converted upon init to a Blob - test.instanceOf(dataUriData.blob, Blob); - test.equal(dataUriData.type(), "text/plain"); //should be extracted from data URI - onComplete(); -}); - -// Init with URL string -Tinytest.addAsync('cfs-data - client - Init with URL string', function(test, onComplete) { - urlData = new DataMan(Meteor.absoluteUrl('test'), "text/plain"); //'Hello World' - // URLs are not converted to Blobs upon init - test.equal(urlData.url, Meteor.absoluteUrl('test')); - test.equal(urlData.type(), "text/plain"); - onComplete(); -}); - -// getBlob -Tinytest.addAsync('cfs-data - client - getBlob', function(test, onComplete) { - var total = 10, done = 0; - function continueIfDone() { - done++; - if (total === done) { - onComplete(); - } - } - - function testBlob(error, blob, testType) { - test.isFalse(!!error, testType + ' got error: ' + (error && error.message)); - test.instanceOf(blob, Blob, testType + ' got no blob'); - - if (blob instanceof Blob) { - var reader = new FileReader(); - reader.addEventListener("load", function(event) { - test.equal(reader.result, 'Hello World', testType + ' got back blob with incorrect data'); - continueIfDone(); - }, false); - reader.addEventListener("error", function(err) { - test.equal(reader.error, null, testType + ' error reading blob as text'); - continueIfDone(); - }, false); - reader.readAsText(blob, 'utf-8'); - } else { - continueIfDone(); - } - } - - // from Blob - blobData.getBlob(function (error, blob) { - testBlob(error, blob, 'getBlob from Blob'); - }); - - // from Blob (no callback) - testBlob(false, blobData.getBlob(), 'getBlob from Blob'); - - // from ArrayBuffer - arrayBufferData.getBlob(function (error, blob) { - testBlob(error, blob, 'getBlob from ArrayBuffer'); - }); - - // from ArrayBuffer (no callback) - testBlob(false, arrayBufferData.getBlob(), 'getBlob from ArrayBuffer'); - - // from binary - binaryData.getBlob(function (error, blob) { - testBlob(error, blob, 'getBlob from binary'); - }); - - // from binary (no callback) - testBlob(false, binaryData.getBlob(), 'getBlob from binary'); - - // from data URI - dataUriData.getBlob(function (error, blob) { - testBlob(error, blob, 'getBlob from data URI'); - }); - - // from data URI (no callback) - testBlob(false, dataUriData.getBlob(), 'getBlob from data URI'); - - // from URL - urlData.getBlob(function (error, blob) { - testBlob(error, blob, 'getBlob from URL'); - }); - - // from URL (no callback) - test.throws(function () { - // callback is required for URLs on the client - urlData.getBlob(); - }); - continueIfDone(); - -}); - -// getBinary -Tinytest.addAsync('cfs-data - client - getBinary', function(test, onComplete) { - var total = 5, done = 0; - function continueIfDone() { - done++; - if (total === done) { - onComplete(); - } - } - - function testBinary(error, binary, testType) { - test.isFalse(!!error, testType + ' got error: ' + (error && error.message)); - test.isTrue(EJSON.isBinary(binary), testType + ' got no binary'); - - if (EJSON.isBinary(binary)) { - test.equal(bin2str(binary), 'Hello World', testType + ' got back binary with incorrect data'); - continueIfDone(); - } else { - continueIfDone(); - } - } - - // from Blob - blobData.getBinary(function (error, binary) { - testBinary(error, binary, 'getBinary from Blob'); - }); - - // from ArrayBuffer - arrayBufferData.getBinary(function (error, binary) { - testBinary(error, binary, 'getBinary from ArrayBuffer'); - }); - - // from binary - binaryData.getBinary(function (error, binary) { - testBinary(error, binary, 'getBinary from binary'); - }); - - // from data URI - dataUriData.getBinary(function (error, binary) { - testBinary(error, binary, 'getBinary from data URI'); - }); - - // from URL - urlData.getBinary(function (error, binary) { - testBinary(error, binary, 'getBinary from URL'); - }); -}); - -// getDataUri -Tinytest.addAsync('cfs-data - client - getDataUri', function(test, onComplete) { - var total = 5, done = 0; - function testURI(error, uri, testType) { - test.isFalse(!!error, testType + ' got error: ' + (error && error.message)); - test.equal(typeof uri, "string", testType + ' got no URI string'); - test.equal(uri, 'data:text/plain;base64,SGVsbG8gV29ybGQ=', testType + ' got invalid URI'); - - done++; - if (total === done) { - onComplete(); - } - } - - // from Blob - blobData.getDataUri(function (error, uri) { - testURI(error, uri, 'getDataUri from Blob'); - }); - - // from ArrayBuffer - arrayBufferData.getDataUri(function (error, uri) { - testURI(error, uri, 'getDataUri from ArrayBuffer'); - }); - - // from binary - binaryData.getDataUri(function (error, uri) { - testURI(error, uri, 'getDataUri from binary'); - }); - - // from data URI - dataUriData.getDataUri(function (error, uri) { - testURI(error, uri, 'getDataUri from data URI'); - }); - - // from URL - urlData.getDataUri(function (error, uri) { - testURI(error, uri, 'getDataUri from URL'); - }); -}); - -// size -Tinytest.addAsync('cfs-data - client - size', function(test, onComplete) { - var total = 10, done = 0; - function continueIfDone() { - done++; - if (total === done) { - onComplete(); - } - } - - function testSize(error, size, testType) { - test.isFalse(!!error, testType + ' got error: ' + (error && error.message)); - test.equal(size, 11, testType + ' got wrong size'); - continueIfDone(); - } - - // from Blob - blobData.size(function (error, size) { - testSize(error, size, 'size from Blob'); - }); - - // from Blob (no callback) - testSize(false, blobData.size(), 'size from Blob'); - - // from ArrayBuffer - arrayBufferData.size(function (error, size) { - testSize(error, size, 'size from ArrayBuffer'); - }); - - // from ArrayBuffer (no callback) - testSize(false, arrayBufferData.size(), 'size from ArrayBuffer'); - - // from binary - binaryData.size(function (error, size) { - testSize(error, size, 'size from binary'); - }); - - // from binary (no callback) - testSize(false, binaryData.size(), 'size from binary'); - - // from data URI - dataUriData.size(function (error, size) { - testSize(error, size, 'size from data URI'); - }); - - // from data URI (no callback) - testSize(false, dataUriData.size(), 'size from data URI'); - - // from URL - urlData.size(function (error, size) { - testSize(error, size, 'size from URL'); - }); - - // from URL (no callback) - test.throws(function () { - // callback is required for URLs on the client - urlData.size(); - }); - continueIfDone(); -}); - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-data-man/tests/common.js b/packages/wekan-cfs-data-man/tests/common.js deleted file mode 100644 index 34eeabc34..000000000 --- a/packages/wekan-cfs-data-man/tests/common.js +++ /dev/null @@ -1,38 +0,0 @@ -// ab2str = function ab2str(buf) { -// return String.fromCharCode(new Uint8Array(buf)); -// } - -bin2str = function bin2str(bufView) { - var length = bufView.length; - var result = ''; - for (var i = 0; i length) { - addition = length - i; - } - try { - // this fails on phantomjs due to old webkit bug; hence the try/catch - result += String.fromCharCode.apply(null, bufView.subarray(i,i+addition)); - } catch (e) { - var dataArray = []; - for (var j = i; j < i+addition; j++) { - dataArray.push(bufView[j]); - } - result += String.fromCharCode.apply(null, dataArray); - } - } - return result; -}; - -ab2str = function ab2str(buffer) { - return bin2str(new Uint8Array(buffer)); -}; - -str2ab = function str2ab(str) { - var buf = new ArrayBuffer(str.length); - var bufView = new Uint8Array(buf); - for (var i=0, strLen=str.length; inew *fs*.File([ref])  Anywhere ### - -*This method __File__ is defined in `FS`* - -__Arguments__ - -* __ref__ *{object|[FS.File](#FS.File)|[data to attach](#data to attach)}* (Optional) - - Another FS.File instance, a filerecord, or some data to pass to attachData - - - -> ```FS.File = function(ref, createdByTransform) { ...``` [fsFile-common.js:8](fsFile-common.js#L8) - - -- - -### *fsFile*.attachData(data, [options], [callback])  Anywhere ### - -*This method __attachData__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __data__ *{[File](#File)|[Blob](#Blob)|Buffer|ArrayBuffer|Uint8Array|String}* - - The data that you want to attach to the file. - -* __options__ *{Object}* (Optional) - - Options - - * __type__ *{String}* (Optional) - - The data content (MIME) type, if known. - - * __headers__ *{String}* (Optional) - - When attaching a URL, headers to be used for the GET request (currently server only) - - * __auth__ *{String}* (Optional) - - When attaching a URL, "username:password" to be used for the GET request (currently server only) - -* __callback__ *{Function}* (Optional) - - Callback function, callback(error). On the client, a callback is required if data is a URL. - - -__Returns__ *{FS.File}* -This FS.File instance. - - - -> ```FS.File.prototype.attachData = function fsFileAttachData(data, options, callback) { ...``` [fsFile-common.js:36](fsFile-common.js#L36) - - -- - -### *fsFile*.uploadProgress()  Anywhere ### - -*This method __uploadProgress__ is defined in `prototype` of `FS.File`* - -__Returns__ *{number}* -The server confirmed upload progress - - -> ```FS.File.prototype.uploadProgress = function() { ...``` [fsFile-common.js:154](fsFile-common.js#L154) - - -- - -### *fsFile*.controlledByDeps()  Anywhere ### - -*This method __controlledByDeps__ is defined in `prototype` of `FS.File`* - -__Returns__ *{FS.Collection}* -Returns true if this FS.File is reactive - - -> Note: Returns true if this FS.File object was created by a FS.Collection -> and we are in a reactive computations. What does this mean? Well it should -> mean that our fileRecord is fully updated by Meteor and we are mounted on -> a collection - -> ```FS.File.prototype.controlledByDeps = function() { ...``` [fsFile-common.js:179](fsFile-common.js#L179) - - -- - -### *fsFile*.getCollection()  Anywhere ### - -*This method __getCollection__ is defined in `prototype` of `FS.File`* - -__Returns__ *{FS.Collection}* -Returns attached collection or undefined if not mounted - - -> ```FS.File.prototype.getCollection = function() { ...``` [fsFile-common.js:189](fsFile-common.js#L189) - - -- - -### *fsFile*.isMounted()  Anywhere ### - -*This method __isMounted__ is defined in `prototype` of `FS.File`* - -__Returns__ *{FS.Collection}* -Returns attached collection or undefined if not mounted - - -> ```FS.File.prototype.isMounted = FS.File.prototype.getCollection;``` [fsFile-common.js:217](fsFile-common.js#L217) - - -- - -### *fsFile*.getFileRecord()  Anywhere ### - -*This method __getFileRecord__ is defined in `prototype` of `FS.File`* - -__Returns__ *{object}* -The filerecord - - -> ```FS.File.prototype.getFileRecord = function() { ...``` [fsFile-common.js:224](fsFile-common.js#L224) - - -- - -### *fsFile*.update(modifier, [options], [callback])  Anywhere ### - -*This method __update__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __modifier__ *{[modifier](#modifier)}* -* __options__ *{object}* (Optional) -* __callback__ *{function}* (Optional) - - -Updates the fileRecord. - -> ```FS.File.prototype.update = function(modifier, options, callback) { ...``` [fsFile-common.js:255](fsFile-common.js#L255) - - -- - -### *fsFile*.remove([callback])  Anywhere ### - -*This method __remove__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __callback__ *{Function}* (Optional) - -__Returns__ *{number}* -Count - - -Remove the current file from its FS.Collection - -> ```FS.File.prototype.remove = function(callback) { ...``` [fsFile-common.js:323](fsFile-common.js#L323) - - -- - -### *fsFile*.getExtension([options])  Anywhere ### - -> __Warning!__ -> This method "FS.File.prototype.getExtension" has deprecated from the API -> Use the `extension` getter/setter method instead. - -*This method __getExtension__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __options__ *{Object}* (Optional) - * __store__ *{String}* (Optional) - - Store name. Default is the original extension. - - -__Returns__ *{string}* -The extension eg.: `jpg` or if not found then an empty string '' - - -> ```FS.File.prototype.getExtension = function(options) { ...``` [fsFile-common.js:364](fsFile-common.js#L364) - - -- - -### *fsFile*.isImage([options])  Anywhere ### - -*This method __isImage__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __options__ *{object}* (Optional) - * __store__ *{string}* (Optional) - - The store we're interested in - - - -Returns true if the copy of this file in the specified store has an image -content type. If the file object is unmounted or doesn't have a copy for -the specified store, or if you don't specify a store, this method checks -the content type of the original file. - -> ```FS.File.prototype.isImage = function(options) { ...``` [fsFile-common.js:393](fsFile-common.js#L393) - - -- - -### *fsFile*.isVideo([options])  Anywhere ### - -*This method __isVideo__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __options__ *{object}* (Optional) - * __store__ *{string}* (Optional) - - The store we're interested in - - - -Returns true if the copy of this file in the specified store has a video -content type. If the file object is unmounted or doesn't have a copy for -the specified store, or if you don't specify a store, this method checks -the content type of the original file. - -> ```FS.File.prototype.isVideo = function(options) { ...``` [fsFile-common.js:408](fsFile-common.js#L408) - - -- - -### *fsFile*.isAudio([options])  Anywhere ### - -*This method __isAudio__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __options__ *{object}* (Optional) - * __store__ *{string}* (Optional) - - The store we're interested in - - - -Returns true if the copy of this file in the specified store has an audio -content type. If the file object is unmounted or doesn't have a copy for -the specified store, or if you don't specify a store, this method checks -the content type of the original file. - -> ```FS.File.prototype.isAudio = function(options) { ...``` [fsFile-common.js:423](fsFile-common.js#L423) - - -- - -### *fsFile*.formattedSize({Object}, {String}, {String})  Anywhere ### - -*This method __formattedSize__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __{Object}__ *{any}* - - options - -* __{String}__ *{any}* - - [options.store=none,display original file size] Which file do you want to get the size of? - -* __{String}__ *{any}* - - [options.formatString='0.00 b'] The `numeral` format string to use. - - -__Returns__ *{String}* -The file size formatted as a human readable string and reactively updated. - - -You must add the `numeral` package to your app before you can use this method. -If info is not found or a size can't be determined, it will show 0. - -> ```FS.File.prototype.formattedSize = function fsFileFormattedSize(options) { ...``` [fsFile-common.js:438](fsFile-common.js#L438) - - -- - -### *fsFile*.isUploaded()  Anywhere ### - -*This method __isUploaded__ is defined in `prototype` of `FS.File`* - -__Returns__ *{boolean}* -True if the number of uploaded bytes is equal to the file size. - - -> ```FS.File.prototype.isUploaded = function() { ...``` [fsFile-common.js:456](fsFile-common.js#L456) - - -- - -### *fsFile*.hasStored(storeName, [optimistic])  Anywhere ### - -*This method __hasStored__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __storeName__ *{string}* - - Name of the store - -* __optimistic__ *{boolean}* (Optional, Default = false) - - In case that the file record is not found, read below - - -__Returns__ *{boolean}* -Is a version of this file stored in the given store? - - -> Note: If the file is not published to the client or simply not found: -this method cannot know for sure if it exists or not. The `optimistic` -param is the boolean value to return. Are we `optimistic` that the copy -could exist. This is the case in `FS.File.url` we are optimistic that the -copy supplied by the user exists. - -> ```FS.File.prototype.hasStored = function(storeName, optimistic) { ...``` [fsFile-common.js:478](fsFile-common.js#L478) - - -- - -### *fsFile*.getCopyInfo(storeName)  Anywhere ### - -> __Warning!__ -> This method "FS.File.prototype.getCopyInfo" has deprecated from the API -> Use individual methods with `store` option instead. - -*This method __getCopyInfo__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __storeName__ *{string}* - - Name of the store for which to get copy info. - - -__Returns__ *{Object}* -The file details, e.g., name, size, key, etc., specific to the copy saved in this store. - - -> ```FS.File.prototype.getCopyInfo = function(storeName) { ...``` [fsFile-common.js:504](fsFile-common.js#L504) - - -- - -### *fsFile*.name([value], [options])  Anywhere ### - -*This method __name__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __value__ *{String|null}* (Optional) - - If setting the name, specify the new name as the first argument. Otherwise the options argument should be first. - -* __options__ *{Object}* (Optional) - * __store__ *{Object}* (Optional, Default = none,original) - - Get or set the name of the version of the file that was saved in this store. Default is the original file name. - - * __updateFileRecordFirst__ *{Boolean}* (Optional, Default = false) - - Update this instance with data from the DB first? Applies to getter usage only. - - * __save__ *{Boolean}* (Optional, Default = true) - - Save change to database? Applies to setter usage only. - - -__Returns__ *{String|undefined}* -If setting, returns `undefined`. If getting, returns the file name. - - -> ```FS.File.prototype.name = function(value, options) { ...``` [fsFile-common.js:568](fsFile-common.js#L568) - - -- - -### *fsFile*.extension([value], [options])  Anywhere ### - -*This method __extension__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __value__ *{String|null}* (Optional) - - If setting the extension, specify the new extension (without period) as the first argument. Otherwise the options argument should be first. - -* __options__ *{Object}* (Optional) - * __store__ *{Object}* (Optional, Default = none,original) - - Get or set the extension of the version of the file that was saved in this store. Default is the original file extension. - - * __updateFileRecordFirst__ *{Boolean}* (Optional, Default = false) - - Update this instance with data from the DB first? Applies to getter usage only. - - * __save__ *{Boolean}* (Optional, Default = true) - - Save change to database? Applies to setter usage only. - - -__Returns__ *{String|undefined}* -If setting, returns `undefined`. If getting, returns the file extension or an empty string if there isn't one. - - -> ```FS.File.prototype.extension = function(value, options) { ...``` [fsFile-common.js:593](fsFile-common.js#L593) - - -- - -### *fsFile*.size([value], [options])  Anywhere ### - -*This method __size__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __value__ *{Number}* (Optional) - - If setting the size, specify the new size in bytes as the first argument. Otherwise the options argument should be first. - -* __options__ *{Object}* (Optional) - * __store__ *{Object}* (Optional, Default = none,original) - - Get or set the size of the version of the file that was saved in this store. Default is the original file size. - - * __updateFileRecordFirst__ *{Boolean}* (Optional, Default = false) - - Update this instance with data from the DB first? Applies to getter usage only. - - * __save__ *{Boolean}* (Optional, Default = true) - - Save change to database? Applies to setter usage only. - - -__Returns__ *{Number|undefined}* -If setting, returns `undefined`. If getting, returns the file size. - - -> ```FS.File.prototype.size = function(value, options) { ...``` [fsFile-common.js:618](fsFile-common.js#L618) - - -- - -### *fsFile*.type([value], [options])  Anywhere ### - -*This method __type__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __value__ *{String}* (Optional) - - If setting the type, specify the new type as the first argument. Otherwise the options argument should be first. - -* __options__ *{Object}* (Optional) - * __store__ *{Object}* (Optional, Default = none,original) - - Get or set the type of the version of the file that was saved in this store. Default is the original file type. - - * __updateFileRecordFirst__ *{Boolean}* (Optional, Default = false) - - Update this instance with data from the DB first? Applies to getter usage only. - - * __save__ *{Boolean}* (Optional, Default = true) - - Save change to database? Applies to setter usage only. - - -__Returns__ *{String|undefined}* -If setting, returns `undefined`. If getting, returns the file type. - - -> ```FS.File.prototype.type = function(value, options) { ...``` [fsFile-common.js:643](fsFile-common.js#L643) - - -- - -### *fsFile*.updatedAt([value], [options])  Anywhere ### - -*This method __updatedAt__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __value__ *{String}* (Optional) - - If setting updatedAt, specify the new date as the first argument. Otherwise the options argument should be first. - -* __options__ *{Object}* (Optional) - * __store__ *{Object}* (Optional, Default = none,original) - - Get or set the last updated date for the version of the file that was saved in this store. Default is the original last updated date. - - * __updateFileRecordFirst__ *{Boolean}* (Optional, Default = false) - - Update this instance with data from the DB first? Applies to getter usage only. - - * __save__ *{Boolean}* (Optional, Default = true) - - Save change to database? Applies to setter usage only. - - -__Returns__ *{String|undefined}* -If setting, returns `undefined`. If getting, returns the file's last updated date. - - -> ```FS.File.prototype.updatedAt = function(value, options) { ...``` [fsFile-common.js:668](fsFile-common.js#L668) - - -- - -### *fsFile*.createReadStream([storeName])  Server ### - -*This method __createReadStream__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __storeName__ *{String}* (Optional) - -__Returns__ *{stream.Readable}* -Readable NodeJS stream - - -Returns a readable stream. Where the stream reads from depends on the FS.File instance and whether you pass a store name. - -If you pass a `storeName`, a readable stream for the file data saved in that store is returned. -If you don't pass a `storeName` and data is attached to the FS.File instance (on `data` property, which must be a DataMan instance), then a readable stream for the attached data is returned. -If you don't pass a `storeName` and there is no data attached to the FS.File instance, a readable stream for the file data currently in the temporary store (`FS.TempStore`) is returned. - - -> ```FS.File.prototype.createReadStream = function(storeName) { ...``` [fsFile-server.js:62](fsFile-server.js#L62) - - -- - -### *fsFile*.createWriteStream([storeName])  Server ### - -*This method __createWriteStream__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __storeName__ *{String}* (Optional) - -__Returns__ *{stream.Writeable}* -Writeable NodeJS stream - - -Returns a writeable stream. Where the stream writes to depends on whether you pass in a store name. - -If you pass a `storeName`, a writeable stream for (over)writing the file data in that store is returned. -If you don't pass a `storeName`, a writeable stream for writing to the temp store for this file is returned. - - -> ```FS.File.prototype.createWriteStream = function(storeName) { ...``` [fsFile-server.js:100](fsFile-server.js#L100) - - -- - -### *fsFile*.copy()  Server ### - -*This method __copy__ is defined in `prototype` of `FS.File`* - -__Returns__ *{FS.File}* -The new FS.File instance - - -> ```FS.File.prototype.copy = function() { ...``` [fsFile-server.js:126](fsFile-server.js#L126) - - diff --git a/packages/wekan-cfs-file/fsFile-common.js b/packages/wekan-cfs-file/fsFile-common.js deleted file mode 100644 index 01bbffbe4..000000000 --- a/packages/wekan-cfs-file/fsFile-common.js +++ /dev/null @@ -1,765 +0,0 @@ -/** - * @method FS.File - * @namespace FS.File - * @public - * @constructor - * @param {object|FS.File|data to attach} [ref] Another FS.File instance, a filerecord, or some data to pass to attachData - */ -FS.File = function(ref, createdByTransform) { - var self = this; - - self.createdByTransform = !!createdByTransform; - - if (ref instanceof FS.File || isBasicObject(ref)) { - // Extend self with filerecord related data - FS.Utility.extend(self, FS.Utility.cloneFileRecord(ref, {full: true})); - } else if (ref) { - self.attachData(ref); - } -}; - -// An FS.File can emit events -FS.File.prototype = new EventEmitter(); - -/** - * @method FS.File.prototype.attachData - * @public - * @param {File|Blob|Buffer|ArrayBuffer|Uint8Array|String} data The data that you want to attach to the file. - * @param {Object} [options] Options - * @param {String} [options.type] The data content (MIME) type, if known. - * @param {String} [options.headers] When attaching a URL, headers to be used for the GET request (currently server only) - * @param {String} [options.auth] When attaching a URL, "username:password" to be used for the GET request (currently server only) - * @param {Function} [callback] Callback function, callback(error). On the client, a callback is required if data is a URL. - * @returns {FS.File} This FS.File instance. - * - */ -FS.File.prototype.attachData = function fsFileAttachData(data, options, callback) { - var self = this; - - if (!callback && typeof options === "function") { - callback = options; - options = {}; - } - options = options || {}; - - if (!data) { - throw new Error('FS.File.attachData requires a data argument with some data'); - } - - var urlOpts; - - // Set any other properties we can determine from the source data - // File - if (typeof File !== "undefined" && data instanceof File) { - self.name(data.name); - self.updatedAt(data.lastModifiedDate); - self.size(data.size); - setData(data.type); - } - // Blob - else if (typeof Blob !== "undefined" && data instanceof Blob) { - self.name(data.name); - self.updatedAt(new Date()); - self.size(data.size); - setData(data.type); - } - // URL: we need to do a HEAD request to get the type because type - // is required for filtering to work. - else if (typeof data === "string" && (data.slice(0, 5) === "http:" || data.slice(0, 6) === "https:")) { - urlOpts = FS.Utility.extend({}, options); - if (urlOpts.type) { - delete urlOpts.type; - } - - if (!callback) { - if (Meteor.isClient) { - throw new Error('FS.File.attachData requires a callback when attaching a URL on the client'); - } - var result = Meteor.call('_cfs_getUrlInfo', data, urlOpts); - FS.Utility.extend(self, {original: result}); - setData(result.type); - } else { - Meteor.call('_cfs_getUrlInfo', data, urlOpts, function (error, result) { - FS.debug && console.log("URL HEAD RESULT:", result); - if (error) { - callback(error); - } else { - var type = result.type || options.type; - if (! type) { - throw new Error('FS.File.attachData got a URL for which it could not determine the MIME type and none was provided using options.type'); - } - FS.Utility.extend(self, {original: result}); - setData(type); - } - }); - } - } - // Everything else - else { - setData(options.type); - } - - // Set the data - function setData(type) { - self.data = new DataMan(data, type, urlOpts); - - // Update the type to match what the data is - self.type(self.data.type()); - - // Update the size to match what the data is. - // It's always safe to call self.data.size() without supplying a callback - // because it requires a callback only for URLs on the client, and we - // already added size for URLs when we got the result from '_cfs_getUrlInfo' method. - if (!self.size()) { - if (callback) { - self.data.size(function (error, size) { - if (error) { - callback && callback(error); - } else { - self.size(size); - setName(); - } - }); - } else { - self.size(self.data.size()); - setName(); - } - } else { - setName(); - } - } - - function setName() { - // See if we can extract a file name from URL or filepath - if (!self.name() && typeof data === "string") { - // name from URL - if (data.slice(0, 5) === "http:" || data.slice(0, 6) === "https:") { - if (FS.Utility.getFileExtension(data).length) { - // for a URL we assume the end is a filename only if it has an extension - self.name(FS.Utility.getFileName(data)); - } - } - // name from filepath - else if (data.slice(0, 5) !== "data:") { - self.name(FS.Utility.getFileName(data)); - } - } - - callback && callback(); - } - - return self; //allow chaining -}; - -/** - * @method FS.File.prototype.uploadProgress - * @public - * @returns {number} The server confirmed upload progress - */ -FS.File.prototype.uploadProgress = function() { - var self = this; - // Make sure our file record is updated - self.getFileRecord(); - - // If fully uploaded, return 100 - if (self.uploadedAt) { - return 100; - } - // Otherwise return the confirmed progress or 0 - else { - return Math.round((self.chunkCount || 0) / (self.chunkSum || 1) * 100); - } -}; - -/** - * @method FS.File.prototype.controlledByDeps - * @public - * @returns {FS.Collection} Returns true if this FS.File is reactive - * - * > Note: Returns true if this FS.File object was created by a FS.Collection - * > and we are in a reactive computations. What does this mean? Well it should - * > mean that our fileRecord is fully updated by Meteor and we are mounted on - * > a collection - */ -FS.File.prototype.controlledByDeps = function() { - var self = this; - return self.createdByTransform && Deps.active; -}; - -/** - * @method FS.File.prototype.getCollection - * @public - * @returns {FS.Collection} Returns attached collection or undefined if not mounted - */ -FS.File.prototype.getCollection = function() { - // Get the collection reference - var self = this; - - // If we already made the link then do no more - if (self.collection) { - return self.collection; - } - - // If we don't have a collectionName then there's not much to do, the file is - // not mounted yet - if (!self.collectionName) { - // Should not throw an error here - could be common that the file is not - // yet mounted into a collection - return; - } - - // Link the collection to the file - self.collection = FS._collections[self.collectionName]; - - return self.collection; //possibly undefined, but that's desired behavior -}; - -/** - * @method FS.File.prototype.isMounted - * @public - * @returns {FS.Collection} Returns attached collection or undefined if not mounted - */ -FS.File.prototype.isMounted = FS.File.prototype.getCollection; - -/** - * @method FS.File.prototype.getFileRecord Returns the fileRecord - * @public - * @returns {object} The filerecord - */ -FS.File.prototype.getFileRecord = function() { - var self = this; - // Check if this file object fileRecord is kept updated by Meteor, if so - // return self - if (self.controlledByDeps()) { - return self; - } - // Go for manually updating the file record - if (self.isMounted()) { - FS.debug && console.log('GET FILERECORD: ' + self._id); - - // Return the fileRecord or an empty object - var fileRecord = self.collection.files.findOne({_id: self._id}) || {}; - FS.Utility.extend(self, fileRecord); - return fileRecord; - } else { - // We return an empty object, this way users can still do `getRecord().size` - // Without getting an error - return {}; - } -}; - -/** - * @method FS.File.prototype.update - * @public - * @param {modifier} modifier - * @param {object} [options] - * @param {function} [callback] - * - * Updates the fileRecord. - */ -FS.File.prototype.update = function(modifier, options, callback) { - var self = this; - - FS.debug && console.log('UPDATE: ' + JSON.stringify(modifier)); - - // Make sure we have options and callback - if (!callback && typeof options === 'function') { - callback = options; - options = {}; - } - callback = callback || FS.Utility.defaultCallback; - - if (!self.isMounted()) { - callback(new Error("Cannot update a file that is not associated with a collection")); - return; - } - - // Call collection update - File record - return self.collection.files.update({_id: self._id}, modifier, options, function(err, count) { - // Update the fileRecord if it was changed and on the client - // The server-side methods will pull the fileRecord if needed - if (count > 0 && Meteor.isClient) - self.getFileRecord(); - // Call callback - callback(err, count); - }); -}; - -/** - * @method FS.File.prototype._saveChanges - * @private - * @param {String} [what] "_original" to save original info, or a store name to save info for that store, or saves everything - * - * Updates the fileRecord from values currently set on the FS.File instance. - */ -FS.File.prototype._saveChanges = function(what) { - var self = this; - - if (!self.isMounted()) { - return; - } - - FS.debug && console.log("FS.File._saveChanges:", what || "all"); - - var mod = {$set: {}}; - if (what === "_original") { - mod.$set.original = self.original; - } else if (typeof what === "string") { - var info = self.copies[what]; - if (info) { - mod.$set["copies." + what] = info; - } - } else { - mod.$set.original = self.original; - mod.$set.copies = self.copies; - } - - self.update(mod); -}; - -/** - * @method FS.File.prototype.remove - * @public - * @param {Function} [callback] - * @returns {number} Count - * - * Remove the current file from its FS.Collection - */ -FS.File.prototype.remove = function(callback) { - var self = this; - - FS.debug && console.log('REMOVE: ' + self._id); - - callback = callback || FS.Utility.defaultCallback; - - if (!self.isMounted()) { - callback(new Error("Cannot remove a file that is not associated with a collection")); - return; - } - - return self.collection.files.remove({_id: self._id}, function(err, res) { - if (!err) { - delete self._id; - delete self.collection; - delete self.collectionName; - } - callback(err, res); - }); -}; - -/** - * @method FS.File.prototype.moveTo - * @param {FS.Collection} targetCollection - * @private // Marked private until implemented - * @todo Needs to be implemented - * - * Move the file from current collection to another collection - * - * > Note: Not yet implemented - */ - -/** - * @method FS.File.prototype.getExtension Returns the lowercase file extension - * @public - * @deprecated Use the `extension` getter/setter method instead. - * @param {Object} [options] - * @param {String} [options.store] - Store name. Default is the original extension. - * @returns {string} The extension eg.: `jpg` or if not found then an empty string '' - */ -FS.File.prototype.getExtension = function(options) { - var self = this; - return self.extension(options); -}; - -function checkContentType(fsFile, storeName, startOfType) { - var type; - if (storeName && fsFile.hasStored(storeName)) { - type = fsFile.type({store: storeName}); - } else { - type = fsFile.type(); - } - if (typeof type === "string") { - return type.indexOf(startOfType) === 0; - } - return false; -} - -/** - * @method FS.File.prototype.isImage Is it an image file? - * @public - * @param {object} [options] - * @param {string} [options.store] The store we're interested in - * - * Returns true if the copy of this file in the specified store has an image - * content type. If the file object is unmounted or doesn't have a copy for - * the specified store, or if you don't specify a store, this method checks - * the content type of the original file. - */ -FS.File.prototype.isImage = function(options) { - return checkContentType(this, (options || {}).store, 'image/'); -}; - -/** - * @method FS.File.prototype.isVideo Is it a video file? - * @public - * @param {object} [options] - * @param {string} [options.store] The store we're interested in - * - * Returns true if the copy of this file in the specified store has a video - * content type. If the file object is unmounted or doesn't have a copy for - * the specified store, or if you don't specify a store, this method checks - * the content type of the original file. - */ -FS.File.prototype.isVideo = function(options) { - return checkContentType(this, (options || {}).store, 'video/'); -}; - -/** - * @method FS.File.prototype.isAudio Is it an audio file? - * @public - * @param {object} [options] - * @param {string} [options.store] The store we're interested in - * - * Returns true if the copy of this file in the specified store has an audio - * content type. If the file object is unmounted or doesn't have a copy for - * the specified store, or if you don't specify a store, this method checks - * the content type of the original file. - */ -FS.File.prototype.isAudio = function(options) { - return checkContentType(this, (options || {}).store, 'audio/'); -}; - -/** - * @method FS.File.prototype.formattedSize - * @public - * @param {Object} options - * @param {String} [options.store=none,display original file size] Which file do you want to get the size of? - * @param {String} [options.formatString='0.00 b'] The `numeral` format string to use. - * @return {String} The file size formatted as a human readable string and reactively updated. - * - * * You must add the `numeral` package to your app before you can use this method. - * * If info is not found or a size can't be determined, it will show 0. - */ -FS.File.prototype.formattedSize = function fsFileFormattedSize(options) { - var self = this; - - if (typeof numeral !== "function") - throw new Error("You must add the numeral package if you call FS.File.formattedSize"); - - options = options || {}; - options = options.hash || options; - - var size = self.size(options) || 0; - return numeral(size).format(options.formatString || '0.00 b'); -}; - -/** - * @method FS.File.prototype.isUploaded Is this file completely uploaded? - * @public - * @returns {boolean} True if the number of uploaded bytes is equal to the file size. - */ -FS.File.prototype.isUploaded = function() { - var self = this; - - // Make sure we use the updated file record - self.getFileRecord(); - - return !!self.uploadedAt; -}; - -/** - * @method FS.File.prototype.hasStored - * @public - * @param {string} storeName Name of the store - * @param {boolean} [optimistic=false] In case that the file record is not found, read below - * @returns {boolean} Is a version of this file stored in the given store? - * - * > Note: If the file is not published to the client or simply not found: - * this method cannot know for sure if it exists or not. The `optimistic` - * param is the boolean value to return. Are we `optimistic` that the copy - * could exist. This is the case in `FS.File.url` we are optimistic that the - * copy supplied by the user exists. - */ -FS.File.prototype.hasStored = function(storeName, optimistic) { - var self = this; - // Make sure we use the updated file record - self.getFileRecord(); - // If we havent the published data then - if (FS.Utility.isEmpty(self.copies)) { - return !!optimistic; - } - if (typeof storeName === "string") { - // Return true only if the `key` property is present, which is not set until - // storage is complete. - return !!(self.copies && self.copies[storeName] && self.copies[storeName].key); - } - return false; -}; - -// Backwards compatibility -FS.File.prototype.hasCopy = FS.File.prototype.hasStored; - -/** - * @method FS.File.prototype.getCopyInfo - * @public - * @deprecated Use individual methods with `store` option instead. - * @param {string} storeName Name of the store for which to get copy info. - * @returns {Object} The file details, e.g., name, size, key, etc., specific to the copy saved in this store. - */ -FS.File.prototype.getCopyInfo = function(storeName) { - var self = this; - // Make sure we use the updated file record - self.getFileRecord(); - return (self.copies && self.copies[storeName]) || null; -}; - -/** - * @method FS.File.prototype._getInfo - * @private - * @param {String} [storeName] Name of the store for which to get file info. Omit for original file details. - * @param {Object} [options] - * @param {Boolean} [options.updateFileRecordFirst=false] Update this instance with data from the DB first? - * @returns {Object} The file details, e.g., name, size, key, etc. If not found, returns an empty object. - */ -FS.File.prototype._getInfo = function(storeName, options) { - var self = this; - options = options || {}; - - if (options.updateFileRecordFirst) { - // Make sure we use the updated file record - self.getFileRecord(); - } - - if (storeName) { - return (self.copies && self.copies[storeName]) || {}; - } else { - return self.original || {}; - } -}; - -/** - * @method FS.File.prototype._setInfo - * @private - * @param {String} storeName - Name of the store for which to set file info. Non-string will set original file details. - * @param {String} property - Property to set - * @param {String} value - New value for property - * @param {Boolean} save - Should the new value be saved to the DB, too, or just set in the FS.File properties? - * @returns {undefined} - */ -FS.File.prototype._setInfo = function(storeName, property, value, save) { - var self = this; - if (typeof storeName === "string") { - self.copies = self.copies || {}; - self.copies[storeName] = self.copies[storeName] || {}; - self.copies[storeName][property] = value; - save && self._saveChanges(storeName); - } else { - self.original = self.original || {}; - self.original[property] = value; - save && self._saveChanges("_original"); - } -}; - -/** - * @method FS.File.prototype.name - * @public - * @param {String|null} [value] - If setting the name, specify the new name as the first argument. Otherwise the options argument should be first. - * @param {Object} [options] - * @param {Object} [options.store=none,original] - Get or set the name of the version of the file that was saved in this store. Default is the original file name. - * @param {Boolean} [options.updateFileRecordFirst=false] Update this instance with data from the DB first? Applies to getter usage only. - * @param {Boolean} [options.save=true] Save change to database? Applies to setter usage only. - * @returns {String|undefined} If setting, returns `undefined`. If getting, returns the file name. - */ -FS.File.prototype.name = function(value, options) { - var self = this; - - if (!options && ((typeof value === "object" && value !== null) || typeof value === "undefined")) { - // GET - options = value || {}; - options = options.hash || options; // allow use as UI helper - return self._getInfo(options.store, options).name; - } else { - // SET - options = options || {}; - return self._setInfo(options.store, 'name', value, typeof options.save === "boolean" ? options.save : true); - } -}; - -/** - * @method FS.File.prototype.extension - * @public - * @param {String|null} [value] - If setting the extension, specify the new extension (without period) as the first argument. Otherwise the options argument should be first. - * @param {Object} [options] - * @param {Object} [options.store=none,original] - Get or set the extension of the version of the file that was saved in this store. Default is the original file extension. - * @param {Boolean} [options.updateFileRecordFirst=false] Update this instance with data from the DB first? Applies to getter usage only. - * @param {Boolean} [options.save=true] Save change to database? Applies to setter usage only. - * @returns {String|undefined} If setting, returns `undefined`. If getting, returns the file extension or an empty string if there isn't one. - */ -FS.File.prototype.extension = function(value, options) { - var self = this; - - if (!options && ((typeof value === "object" && value !== null) || typeof value === "undefined")) { - // GET - options = value || {}; - return FS.Utility.getFileExtension(self.name(options) || ''); - } else { - // SET - options = options || {}; - var newName = FS.Utility.setFileExtension(self.name(options) || '', value); - return self._setInfo(options.store, 'name', newName, typeof options.save === "boolean" ? options.save : true); - } -}; - -/** - * @method FS.File.prototype.size - * @public - * @param {Number} [value] - If setting the size, specify the new size in bytes as the first argument. Otherwise the options argument should be first. - * @param {Object} [options] - * @param {Object} [options.store=none,original] - Get or set the size of the version of the file that was saved in this store. Default is the original file size. - * @param {Boolean} [options.updateFileRecordFirst=false] Update this instance with data from the DB first? Applies to getter usage only. - * @param {Boolean} [options.save=true] Save change to database? Applies to setter usage only. - * @returns {Number|undefined} If setting, returns `undefined`. If getting, returns the file size. - */ -FS.File.prototype.size = function(value, options) { - var self = this; - - if (!options && ((typeof value === "object" && value !== null) || typeof value === "undefined")) { - // GET - options = value || {}; - options = options.hash || options; // allow use as UI helper - return self._getInfo(options.store, options).size; - } else { - // SET - options = options || {}; - return self._setInfo(options.store, 'size', value, typeof options.save === "boolean" ? options.save : true); - } -}; - -/** - * @method FS.File.prototype.type - * @public - * @param {String} [value] - If setting the type, specify the new type as the first argument. Otherwise the options argument should be first. - * @param {Object} [options] - * @param {Object} [options.store=none,original] - Get or set the type of the version of the file that was saved in this store. Default is the original file type. - * @param {Boolean} [options.updateFileRecordFirst=false] Update this instance with data from the DB first? Applies to getter usage only. - * @param {Boolean} [options.save=true] Save change to database? Applies to setter usage only. - * @returns {String|undefined} If setting, returns `undefined`. If getting, returns the file type. - */ -FS.File.prototype.type = function(value, options) { - var self = this; - - if (!options && ((typeof value === "object" && value !== null) || typeof value === "undefined")) { - // GET - options = value || {}; - options = options.hash || options; // allow use as UI helper - return self._getInfo(options.store, options).type; - } else { - // SET - options = options || {}; - return self._setInfo(options.store, 'type', value, typeof options.save === "boolean" ? options.save : true); - } -}; - -/** - * @method FS.File.prototype.updatedAt - * @public - * @param {String} [value] - If setting updatedAt, specify the new date as the first argument. Otherwise the options argument should be first. - * @param {Object} [options] - * @param {Object} [options.store=none,original] - Get or set the last updated date for the version of the file that was saved in this store. Default is the original last updated date. - * @param {Boolean} [options.updateFileRecordFirst=false] Update this instance with data from the DB first? Applies to getter usage only. - * @param {Boolean} [options.save=true] Save change to database? Applies to setter usage only. - * @returns {String|undefined} If setting, returns `undefined`. If getting, returns the file's last updated date. - */ -FS.File.prototype.updatedAt = function(value, options) { - var self = this; - - if (!options && ((typeof value === "object" && value !== null && !(value instanceof Date)) || typeof value === "undefined")) { - // GET - options = value || {}; - options = options.hash || options; // allow use as UI helper - return self._getInfo(options.store, options).updatedAt; - } else { - // SET - options = options || {}; - return self._setInfo(options.store, 'updatedAt', value, typeof options.save === "boolean" ? options.save : true); - } -}; - -/** - * @method FS.File.onStoredCallback - * @summary Calls callback when the file is fully stored to the specify storeName - * @public - * @param {String} [storeName] - The name of the file store we want to get called when stored. - * @param {function} [callback] - */ -FS.File.prototype.onStoredCallback = function (storeName, callback) { - // Check file is not already stored - if (this.hasStored(storeName)) { - callback(); - return; - } - if (Meteor.isServer) { - // Listen to file stored events - // TODO Require thinking whether it is better to use observer for case of using multiple application instances, Ask for same image url while upload is being done. - this.on('stored', function (newStoreName) { - // If stored is completed to the specified store call callback - if (storeName === newStoreName) { - // Remove the specified file stored listener - this.removeListener('stored', arguments.callee); - callback(); - } - }.bind(this) - ); - } else { - var fileId = this._id, - collectionName = this.collectionName; - // Wait for file to be fully uploaded - Tracker.autorun(function (c) { - Meteor.call('_cfs_returnWhenStored', collectionName, fileId, storeName, function (error, result) { - if (result && result === true) { - c.stop(); - callback(); - } else { - Meteor.setTimeout(function () { - c.invalidate(); - }, 100); - } - }); - }); - } -}; - -/** - * @method FS.File.onStored - * @summary Function that returns when the file is fully stored to the specify storeName - * @public - * @param {String} storeName - The name of the file store we want to get called when stored. - * - * Function that returns when the file is fully stored to the specify storeName. - * - * For example needed if wanted to save the direct link to a file on s3 when fully uploaded. - */ -FS.File.prototype.onStored = function (arguments) { - var onStoredSync = Meteor.wrapAsync(this.onStoredCallback); - return onStoredSync.call(this, arguments); -}; - -function isBasicObject(obj) { - return (obj === Object(obj) && Object.getPrototypeOf(obj) === Object.prototype); -} - -// getPrototypeOf polyfill -if (typeof Object.getPrototypeOf !== "function") { - if (typeof "".__proto__ === "object") { - Object.getPrototypeOf = function(object) { - return object.__proto__; - }; - } else { - Object.getPrototypeOf = function(object) { - // May break if the constructor has been tampered with - return object.constructor.prototype; - }; - } -} - - diff --git a/packages/wekan-cfs-file/fsFile-server.js b/packages/wekan-cfs-file/fsFile-server.js deleted file mode 100644 index d502d0295..000000000 --- a/packages/wekan-cfs-file/fsFile-server.js +++ /dev/null @@ -1,361 +0,0 @@ -/** - * Notes a details about a storage adapter failure within the file record - * @param {string} storeName - * @param {number} maxTries - * @return {undefined} - * @todo deprecate this - */ -FS.File.prototype.logCopyFailure = function(storeName, maxTries) { - var self = this; - - // hasStored will update from the fileRecord - if (self.hasStored(storeName)) { - throw new Error("logCopyFailure: invalid storeName"); - } - - // Make sure we have a temporary file saved since we will be - // trying the save again. - FS.TempStore.ensureForFile(self); - - var now = new Date(); - var currentCount = (self.failures && self.failures.copies && self.failures.copies[storeName] && typeof self.failures.copies[storeName].count === "number") ? self.failures.copies[storeName].count : 0; - maxTries = maxTries || 5; - - var modifier = {}; - modifier.$set = {}; - modifier.$set['failures.copies.' + storeName + '.lastAttempt'] = now; - if (currentCount === 0) { - modifier.$set['failures.copies.' + storeName + '.firstAttempt'] = now; - } - modifier.$set['failures.copies.' + storeName + '.count'] = currentCount + 1; - modifier.$set['failures.copies.' + storeName + '.doneTrying'] = (currentCount + 1 >= maxTries); - self.update(modifier); -}; - -/** - * Has this store permanently failed? - * @param {String} storeName The name of the store - * @return {boolean} Has this store failed permanently? - * @todo deprecate this - */ -FS.File.prototype.failedPermanently = function(storeName) { - var self = this; - return !!(self.failures && - self.failures.copies && - self.failures.copies[storeName] && - self.failures.copies[storeName].doneTrying); -}; - -/** - * @method FS.File.prototype.createReadStream - * @public - * @param {String} [storeName] - * @returns {stream.Readable} Readable NodeJS stream - * - * Returns a readable stream. Where the stream reads from depends on the FS.File instance and whether you pass a store name. - * - * * If you pass a `storeName`, a readable stream for the file data saved in that store is returned. - * * If you don't pass a `storeName` and data is attached to the FS.File instance (on `data` property, which must be a DataMan instance), then a readable stream for the attached data is returned. - * * If you don't pass a `storeName` and there is no data attached to the FS.File instance, a readable stream for the file data currently in the temporary store (`FS.TempStore`) is returned. - * - */ -FS.File.prototype.createReadStream = function(storeName) { - var self = this; - - // If we dont have a store name but got Buffer data? - if (!storeName && self.data) { - FS.debug && console.log("fileObj.createReadStream creating read stream for attached data"); - // Stream from attached data if present - return self.data.createReadStream(); - } else if (!storeName && FS.TempStore && FS.TempStore.exists(self)) { - FS.debug && console.log("fileObj.createReadStream creating read stream for temp store"); - // Stream from temp store - its a bit slower than regular streams? - return FS.TempStore.createReadStream(self); - } else { - // Stream from the store using storage adapter - if (self.isMounted()) { - var storage = self.collection.storesLookup[storeName] || self.collection.primaryStore; - FS.debug && console.log("fileObj.createReadStream creating read stream for store", storage.name); - // return stream - return storage.adapter.createReadStream(self); - } else { - throw new Meteor.Error('File not mounted'); - } - - } -}; - -/** - * @method FS.File.prototype.createWriteStream - * @public - * @param {String} [storeName] - * @returns {stream.Writeable} Writeable NodeJS stream - * - * Returns a writeable stream. Where the stream writes to depends on whether you pass in a store name. - * - * * If you pass a `storeName`, a writeable stream for (over)writing the file data in that store is returned. - * * If you don't pass a `storeName`, a writeable stream for writing to the temp store for this file is returned. - * - */ -FS.File.prototype.createWriteStream = function(storeName) { - var self = this; - - // We have to have a mounted file in order for this to work - if (self.isMounted()) { - if (!storeName && FS.TempStore && FS.FileWorker) { - // If we have worker installed - we pass the file to FS.TempStore - // We dont need the storeName since all stores will be generated from - // TempStore. - // This should trigger FS.FileWorker at some point? - FS.TempStore.createWriteStream(self); - } else { - // Stream directly to the store using storage adapter - var storage = self.collection.storesLookup[storeName] || self.collection.primaryStore; - return storage.adapter.createWriteStream(self); - } - } else { - throw new Meteor.Error('File not mounted'); - } -}; - -/** - * @method FS.File.prototype.copy Makes a copy of the file and underlying data in all stores. - * @public - * @returns {FS.File} The new FS.File instance - */ -FS.File.prototype.copy = function() { - var self = this; - - if (!self.isMounted()) { - throw new Error("Cannot copy a file that is not associated with a collection"); - } - - // Get the file record - var fileRecord = self.collection.files.findOne({_id: self._id}, {transform: null}) || {}; - - // Remove _id and copy keys from the file record - delete fileRecord._id; - - // Insert directly; we don't have access to "original" in this case - var newId = self.collection.files.insert(fileRecord); - - var newFile = self.collection.findOne(newId); - - // Copy underlying files in the stores - var mod, oldKey; - for (var name in newFile.copies) { - if (newFile.copies.hasOwnProperty(name)) { - oldKey = newFile.copies[name].key; - if (oldKey) { - // We need to ask the adapter for the true oldKey because - // right now gridfs does some extra stuff. - // TODO GridFS should probably set the full key object - // (with _id and filename) into `copies.key` - // so that copies.key can be passed directly to - // createReadStreamForFileKey - var sourceFileStorage = self.collection.storesLookup[name]; - if (!sourceFileStorage) { - throw new Error(name + " is not a valid store name"); - } - oldKey = sourceFileStorage.adapter.fileKey(self); - // delete so that new fileKey will be generated in copyStoreData - delete newFile.copies[name].key; - mod = mod || {}; - mod["copies." + name + ".key"] = copyStoreData(newFile, name, oldKey); - } - } - } - // Update keys in the filerecord - if (mod) { - newFile.update({$set: mod}); - } - - return newFile; -}; - -Meteor.methods({ - // Does a HEAD request to URL to get the type, updatedAt, - // and size prior to actually downloading the data. - // That way we can do filter checks without actually downloading. - '_cfs_getUrlInfo': function (url, options) { - check(url, String); - check(options, Object); - - this.unblock(); - - var response = HTTP.call("HEAD", url, options); - var headers = response.headers; - var result = {}; - - if (headers['content-type']) { - result.type = headers['content-type']; - } - - if (headers['content-length']) { - result.size = +headers['content-length']; - } - - if (headers['last-modified']) { - result.updatedAt = new Date(headers['last-modified']); - } - - return result; - }, - // Helper function that checks whether given fileId from collectionName - // Is fully uploaded to specify storeName. - '_cfs_returnWhenStored' : function (collectionName, fileId, storeName) { - check(collectionName, String); - check(fileId, String); - check(storeName, String); - - var collection = FS._collections[collectionName]; - if (!collection) { - return Meteor.Error('_cfs_returnWhenStored: FSCollection name not exists'); - } - - var file = collection.findOne({_id: fileId}); - if (!file) { - return Meteor.Error('_cfs_returnWhenStored: FSFile not exists'); - } - return file.hasStored(storeName); - } -}); - -// TODO maybe this should be in cfs-storage-adapter -function _copyStoreData(fileObj, storeName, sourceKey, callback) { - if (!fileObj.isMounted()) { - throw new Error("Cannot copy store data for a file that is not associated with a collection"); - } - - var storage = fileObj.collection.storesLookup[storeName]; - if (!storage) { - throw new Error(storeName + " is not a valid store name"); - } - - // We want to prevent beforeWrite and transformWrite from running, so - // we interact directly with the store. - var destinationKey = storage.adapter.fileKey(fileObj); - var readStream = storage.adapter.createReadStreamForFileKey(sourceKey); - var writeStream = storage.adapter.createWriteStreamForFileKey(destinationKey); - - writeStream.once('stored', function(result) { - callback(null, result.fileKey); - }); - - writeStream.once('error', function(error) { - callback(error); - }); - - readStream.pipe(writeStream); -} -var copyStoreData = Meteor.wrapAsync(_copyStoreData); - -/** - * @method FS.File.prototype.copyData Copies the content of a store directly into another store. - * @public - * @param {string} sourceStoreName - * @param {string} targetStoreName - * @param {boolean=} move - */ -FS.File.prototype.copyData = function(sourceStoreName, targetStoreName, move){ - - move = !!move; - /** - * @type {Object.} - */ - var sourceStoreValues = this.copies[sourceStoreName]; - /** - * @type {string} - */ - var copyKey = cloneDataToStore(this, sourceStoreName, targetStoreName, move); - /** - * @type {Object.} - */ - var targetStoreValues = {}; - for (var v in sourceStoreValues) { - if (sourceStoreValues.hasOwnProperty(v)) { - targetStoreValues[v] = sourceStoreValues[v] - } - } - targetStoreValues.key = copyKey; - targetStoreValues.createdAt = new Date(); - targetStoreValues.updatedAt = new Date(); - /** - * - * @type {modifier} - */ - var modifier = {}; - modifier.$set = {}; - modifier.$set["copies."+targetStoreName] = targetStoreValues; - if(move){ - modifier.$unset = {}; - modifier.$unset["copies."+sourceStoreName] = ""; - } - this.update(modifier); -}; -/** - * @method FS.File.prototype.moveData Moves the content of a store directly into another store. - * @public - * @param {string} sourceStoreName - * @param {string} targetStoreName - */ -FS.File.prototype.moveData = function(sourceStoreName, targetStoreName){ - this.copyData(sourceStoreName, targetStoreName, true); -}; -// TODO maybe this should be in cfs-storage-adapter -/** - * - * @param {FS.File} fileObj - * @param {string} sourceStoreName - * @param {string} targetStoreName - * @param {boolean} move - * @param callback - * @private - */ -function _copyDataFromStoreToStore(fileObj, sourceStoreName, targetStoreName, move, callback) { - if (!fileObj.isMounted()) { - throw new Error("Cannot copy store data for a file that is not associated with a collection"); - } - /** - * @type {FS.StorageAdapter} - */ - var sourceStorage = fileObj.collection.storesLookup[sourceStoreName]; - /** - * @type {FS.StorageAdapter} - */ - var targetStorage = fileObj.collection.storesLookup[targetStoreName]; - - if (!sourceStorage) { - throw new Error(sourceStoreName + " is not a valid store name"); - } - if (!targetStorage) { - throw new Error(targetStorage + " is not a valid store name"); - } - - // We want to prevent beforeWrite and transformWrite from running, so - // we interact directly with the store. - var sourceKey = sourceStorage.adapter.fileKey(fileObj); - var targetKey = targetStorage.adapter.fileKey(fileObj); - var readStream = sourceStorage.adapter.createReadStreamForFileKey(sourceKey); - var writeStream = targetStorage.adapter.createWriteStreamForFileKey(targetKey); - - - writeStream.safeOnce('stored', function(result) { - if(move && sourceStorage.adapter.remove(fileObj)===false){ - callback("Copied to store:" + targetStoreName - + " with fileKey: " - + result.fileKey - + ", but could not delete from source store: " - + sourceStoreName); - }else{ - callback(null, result.fileKey); - } - }); - - writeStream.once('error', function(error) { - callback(error); - }); - - readStream.pipe(writeStream); -} -var cloneDataToStore = Meteor.wrapAsync(_copyDataFromStoreToStore); diff --git a/packages/wekan-cfs-file/internal.api.md b/packages/wekan-cfs-file/internal.api.md deleted file mode 100644 index 362c9a622..000000000 --- a/packages/wekan-cfs-file/internal.api.md +++ /dev/null @@ -1,749 +0,0 @@ -## Public and Private API ## - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -*** - -__File: ["fsFile-common.js"](fsFile-common.js) Where: {client|server}__ - -*** - -### new *fs*.File([ref])  Anywhere ### - -*This method __File__ is defined in `FS`* - -__Arguments__ - -* __ref__ *{object|[FS.File](#FS.File)|[data to attach](#data to attach)}* (Optional) - - Another FS.File instance, a filerecord, or some data to pass to attachData - - - -> ```FS.File = function(ref, createdByTransform) { ...``` [fsFile-common.js:8](fsFile-common.js#L8) - - -- - -### *fsFile*.attachData(data, [options], [callback])  Anywhere ### - -*This method __attachData__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __data__ *{[File](#File)|[Blob](#Blob)|Buffer|ArrayBuffer|Uint8Array|String}* - - The data that you want to attach to the file. - -* __options__ *{Object}* (Optional) - - Options - - * __type__ *{String}* (Optional) - - The data content (MIME) type, if known. - - * __headers__ *{String}* (Optional) - - When attaching a URL, headers to be used for the GET request (currently server only) - - * __auth__ *{String}* (Optional) - - When attaching a URL, "username:password" to be used for the GET request (currently server only) - -* __callback__ *{Function}* (Optional) - - Callback function, callback(error). On the client, a callback is required if data is a URL. - - -__Returns__ *{FS.File}* -This FS.File instance. - - - -> ```FS.File.prototype.attachData = function fsFileAttachData(data, options, callback) { ...``` [fsFile-common.js:36](fsFile-common.js#L36) - - -- - -### *fsFile*.uploadProgress()  Anywhere ### - -*This method __uploadProgress__ is defined in `prototype` of `FS.File`* - -__Returns__ *{number}* -The server confirmed upload progress - - -> ```FS.File.prototype.uploadProgress = function() { ...``` [fsFile-common.js:154](fsFile-common.js#L154) - - -- - -### *fsFile*.controlledByDeps()  Anywhere ### - -*This method __controlledByDeps__ is defined in `prototype` of `FS.File`* - -__Returns__ *{FS.Collection}* -Returns true if this FS.File is reactive - - -> Note: Returns true if this FS.File object was created by a FS.Collection -> and we are in a reactive computations. What does this mean? Well it should -> mean that our fileRecord is fully updated by Meteor and we are mounted on -> a collection - -> ```FS.File.prototype.controlledByDeps = function() { ...``` [fsFile-common.js:179](fsFile-common.js#L179) - - -- - -### *fsFile*.getCollection()  Anywhere ### - -*This method __getCollection__ is defined in `prototype` of `FS.File`* - -__Returns__ *{FS.Collection}* -Returns attached collection or undefined if not mounted - - -> ```FS.File.prototype.getCollection = function() { ...``` [fsFile-common.js:189](fsFile-common.js#L189) - - -- - -### *fsFile*.isMounted()  Anywhere ### - -*This method __isMounted__ is defined in `prototype` of `FS.File`* - -__Returns__ *{FS.Collection}* -Returns attached collection or undefined if not mounted - - -> ```FS.File.prototype.isMounted = FS.File.prototype.getCollection;``` [fsFile-common.js:217](fsFile-common.js#L217) - - -- - -### *fsFile*.getFileRecord()  Anywhere ### - -*This method __getFileRecord__ is defined in `prototype` of `FS.File`* - -__Returns__ *{object}* -The filerecord - - -> ```FS.File.prototype.getFileRecord = function() { ...``` [fsFile-common.js:224](fsFile-common.js#L224) - - -- - -### *fsFile*.update(modifier, [options], [callback])  Anywhere ### - -*This method __update__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __modifier__ *{[modifier](#modifier)}* -* __options__ *{object}* (Optional) -* __callback__ *{function}* (Optional) - - -Updates the fileRecord. - -> ```FS.File.prototype.update = function(modifier, options, callback) { ...``` [fsFile-common.js:255](fsFile-common.js#L255) - - -- - -### *fsFile*._saveChanges([what])  Anywhere ### - -*This method is private* -*This method ___saveChanges__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __what__ *{String}* (Optional) - - "_original" to save original info, or a store name to save info for that store, or saves everything - - - -Updates the fileRecord from values currently set on the FS.File instance. - -> ```FS.File.prototype._saveChanges = function(what) { ...``` [fsFile-common.js:290](fsFile-common.js#L290) - - -- - -### *fsFile*.remove([callback])  Anywhere ### - -*This method __remove__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __callback__ *{Function}* (Optional) - -__Returns__ *{number}* -Count - - -Remove the current file from its FS.Collection - -> ```FS.File.prototype.remove = function(callback) { ...``` [fsFile-common.js:323](fsFile-common.js#L323) - - -- - -### *fsFile*.moveTo(targetCollection)  Anywhere ### - -*This method is private* -*This method __moveTo__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __targetCollection__ *{[FS.Collection](#FS.Collection)}* - -__TODO__ -``` -* Needs to be implemented -``` - - -Move the file from current collection to another collection - -> Note: Not yet implemented - -> ```FS.File.prototype.getExtension = function(options) { ...``` [fsFile-common.js:364](fsFile-common.js#L364) - - -- - -### *fsFile*.getExtension([options])  Anywhere ### - -> __Warning!__ -> This method "FS.File.prototype.getExtension" has deprecated from the API -> Use the `extension` getter/setter method instead. - -*This method __getExtension__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __options__ *{Object}* (Optional) - * __store__ *{String}* (Optional) - - Store name. Default is the original extension. - - -__Returns__ *{string}* -The extension eg.: `jpg` or if not found then an empty string '' - - -> ```FS.File.prototype.getExtension = function(options) { ...``` [fsFile-common.js:364](fsFile-common.js#L364) - - -- - -### *fsFile*.isImage([options])  Anywhere ### - -*This method __isImage__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __options__ *{object}* (Optional) - * __store__ *{string}* (Optional) - - The store we're interested in - - - -Returns true if the copy of this file in the specified store has an image -content type. If the file object is unmounted or doesn't have a copy for -the specified store, or if you don't specify a store, this method checks -the content type of the original file. - -> ```FS.File.prototype.isImage = function(options) { ...``` [fsFile-common.js:393](fsFile-common.js#L393) - - -- - -### *fsFile*.isVideo([options])  Anywhere ### - -*This method __isVideo__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __options__ *{object}* (Optional) - * __store__ *{string}* (Optional) - - The store we're interested in - - - -Returns true if the copy of this file in the specified store has a video -content type. If the file object is unmounted or doesn't have a copy for -the specified store, or if you don't specify a store, this method checks -the content type of the original file. - -> ```FS.File.prototype.isVideo = function(options) { ...``` [fsFile-common.js:408](fsFile-common.js#L408) - - -- - -### *fsFile*.isAudio([options])  Anywhere ### - -*This method __isAudio__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __options__ *{object}* (Optional) - * __store__ *{string}* (Optional) - - The store we're interested in - - - -Returns true if the copy of this file in the specified store has an audio -content type. If the file object is unmounted or doesn't have a copy for -the specified store, or if you don't specify a store, this method checks -the content type of the original file. - -> ```FS.File.prototype.isAudio = function(options) { ...``` [fsFile-common.js:423](fsFile-common.js#L423) - - -- - -### *fsFile*.formattedSize({Object}, {String}, {String})  Anywhere ### - -*This method __formattedSize__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __{Object}__ *{any}* - - options - -* __{String}__ *{any}* - - [options.store=none,display original file size] Which file do you want to get the size of? - -* __{String}__ *{any}* - - [options.formatString='0.00 b'] The `numeral` format string to use. - - -__Returns__ *{String}* -The file size formatted as a human readable string and reactively updated. - - -You must add the `numeral` package to your app before you can use this method. -If info is not found or a size can't be determined, it will show 0. - -> ```FS.File.prototype.formattedSize = function fsFileFormattedSize(options) { ...``` [fsFile-common.js:438](fsFile-common.js#L438) - - -- - -### *fsFile*.isUploaded()  Anywhere ### - -*This method __isUploaded__ is defined in `prototype` of `FS.File`* - -__Returns__ *{boolean}* -True if the number of uploaded bytes is equal to the file size. - - -> ```FS.File.prototype.isUploaded = function() { ...``` [fsFile-common.js:456](fsFile-common.js#L456) - - -- - -### *fsFile*.hasStored(storeName, [optimistic])  Anywhere ### - -*This method __hasStored__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __storeName__ *{string}* - - Name of the store - -* __optimistic__ *{boolean}* (Optional, Default = false) - - In case that the file record is not found, read below - - -__Returns__ *{boolean}* -Is a version of this file stored in the given store? - - -> Note: If the file is not published to the client or simply not found: -this method cannot know for sure if it exists or not. The `optimistic` -param is the boolean value to return. Are we `optimistic` that the copy -could exist. This is the case in `FS.File.url` we are optimistic that the -copy supplied by the user exists. - -> ```FS.File.prototype.hasStored = function(storeName, optimistic) { ...``` [fsFile-common.js:478](fsFile-common.js#L478) - - -- - -### *fsFile*.getCopyInfo(storeName)  Anywhere ### - -> __Warning!__ -> This method "FS.File.prototype.getCopyInfo" has deprecated from the API -> Use individual methods with `store` option instead. - -*This method __getCopyInfo__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __storeName__ *{string}* - - Name of the store for which to get copy info. - - -__Returns__ *{Object}* -The file details, e.g., name, size, key, etc., specific to the copy saved in this store. - - -> ```FS.File.prototype.getCopyInfo = function(storeName) { ...``` [fsFile-common.js:504](fsFile-common.js#L504) - - -- - -### *fsFile*._getInfo([storeName], [options])  Anywhere ### - -*This method is private* -*This method ___getInfo__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __storeName__ *{String}* (Optional) - - Name of the store for which to get file info. Omit for original file details. - -* __options__ *{Object}* (Optional) - * __updateFileRecordFirst__ *{Boolean}* (Optional, Default = false) - - Update this instance with data from the DB first? - - -__Returns__ *{Object}* -The file details, e.g., name, size, key, etc. If not found, returns an empty object. - - -> ```FS.File.prototype._getInfo = function(storeName, options) { ...``` [fsFile-common.js:519](fsFile-common.js#L519) - - -- - -### *fsFile*._setInfo(storeName, property, value, save)  Anywhere ### - -*This method is private* -*This method ___setInfo__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __storeName__ *{String}* - - Name of the store for which to set file info. Non-string will set original file details. - -* __property__ *{String}* - - Property to set - -* __value__ *{String}* - - New value for property - -* __save__ *{Boolean}* - - Should the new value be saved to the DB, too, or just set in the FS.File properties? - - -__Returns__ *{undefined}* - - -> ```FS.File.prototype._setInfo = function(storeName, property, value, save) { ...``` [fsFile-common.js:544](fsFile-common.js#L544) - - -- - -### *fsFile*.name([value], [options])  Anywhere ### - -*This method __name__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __value__ *{String|null}* (Optional) - - If setting the name, specify the new name as the first argument. Otherwise the options argument should be first. - -* __options__ *{Object}* (Optional) - * __store__ *{Object}* (Optional, Default = none,original) - - Get or set the name of the version of the file that was saved in this store. Default is the original file name. - - * __updateFileRecordFirst__ *{Boolean}* (Optional, Default = false) - - Update this instance with data from the DB first? Applies to getter usage only. - - * __save__ *{Boolean}* (Optional, Default = true) - - Save change to database? Applies to setter usage only. - - -__Returns__ *{String|undefined}* -If setting, returns `undefined`. If getting, returns the file name. - - -> ```FS.File.prototype.name = function(value, options) { ...``` [fsFile-common.js:568](fsFile-common.js#L568) - - -- - -### *fsFile*.extension([value], [options])  Anywhere ### - -*This method __extension__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __value__ *{String|null}* (Optional) - - If setting the extension, specify the new extension (without period) as the first argument. Otherwise the options argument should be first. - -* __options__ *{Object}* (Optional) - * __store__ *{Object}* (Optional, Default = none,original) - - Get or set the extension of the version of the file that was saved in this store. Default is the original file extension. - - * __updateFileRecordFirst__ *{Boolean}* (Optional, Default = false) - - Update this instance with data from the DB first? Applies to getter usage only. - - * __save__ *{Boolean}* (Optional, Default = true) - - Save change to database? Applies to setter usage only. - - -__Returns__ *{String|undefined}* -If setting, returns `undefined`. If getting, returns the file extension or an empty string if there isn't one. - - -> ```FS.File.prototype.extension = function(value, options) { ...``` [fsFile-common.js:593](fsFile-common.js#L593) - - -- - -### *fsFile*.size([value], [options])  Anywhere ### - -*This method __size__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __value__ *{Number}* (Optional) - - If setting the size, specify the new size in bytes as the first argument. Otherwise the options argument should be first. - -* __options__ *{Object}* (Optional) - * __store__ *{Object}* (Optional, Default = none,original) - - Get or set the size of the version of the file that was saved in this store. Default is the original file size. - - * __updateFileRecordFirst__ *{Boolean}* (Optional, Default = false) - - Update this instance with data from the DB first? Applies to getter usage only. - - * __save__ *{Boolean}* (Optional, Default = true) - - Save change to database? Applies to setter usage only. - - -__Returns__ *{Number|undefined}* -If setting, returns `undefined`. If getting, returns the file size. - - -> ```FS.File.prototype.size = function(value, options) { ...``` [fsFile-common.js:618](fsFile-common.js#L618) - - -- - -### *fsFile*.type([value], [options])  Anywhere ### - -*This method __type__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __value__ *{String}* (Optional) - - If setting the type, specify the new type as the first argument. Otherwise the options argument should be first. - -* __options__ *{Object}* (Optional) - * __store__ *{Object}* (Optional, Default = none,original) - - Get or set the type of the version of the file that was saved in this store. Default is the original file type. - - * __updateFileRecordFirst__ *{Boolean}* (Optional, Default = false) - - Update this instance with data from the DB first? Applies to getter usage only. - - * __save__ *{Boolean}* (Optional, Default = true) - - Save change to database? Applies to setter usage only. - - -__Returns__ *{String|undefined}* -If setting, returns `undefined`. If getting, returns the file type. - - -> ```FS.File.prototype.type = function(value, options) { ...``` [fsFile-common.js:643](fsFile-common.js#L643) - - -- - -### *fsFile*.updatedAt([value], [options])  Anywhere ### - -*This method __updatedAt__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __value__ *{String}* (Optional) - - If setting updatedAt, specify the new date as the first argument. Otherwise the options argument should be first. - -* __options__ *{Object}* (Optional) - * __store__ *{Object}* (Optional, Default = none,original) - - Get or set the last updated date for the version of the file that was saved in this store. Default is the original last updated date. - - * __updateFileRecordFirst__ *{Boolean}* (Optional, Default = false) - - Update this instance with data from the DB first? Applies to getter usage only. - - * __save__ *{Boolean}* (Optional, Default = true) - - Save change to database? Applies to setter usage only. - - -__Returns__ *{String|undefined}* -If setting, returns `undefined`. If getting, returns the file's last updated date. - - -> ```FS.File.prototype.updatedAt = function(value, options) { ...``` [fsFile-common.js:668](fsFile-common.js#L668) - - -*** - -__File: ["fsFile-server.js"](fsFile-server.js) Where: {server}__ - -*** - -### *fsFile*.logCopyFailure(storeName, maxTries)  Server ### - -``` -Notes a details about a storage adapter failure within the file record -``` -*This method __logCopyFailure__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __storeName__ *{string}* -* __maxTries__ *{number}* - -__Returns__ *{undefined}* - -__TODO__ -``` -* deprecate this -``` - - -> ```FS.File.prototype.logCopyFailure = function(storeName, maxTries) { ...``` [fsFile-server.js:8](fsFile-server.js#L8) - - -- - -### *fsFile*.failedPermanently(storeName)  Server ### - -``` -Has this store permanently failed? -``` -*This method __failedPermanently__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __storeName__ *{String}* - - The name of the store - - -__Returns__ *{boolean}* -Has this store failed permanently? - -__TODO__ -``` -* deprecate this -``` - - -> ```FS.File.prototype.failedPermanently = function(storeName) { ...``` [fsFile-server.js:41](fsFile-server.js#L41) - - -- - -### *fsFile*.createReadStream([storeName])  Server ### - -*This method __createReadStream__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __storeName__ *{String}* (Optional) - -__Returns__ *{stream.Readable}* -Readable NodeJS stream - - -Returns a readable stream. Where the stream reads from depends on the FS.File instance and whether you pass a store name. - -If you pass a `storeName`, a readable stream for the file data saved in that store is returned. -If you don't pass a `storeName` and data is attached to the FS.File instance (on `data` property, which must be a DataMan instance), then a readable stream for the attached data is returned. -If you don't pass a `storeName` and there is no data attached to the FS.File instance, a readable stream for the file data currently in the temporary store (`FS.TempStore`) is returned. - - -> ```FS.File.prototype.createReadStream = function(storeName) { ...``` [fsFile-server.js:62](fsFile-server.js#L62) - - -- - -### *fsFile*.createWriteStream([storeName])  Server ### - -*This method __createWriteStream__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __storeName__ *{String}* (Optional) - -__Returns__ *{stream.Writeable}* -Writeable NodeJS stream - - -Returns a writeable stream. Where the stream writes to depends on whether you pass in a store name. - -If you pass a `storeName`, a writeable stream for (over)writing the file data in that store is returned. -If you don't pass a `storeName`, a writeable stream for writing to the temp store for this file is returned. - - -> ```FS.File.prototype.createWriteStream = function(storeName) { ...``` [fsFile-server.js:100](fsFile-server.js#L100) - - -- - -### *fsFile*.copy()  Server ### - -*This method __copy__ is defined in `prototype` of `FS.File`* - -__Returns__ *{FS.File}* -The new FS.File instance - - -> ```FS.File.prototype.copy = function() { ...``` [fsFile-server.js:126](fsFile-server.js#L126) - - diff --git a/packages/wekan-cfs-file/package.js b/packages/wekan-cfs-file/package.js deleted file mode 100644 index d14cc069f..000000000 --- a/packages/wekan-cfs-file/package.js +++ /dev/null @@ -1,55 +0,0 @@ -Package.describe({ - git: 'https://github.com/zcfs/Meteor-cfs-file.git', - name: 'wekan-cfs-file', - version: '0.1.17', - summary: 'CollectionFS, FS.File object' -}); - -Npm.depends({ - temp: "0.7.0" // for tests only -}); - -Package.onUse(function(api) { - api.versionsFrom('1.0'); - - // This imply is needed for tests, and is technically probably correct anyway. - api.imply([ - 'wekan-cfs-base-package@0.0.30' - ]); - - api.use([ - 'wekan-cfs-base-package@0.0.30', - 'wekan-cfs-storage-adapter@0.2.1', - 'tracker', - 'check', - 'ddp', - 'mongo', - 'http', - 'wekan-cfs-data-man@0.0.6', - 'raix:eventemitter@0.1.1' - ]); - - api.addFiles([ - 'fsFile-common.js' - ], 'client'); - - api.addFiles([ - 'fsFile-common.js', - 'fsFile-server.js' - ], 'server'); -}); - -Package.onTest(function (api) { - api.use([ - 'wekan-cfs-standard-packages@0.0.0', - 'wekan-cfs-gridfs@0.0.0', - 'tinytest@1.0.0', - 'http@1.0.0', - 'test-helpers@1.0.0', - 'wekan-cfs-http-methods@0.0.29' - ]); - - api.addFiles([ - 'tests/file-tests.js' - ]); -}); diff --git a/packages/wekan-cfs-file/tests/file-tests.js b/packages/wekan-cfs-file/tests/file-tests.js deleted file mode 100644 index 7ad3310e4..000000000 --- a/packages/wekan-cfs-file/tests/file-tests.js +++ /dev/null @@ -1,436 +0,0 @@ -function bin2str(bufView) { - var length = bufView.length; - var result = ''; - for (var i = 0; i length) { - addition = length - i; - } - try { - // this fails on phantomjs due to old webkit bug; hence the try/catch - result += String.fromCharCode.apply(null, bufView.subarray(i,i+addition)); - } catch (e) { - var dataArray = []; - for (var j = i; j < i+addition; j++) { - dataArray.push(bufView[j]); - } - result += String.fromCharCode.apply(null, dataArray); - } - } - return result; -} - -//function ab2str(buffer) { -// return bin2str(new Uint8Array(buffer)); -//} - -function str2ab(str) { - var buf = new ArrayBuffer(str.length); - var bufView = new Uint8Array(buf); - for (var i=0, strLen=str.length; inew *fsStore*.GridFS(name, options)  Server ### - -*This method __GridFS__ is defined in `FS.Store`* - -__Arguments__ - -* __name__ *{String}* - - The store name - -* __options__ *{Object}* - * __beforeSave__ *{Function}* (Optional) - - Function to run before saving a file from the server. The context of the function will be the `FS.File` instance we're saving. The function may alter its properties. - - * __maxTries__ *{Number}* (Optional, Default = 5) - - Max times to attempt saving a file - - -__Returns__ *{FS.StorageAdapter}* -An instance of FS.StorageAdapter. - - -Creates a GridFS store instance on the server. Inherits from FS.StorageAdapter -type. - -> ```FS.Store.GridFS = function(name, options) { ...``` [gridfs.server.js:16](gridfs.server.js#L16) - - -- - -### new *fsStore*.GridFS(name, options)  Client ### - -*This method __GridFS__ is defined in `FS.Store`* - -__Arguments__ - -* __name__ *{String}* - - The store name - -* __options__ *{Object}* - * __beforeSave__ *{Function}* (Optional) - - Function to run before saving a file from the client. The context of the function will be the `FS.File` instance we're saving. The function may alter its properties. - - * __maxTries__ *{Number}* (Optional, Default = 5) - - Max times to attempt saving a file - - -__Returns__ *{undefined}* - - -Creates a GridFS store instance on the client, which is just a shell object -storing some info. - -> ```FS.Store.GridFS = function(name, options) { ...``` [gridfs.client.js:13](gridfs.client.js#L13) - - diff --git a/packages/wekan-cfs-gridfs/gridfs.client.js b/packages/wekan-cfs-gridfs/gridfs.client.js deleted file mode 100644 index 3cb26583b..000000000 --- a/packages/wekan-cfs-gridfs/gridfs.client.js +++ /dev/null @@ -1,21 +0,0 @@ -/** - * @public - * @constructor - * @param {String} name - The store name - * @param {Object} options - * @param {Function} [options.beforeSave] - Function to run before saving a file from the client. The context of the function will be the `FS.File` instance we're saving. The function may alter its properties. - * @param {Number} [options.maxTries=5] - Max times to attempt saving a file - * @returns {undefined} - * - * Creates a GridFS store instance on the client, which is just a shell object - * storing some info. - */ -FS.Store.GridFS = function(name, options) { - var self = this; - if (!(self instanceof FS.Store.GridFS)) - throw new Error('FS.Store.GridFS missing keyword "new"'); - - return new FS.StorageAdapter(name, options, { - typeName: 'storage.gridfs' - }); -}; diff --git a/packages/wekan-cfs-gridfs/gridfs.server.js b/packages/wekan-cfs-gridfs/gridfs.server.js deleted file mode 100644 index 90b92e0ca..000000000 --- a/packages/wekan-cfs-gridfs/gridfs.server.js +++ /dev/null @@ -1,176 +0,0 @@ -var path = Npm.require('path'); -var mongodb = Npm.require('mongodb'); -var ObjectID = Npm.require('mongodb').ObjectID; -var Grid = Npm.require('gridfs-stream'); -//var Grid = Npm.require('gridfs-locking-stream'); - -var chunkSize = 1024*1024*2; // 256k is default GridFS chunk size, but performs terribly for largish files - -/** - * @public - * @constructor - * @param {String} name - The store name - * @param {Object} options - * @param {Function} [options.beforeSave] - Function to run before saving a file from the server. The context of the function will be the `FS.File` instance we're saving. The function may alter its properties. - * @param {Number} [options.maxTries=5] - Max times to attempt saving a file - * @returns {FS.StorageAdapter} An instance of FS.StorageAdapter. - * - * Creates a GridFS store instance on the server. Inherits from FS.StorageAdapter - * type. - */ - -FS.Store.GridFS = function(name, options) { - var self = this; - options = options || {}; - - var gridfsName = name; - var mongoOptions = options.mongoOptions || {}; - - if (!(self instanceof FS.Store.GridFS)) - throw new Error('FS.Store.GridFS missing keyword "new"'); - - if (!options.mongoUrl) { - options.mongoUrl = process.env.MONGO_URL; - // When using a Meteor MongoDB instance, preface name with "cfs_gridfs." - gridfsName = "cfs_gridfs." + name; - } - - if (!options.mongoOptions) { - options.mongoOptions = { db: { native_parser: true }, server: { auto_reconnect: true }}; - } - - if (options.chunkSize) { - chunkSize = options.chunkSize; - } - - return new FS.StorageAdapter(name, options, { - - typeName: 'storage.gridfs', - fileKey: function(fileObj) { - // We should not have to mount the file here - We assume its taken - // care of - Otherwise we create new files instead of overwriting - var key = { - _id: null, - filename: null - }; - - // If we're passed a fileObj, we retrieve the _id and filename from it. - if (fileObj) { - var info = fileObj._getInfo(name, {updateFileRecordFirst: false}); - key._id = info.key || null; - key.filename = info.name || fileObj.name({updateFileRecordFirst: false}) || (fileObj.collectionName + '-' + fileObj._id); - } - - // If key._id is null at this point, createWriteStream will let GridFS generate a new ID - return key; - }, - createReadStream: function(fileKey, options) { - options = options || {}; - - // Init GridFS - var gfs = new Grid(self.db, mongodb); - - // Set the default streamning settings - var settings = { - _id: new ObjectID(fileKey._id), - root: gridfsName - }; - - // Check if this should be a partial read - if (typeof options.start !== 'undefined' && typeof options.end !== 'undefined' ) { - // Add partial info - settings.range = { - startPos: options.start, - endPos: options.end - }; - } - - FS.debug && console.log('GRIDFS', settings); - - return gfs.createReadStream(settings); - - }, - createWriteStream: function(fileKey, options) { - options = options || {}; - - // Init GridFS - var gfs = new Grid(self.db, mongodb); - - var opts = { - filename: fileKey.filename, - mode: 'w', - root: gridfsName, - chunk_size: options.chunk_size || chunkSize, - // We allow aliases, metadata and contentType to be passed in via - // options - aliases: options.aliases || [], - metadata: options.metadata || null, - content_type: options.contentType || 'application/octet-stream' - }; - - if (fileKey._id) { - opts._id = new ObjectID(fileKey._id); - } - - var writeStream = gfs.createWriteStream(opts); - - writeStream.on('close', function(file) { - if (!file) { - // gridfs-stream will emit "close" without passing a file - // if there is an error. We can simply exit here because - // the "error" listener will also be called in this case. - return; - } - - if (FS.debug) console.log('SA GridFS - DONE!'); - - // Emit end and return the fileKey, size, and updated date - writeStream.emit('stored', { - // Set the generated _id so that we know it for future reads and writes. - // We store the _id as a string and only convert to ObjectID right before - // reading, writing, or deleting. If we store the ObjectID itself, - // Meteor (EJSON?) seems to convert it to a LocalCollection.ObjectID, - // which GFS doesn't understand. - fileKey: file._id.toString(), - size: file.length, - storedAt: file.uploadDate || new Date() - }); - }); - - writeStream.on('error', function(error) { - console.log('SA GridFS - ERROR!', error); - }); - - return writeStream; - - }, - remove: function(fileKey, callback) { - // Init GridFS - var gfs = new Grid(self.db, mongodb); - - try { - gfs.remove({ _id: new ObjectID(fileKey._id), root: gridfsName }, callback); - } catch(err) { - callback(err); - } - }, - - // Not implemented - watch: function() { - throw new Error("GridFS storage adapter does not support the sync option"); - }, - - init: function(callback) { - mongodb.MongoClient.connect(options.mongoUrl, mongoOptions, function (err, db) { - if (err) { return callback(err); } - self.db = db; - - // ensure that indexes are added as otherwise CollectionFS fails for Mongo >= 3.0 - var collection = new Mongo.Collection(gridfsName); - collection.rawCollection().ensureIndex({ "files_id": 1, "n": 1}); - - callback(null); - }); - } - }); -}; diff --git a/packages/wekan-cfs-gridfs/internal.api.md b/packages/wekan-cfs-gridfs/internal.api.md deleted file mode 100644 index cb81e7439..000000000 --- a/packages/wekan-cfs-gridfs/internal.api.md +++ /dev/null @@ -1,75 +0,0 @@ -## Public and Private API ## - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -*** - -__File: ["gridfs.server.js"](gridfs.server.js) Where: {server}__ - -*** - -### new *fsStore*.GridFS(name, options)  Server ### - -*This method __GridFS__ is defined in `FS.Store`* - -__Arguments__ - -* __name__ *{String}* - - The store name - -* __options__ *{Object}* - * __beforeSave__ *{Function}* (Optional) - - Function to run before saving a file from the server. The context of the function will be the `FS.File` instance we're saving. The function may alter its properties. - - * __maxTries__ *{Number}* (Optional, Default = 5) - - Max times to attempt saving a file - - -__Returns__ *{FS.StorageAdapter}* -An instance of FS.StorageAdapter. - - -Creates a GridFS store instance on the server. Inherits from FS.StorageAdapter -type. - -> ```FS.Store.GridFS = function(name, options) { ...``` [gridfs.server.js:16](gridfs.server.js#L16) - - -*** - -__File: ["gridfs.client.js"](gridfs.client.js) Where: {client}__ - -*** - -### new *fsStore*.GridFS(name, options)  Client ### - -*This method __GridFS__ is defined in `FS.Store`* - -__Arguments__ - -* __name__ *{String}* - - The store name - -* __options__ *{Object}* - * __beforeSave__ *{Function}* (Optional) - - Function to run before saving a file from the client. The context of the function will be the `FS.File` instance we're saving. The function may alter its properties. - - * __maxTries__ *{Number}* (Optional, Default = 5) - - Max times to attempt saving a file - - -__Returns__ *{undefined}* - - -Creates a GridFS store instance on the client, which is just a shell object -storing some info. - -> ```FS.Store.GridFS = function(name, options) { ...``` [gridfs.client.js:13](gridfs.client.js#L13) - - diff --git a/packages/wekan-cfs-gridfs/package.js b/packages/wekan-cfs-gridfs/package.js deleted file mode 100755 index 6c430f22a..000000000 --- a/packages/wekan-cfs-gridfs/package.js +++ /dev/null @@ -1,24 +0,0 @@ -Package.describe({ - name: 'wekan-cfs-gridfs', - version: '0.0.34', - summary: 'GridFS storage adapter for CollectionFS', - git: 'https://github.com/zcfs/Meteor-cfs-gridfs.git' -}); - -Npm.depends({ - mongodb: '2.2.9', - 'gridfs-stream': '1.1.1' - //'gridfs-locking-stream': '0.0.3' -}); - -Package.onUse(function (api) { - api.use(['wekan-cfs-base-package@0.0.30', 'wekan-cfs-storage-adapter@0.2.3', 'ecmascript@0.1.0']); - api.addFiles('gridfs.server.js', 'server'); - api.addFiles('gridfs.client.js', 'client'); -}); - -Package.onTest(function (api) { - api.use(['wekan-cfs-gridfs', 'test-helpers', 'tinytest'], 'server'); - api.addFiles('tests/server-tests.js', 'server'); - api.addFiles('tests/client-tests.js', 'client'); -}); diff --git a/packages/wekan-cfs-gridfs/tests/client-tests.js b/packages/wekan-cfs-gridfs/tests/client-tests.js deleted file mode 100644 index 222af562f..000000000 --- a/packages/wekan-cfs-gridfs/tests/client-tests.js +++ /dev/null @@ -1,44 +0,0 @@ -function equals(a, b) { - return !!(EJSON.stringify(a) === EJSON.stringify(b)); -} - -Tinytest.add('cfs-gridfs - client - test environment', function(test) { - test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection'); - test.isTrue(typeof CFSErrorType !== 'undefined', 'test environment not initialized CFSErrorType'); -}); - -/* - * FS.File Client Tests - * - * construct FS.File with no arguments - * construct FS.File passing in File - * construct FS.File passing in Blob - * load blob into FS.File and then call FS.File.toDataUrl - * call FS.File.setDataFromBinary, then FS.File.getBlob(); make sure correct data is returned - * load blob into FS.File and then call FS.File.getBinary() with and without start/end; make sure correct data is returned - * construct FS.File, set FS.File.collectionName to a CFS name, and then test FS.File.update/remove/get/put/del/url - * set FS.File.name to a filename and test that FS.File.getExtension() returns the extension - * load blob into FS.File and make sure FS.File.saveLocal initiates a download (possibly can't do automatically) - * - */ - - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-gridfs/tests/server-tests.js b/packages/wekan-cfs-gridfs/tests/server-tests.js deleted file mode 100644 index 61a7a3f92..000000000 --- a/packages/wekan-cfs-gridfs/tests/server-tests.js +++ /dev/null @@ -1,49 +0,0 @@ -function equals(a, b) { - return !!(EJSON.stringify(a) === EJSON.stringify(b)); -} - -Tinytest.add('cfs-gridfs - server - test environment', function(test) { - test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection'); - test.isTrue(typeof CFSErrorType !== 'undefined', 'test environment not initialized CFSErrorType'); -}); - -/* - * FS.File Server Tests - * - * construct FS.File with no arguments - * load data with FS.File.setDataFromBuffer - * load data with FS.File.setDataFromBinary - * load data and then call FS.File.toDataUrl with and without callback - * load buffer into FS.File and then call FS.File.getBinary with and without start/end; make sure correct data is returned - * construct FS.File, set FS.File.collectionName to a CFS name, and then test FS.File.update/remove/get/put/del/url - * (call these with and without callback to test sync vs. async) - * set FS.File.name to a filename and test that FS.File.getExtension() returns the extension - * - * - * FS.Collection Server Tests - * - * Make sure options.filter is respected - * - * - */ - - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-http-methods/.editorconfig b/packages/wekan-cfs-http-methods/.editorconfig deleted file mode 100644 index a2cc1c1fe..000000000 --- a/packages/wekan-cfs-http-methods/.editorconfig +++ /dev/null @@ -1,18 +0,0 @@ -# .editorconfig -# Meteor adapted EditorConfig, http://EditorConfig.org -# By RaiX 2013 - -root = true - -[*.js] -end_of_line = lf -insert_final_newline = true -indent_style = space -indent_size = 2 -trim_trailing_whitespace = true -charset = utf-8 -max_line_length = 80 -indent_brace_style = 1TBS -spaces_around_operators = true -quote_type = auto -# curly_bracket_next_line = true \ No newline at end of file diff --git a/packages/wekan-cfs-http-methods/.gitignore b/packages/wekan-cfs-http-methods/.gitignore deleted file mode 100644 index 361e39a8f..000000000 --- a/packages/wekan-cfs-http-methods/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.build* -/.versions \ No newline at end of file diff --git a/packages/wekan-cfs-http-methods/.jshintrc b/packages/wekan-cfs-http-methods/.jshintrc deleted file mode 100644 index b288c9edc..000000000 --- a/packages/wekan-cfs-http-methods/.jshintrc +++ /dev/null @@ -1,140 +0,0 @@ -{ - // JSHint Meteor Configuration File - // Match the Meteor Style Guide - // - // By @raix with contributions from @aldeed and @awatson1978 - // Source https://github.com/raix/Meteor-jshintrc - // - // See http://jshint.com/docs/ for more details - - "maxerr" : 50, // {int} Maximum error before stopping - - // Enforcing - "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.) - "camelcase" : false, // false: Identifiers do not need to be in camelCase. We would like to enforce this except for when interacting with our api objects which use snakeCase properties. - "curly" : false, // false: Do not require {} for every new block or scope - "eqeqeq" : true, // true: Require triple equals (===) for comparison - "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty() - "immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());` - "indent" : 2, // {int} Number of spaces to use for indentation - "latedef" : false, // true: Require variables/functions to be defined before being used - "newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()` - "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee` - "noempty" : true, // true: Prohibit use of empty blocks - "nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment) - "plusplus" : false, // true: Prohibit use of `++` & `--` - "quotmark" : false, // Quotation mark consistency: - // false : do nothing (default) - // true : ensure whatever is used is consistent - // "single" : require single quotes - // "double" : require double quotes - "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks) - "unused" : true, // true: Require all defined variables be used - "strict" : false, // false: Do not require all functions to be run in ES5 Strict Mode - "trailing" : true, // true: Prohibit trailing whitespaces - "maxparams" : false, // {int} Max number of formal params allowed per function - "maxdepth" : false, // {int} Max depth of nested blocks (within functions) - "maxstatements" : false, // {int} Max number statements per function - "maxcomplexity" : false, // {int} Max cyclomatic complexity per function - "maxlen" : 250, // {int} Max number of characters per line - - // Relaxing - "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons) - "boss" : false, // true: Tolerate assignments where comparisons would be expected - "debug" : false, // true: Allow debugger statements e.g. browser breakpoints. - "eqnull" : false, // true: Tolerate use of `== null` - "es5" : false, // true: Allow ES5 syntax (ex: getters and setters) - "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`) - "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features) - // (ex: `for each`, multiple try/catch, function expression…) - "evil" : false, // true: Tolerate use of `eval` and `new Function()` - "expr" : true, // true: Tolerate `ExpressionStatement` as Programs - "funcscope" : false, // true: Tolerate defining variables inside control statements" - "globalstrict" : true, // true: Allow global "use strict" (also enables 'strict') - "iterator" : false, // true: Tolerate using the `__iterator__` property - "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block - "laxbreak" : false, // true: Tolerate possibly unsafe line breakings - "laxcomma" : false, // true: Tolerate comma-first style coding - "loopfunc" : false, // true: Tolerate functions being defined in loops - "multistr" : false, // true: Tolerate multi-line strings - "proto" : false, // true: Tolerate using the `__proto__` property - "scripturl" : false, // true: Tolerate script-targeted URLs - "smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment - "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;` - "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation - "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;` - "validthis" : false, // true: Tolerate using this in a non-constructor function - - // Environments - "browser" : true, // Web Browser (window, document, etc) - "couch" : false, // CouchDB - "devel" : true, // Development/debugging (alert, confirm, etc) - "dojo" : false, // Dojo Toolkit - "jquery" : false, // jQuery - "mootools" : false, // MooTools - "node" : false, // Node.js - "nonstandard" : false, // Widely adopted globals (escape, unescape, etc) - "prototypejs" : false, // Prototype and Scriptaculous - "rhino" : false, // Rhino - "worker" : false, // Web Workers - "wsh" : false, // Windows Scripting Host - "yui" : false, // Yahoo User Interface - //"meteor" : false, // Meteor.js - - // Legacy - "nomen" : false, // true: Prohibit dangling `_` in variables - "onevar" : false, // true: Allow only one `var` statement per function - "passfail" : false, // true: Stop on first error - "white" : false, // true: Check against strict whitespace and indentation rules - - // Custom globals, from http://docs.meteor.com, in the order they appear there - "globals" : { - "Meteor": false, - "DDP": false, - "Mongo": false, - "Session": false, - "Accounts": false, - "Template": false, - "Blaze": false, - "Spacebars": false, - "Match": false, - "check": false, - "Tracker": false, - "ReactiveVar": false, - "ReactiveDict": false, - "EJSON": false, - "HTTP": false, - "Email": false, - "Assets": false, - "Package": false, - "App": false, //mobile-config.js - "cordova": false, - "Cordova": false, - "Buffer": false, - - // Meteor internals - "DDPServer": false, - "global": false, - "Log": false, - "MongoInternals": false, - "process": false, - "Retry": false, - "WebApp": false, - "WebAppInternals": false, - - // globals useful when creating Meteor packages - "Npm": false, - "Tinytest": false, - - // common Meteor packages - "HTTP": true, - "Random": false, - "_": false, // Underscore.js - "$": false, // jQuery - - // This package - "_methodHTTP": true, - "Fiber": true, - "runServerMethod": true - } -} diff --git a/packages/wekan-cfs-http-methods/.travis.yml b/packages/wekan-cfs-http-methods/.travis.yml deleted file mode 100644 index 6a4640033..000000000 --- a/packages/wekan-cfs-http-methods/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - "0.10" -before_install: - - "curl -L http://git.io/s0Zu-w | /bin/sh" \ No newline at end of file diff --git a/packages/wekan-cfs-http-methods/CHANGELOG.md b/packages/wekan-cfs-http-methods/CHANGELOG.md deleted file mode 100644 index 425243944..000000000 --- a/packages/wekan-cfs-http-methods/CHANGELOG.md +++ /dev/null @@ -1,152 +0,0 @@ -# Changelog - -## vCurrent - -## [v0.0.30] -#### 9/9/15 by Eric Dobbertin -- Ensure we do not try to end responses twice - -## [v0.0.29] -#### 29/4/15 by Eric Dobbertin -- Respond properly to 206 Range requests (thanks [cherbst](https://github.com/cherbst)) - -## [v0.0.28] -#### 8/4/15 by Eric Dobbertin -- Fix issue where response would not be sent when using streams - -## [v0.0.26] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.26) -#### 17/12/14 by Morten Henriksen -- mbr update, remove versions.json - -## [v0.0.25] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.25) -#### 17/12/14 by Morten Henriksen -- mbr update versions and fix warnings - -- *Merged pull-request:* "- Added link to documentation about usage of HTTP client-side" [#22](https://github.com/zcfs/Meteor-http-methods/issues/22) ([jkaan](https://github.com/jkaan)) - -- *Merged pull-request:* "Typos." [#23](https://github.com/zcfs/Meteor-http-methods/issues/23) ([bradvogel](https://github.com/bradvogel)) - -- - Added link to documentation about usage of HTTP client-side - -- *Merged pull-request:* "typo in example: this.params instead of this.param" [#21](https://github.com/zcfs/Meteor-http-methods/issues/21) ([lukasvan3l](https://github.com/lukasvan3l)) - -- typo in example: this.params instead of this.param - -- *Merged pull-request:* ""code" is not always there" [#20](https://github.com/zcfs/Meteor-http-methods/issues/20) ([lukasvan3l](https://github.com/lukasvan3l)) - -- code is not always there - -- 0.9.1 support - -Patches by GitHub users [@jkaan](https://github.com/jkaan), [@bradvogel](https://github.com/bradvogel), [@lukasvan3l](https://github.com/lukasvan3l). - -## [v0.0.23] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.23) -#### 25/08/14 by Morten Henriksen -- *Fixed bug:* "Cannot transfer a file stream over 5Mb to the server." [#17](https://github.com/zcfs/Meteor-http-methods/issues/17) - -- *Merged pull-request:* "Add this.requestHeaders to readme" [#12](https://github.com/zcfs/Meteor-http-methods/issues/12) ([matthewsimo](https://github.com/matthewsimo)) - -- Add this.requestHeaders to readme - -Patches by GitHub user [@matthewsimo](https://github.com/matthewsimo). - -## [v0.0.22] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.22) -#### 25/03/14 by Morten Henriksen -- *Merged pull-request:* "Typo fixes" [#11](https://github.com/zcfs/Meteor-http-methods/issues/11) ([dandv](https://github.com/dandv)) - -- *Merged pull-request:* "Cosmetic fixes" [#10](https://github.com/zcfs/Meteor-http-methods/issues/10) ([dandv](https://github.com/dandv)) - -- Typo fixes - -- Cosmetic fixes - -Patches by GitHub user [@dandv](https://github.com/dandv). - -## [v0.0.21] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.21) -#### 23/03/14 by Morten Henriksen -## [v0.0.20] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.20) -#### 22/03/14 by Morten Henriksen -- add check - -- use collectionFS travis version force update - -## [v0.0.19] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.19) -#### 22/03/14 by Morten Henriksen -- Added ability for throwing http errors - -## [v0.0.18] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.18) -#### 18/03/14 by Morten Henriksen -- support HEAD requests - -- Add better streaming api and fix timeout / chunk size bug - -- refactor + added read stream - -- Add streaming WIP - -- Name tests by package - -- unbreak http-publish tests when run at in one test - -## [v0.0.17] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.17) -#### 22/02/14 by Morten Henriksen -- *Fixed bug:* "Binary use currently breaks json usage of data" [#6](https://github.com/zcfs/Meteor-http-methods/issues/6) - -## [v0.0.16] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.16) -#### 22/02/14 by Morten Henriksen -- Fix test - params from a query string is string now - -- make sure falsy turns into string - -## [v0.0.15] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.15) -#### 21/02/14 by Eric Dobbertin -## [v0.0.14] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.14) -#### 20/02/14 by Eric Dobbertin -- support binary data from the request - -## [v0.0.13] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.13) -#### 17/02/14 by Morten Henriksen -- Merge branch 'master' of https://github.com/zcfs/Meteor-http-methods - -- Bump to version 0.0.12 - -## [v0.0.12] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.12) -#### 17/02/14 by Eric Dobbertin -- Add requestHeaders to method context - -- Better handling of Meteor.Error's - -- url decode values in params - -- Allow user to set headers in custom response - -## [v0.0.11] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.11) -#### 08/12/13 by Morten Henriksen -## [v0.0.10] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.10) -#### 14/11/13 by Morten Henriksen -## [v0.0.9] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.9) -#### 30/09/13 by Morten Henriksen -- Add MIT License - -## [v0.0.8] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.8) -#### 28/09/13 by Morten Henriksen -- Comment feature - format selector as extension in url - -## [v0.0.7] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.7) -#### 18/09/13 by Morten Henriksen -## [v0.0.6, tag: v0.0.5] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.6, tag: v0.0.5) -#### 18/09/13 by Morten Henriksen -- Added more features - -## [v0.0.4] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.4) -#### 13/09/13 by Morten Henriksen -## [v0.0.3] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.3) -#### 12/09/13 by Morten Henriksen -## [v0.0.2] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.2) -#### 12/09/13 by Morten Henriksen -- *Fixed bug:* "allow empty last value in url" [#1](https://github.com/zcfs/Meteor-http-methods/issues/1) - -## [v0.0.1] (https://github.com/zcfs/Meteor-http-methods/tree/v0.0.1) -#### 12/09/13 by Morten Henriksen -- Init commit - diff --git a/packages/wekan-cfs-http-methods/LICENSE.md b/packages/wekan-cfs-http-methods/LICENSE.md deleted file mode 100644 index 2a5c5339e..000000000 --- a/packages/wekan-cfs-http-methods/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 [@raix](https://github.com/raix), aka Morten N.O. Nørgaard Henriksen, mh@gi-software.com - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/wekan-cfs-http-methods/README.md b/packages/wekan-cfs-http-methods/README.md deleted file mode 100644 index b253ff48b..000000000 --- a/packages/wekan-cfs-http-methods/README.md +++ /dev/null @@ -1,215 +0,0 @@ -wekan-cfs-http-methods [![Build Status](https://travis-ci.org/CollectionFS/Meteor-http-methods.png?branch=master)](https://travis-ci.org/CollectionFS/Meteor-http-methods) -============ - -~~Looking for maintainers - please reach out!~~ -This package is to be archived due to inability to find contributors, thanks to everyone who helped make it possible. - -**If you're looking for an alternative, we highly recommend [Meteor-Files](https://github.com/VeliovGroup/Meteor-Files) by [VeliovGroup](https://github.com/VeliovGroup)** - ---- - -Add server-side methods to the `HTTP` object your app. It's a server-side package only *- no client simulations added.* - -## Usage - -The `HTTP` object gets a `methods` method: - -```js - HTTP.methods({ - 'list': function() { - return 'Default content type is text/html'; - } - }); -``` - -## Methods scope -The methods scope contains different kinds of inputs. We can also get user details if logged in. - - -* `this.userId` - the user whose id and token was used to run this method, if set/found -* `this.method` - `GET`, `POST`, `PUT`, `DELETE` -* `this.query` - query params `?token=1&id=2` -> `{ token: 1, id: 2 }` -* `this.params` - set params `/foo/:name/test/:id` -> `{ name: '', id: '' }` -* `this.userAgent` - get the user agent string set in the request header -* `this.requestHeaders` - request headers object -* `this.setUserId(id)` - option for setting the `this.userId` -* `this.isSimulation` - always false on the server -* `this.unblock` - not implemented -* `this.setContentType('text/html')` - set the content type in header, defaults to `text/html` -* `this.addHeader('Content-Disposition', 'attachment; filename="name.ext"')` -* `this.setStatusCode(200)` - set the status code in the response header -* `createReadStream` - if a request, then get the read stream -* `createWriteStream` - if you want to stream data to the client -* `Error` - when streaming we have to be able to send error and close connection -* `this.request` The original request object - -## Passing data via header - -From the client: -```js - HTTP.post('list', { - data: { foo: 'bar' } - }, function(err, result) { - console.log('Content: ' + result.content + ' === "Hello"'); - }); -``` - -HTTP Server method: -```js - HTTP.methods({ - 'list': function(data) { - if (data.foo === 'bar') { - /* data we pass via the header is parsed by EJSON.parse - If not able, then it returns the raw data instead */ - } - return 'Hello'; - } - }); -``` - -## Parameters -The method name or URL can be used to pass parameters to the method. The parameters are available on the server under `this.params`: - -Client -```js - HTTP.post('/items/12/emails/5', function(err, result) { - console.log('Got back: ' + result.content); - }); -``` - -Server -```js - HTTP.methods({ - '/items/:itemId/emails/:emailId': function() { - // this.params.itemId === '12' - // this.params.emailId === '5' - } - }); -``` - -## Extended usage -The `HTTP.methods` normally takes a function, but it can be set to an object for fine-grained handling. - -Example: -```js - HTTP.methods({ - '/hello': { - get: function(data) {}, - // post: function(data) {}, - // put: function(data) {}, - // delete: function(data) {}, - // options: function() { - // // Example of a simple options function - // this.setStatusCode(200); - // this.addHeader('Accept', 'POST,PUT'); - // // The options for this restpoint - // var options = { - // POST: { - // description: 'Create an issue', - // parameters: { - // title: { - // type: 'string', - // description: 'Issue title' - // } - // } - // } - // }; - // // Print the options in pretty json - // return JSON.stringify(options, null, '\t'); - // }, - // stream: true // flag whether to allow stream handling in the request - } - }); -``` -*In this example the mounted http rest point will only support the `get` method* - -Example: -```js - HTTP.methods({ - '/hello': { - method: function(data) {}, - } - }); -``` -*In this example all methods `get`, `put`, `post`, `delete` will use the same function - This would be equal to setting the function directly on the http mount point* - -## Authentication - -The client needs the `access_token` to login in HTTP methods. *One could create a HTTP login/logout method for allowing pure external access* - -Client -```js - HTTP.post('/hello', { - params: { - token: Accounts && Accounts._storedLoginToken() - } - }, function(err, result) { - console.log('Got back: ' + result.content); - }); -``` - -Server -```js - 'hello': function(data) { - if (this.userId) { - var user = Meteor.users.findOne({ _id: this.userId }); - return 'Hello ' + (user && user.username || user && user.emails[0].address || 'user'); - } else { - this.setStatusCode(401); // Unauthorized - } - } -``` - -## Using custom authentication - -It's possible to make your own function to set the userId - not using the built-in token pattern. -```js - // My auth will return the userId - var myAuth = function() { - // Read the token from '/hello?token=5' - var userToken = self.query.token; - // Check the userToken before adding it to the db query - // Set the this.userId - if (userToken) { - var user = Meteor.users.findOne({ 'services.resume.loginTokens.token': userToken }); - - // Set the userId in the scope - return user && user._id; - } - }; - - HTTP.methods({ - '/hello': { - auth: myAuth, - method: function(data) { - // this.userId is set by myAuth - if (this.userId) { /**/ } else { /**/ } - } - } - }); -``` -*The above resembles the builtin auth handler* - -## Security -When buffering data instead of streaming we set the buffer limit to 5mb - This can be changed on the fly: -```js - // Set the max data length - // 5mb = 5 * 1024 * 1024 = 5242880; - HTTP.methodsMaxDataLength = 5242880; -``` - -## Login and logout (TODO) - -These operations are not currently supported for off Meteor use - there are some security considerations. - -`basic-auth` is broadly supported, but: -* password should not be sent in clear text - hash with base64? -* should be used on https connections -* Its difficult / impossible to logout a user? - -`token` the current `access_token` seems to be a better solution. Better control and options to logout users. But calling the initial `login` method still requires: -* hashing of password -* use https - -## HTTP Client-side usage -If you want to use the HTTP client-side functionality and find yourself having a hard time viewing all available options; these can be found on https://docs.meteor.com/#/full/http. diff --git a/packages/wekan-cfs-http-methods/http.methods.client.api.js b/packages/wekan-cfs-http-methods/http.methods.client.api.js deleted file mode 100644 index d6dd694a9..000000000 --- a/packages/wekan-cfs-http-methods/http.methods.client.api.js +++ /dev/null @@ -1,6 +0,0 @@ -HTTP = Package.http && Package.http.HTTP || {}; - -// Client-side simulation is not yet implemented -HTTP.methods = function() { - throw new Error('HTTP.methods not implemented on client-side'); -}; diff --git a/packages/wekan-cfs-http-methods/http.methods.server.api.js b/packages/wekan-cfs-http-methods/http.methods.server.api.js deleted file mode 100644 index fc3b9d116..000000000 --- a/packages/wekan-cfs-http-methods/http.methods.server.api.js +++ /dev/null @@ -1,644 +0,0 @@ -/* - -GET /note -GET /note/:id -POST /note -PUT /note/:id -DELETE /note/:id - -*/ -HTTP = Package.http && Package.http.HTTP || {}; - -// Primary local test scope -_methodHTTP = {}; - - -_methodHTTP.methodHandlers = {}; -_methodHTTP.methodTree = {}; - -// This could be changed eg. could allow larger data chunks than 1.000.000 -// 5mb = 5 * 1024 * 1024 = 5242880; -HTTP.methodsMaxDataLength = 5242880; //1e6; - -_methodHTTP.nameFollowsConventions = function(name) { - // Check that name is string, not a falsy or empty - return name && name === '' + name && name !== ''; -}; - - -_methodHTTP.getNameList = function(name) { - // Remove leading and trailing slashes and make command array - name = name && name.replace(/^\//g, '') || ''; // /^\/|\/$/g - // TODO: Get the format from the url - eg.: "/list/45.json" format should be - // set in this function by splitting the last list item by . and have format - // as the last item. How should we toggle: - // "/list/45/item.name.json" and "/list/45/item.name"? - // We would either have to check all known formats or allways determin the "." - // as an extension. Resolving in "json" and "name" as handed format - the user - // Could simply just add the format as a parametre? or be explicit about - // naming - return name && name.split('/') || []; -}; - -// Merge two arrays one containing keys and one values -_methodHTTP.createObject = function(keys, values) { - var result = {}; - if (keys && values) { - for (var i = 0; i < keys.length; i++) { - result[keys[i]] = values[i] && decodeURIComponent(values[i]) || ''; - } - } - return result; -}; - -_methodHTTP.addToMethodTree = function(methodName) { - var list = _methodHTTP.getNameList(methodName); - var name = '/'; - // Contains the list of params names - var params = []; - var currentMethodTree = _methodHTTP.methodTree; - - for (var i = 0; i < list.length; i++) { - - // get the key name - var key = list[i]; - // Check if it expects a value - if (key[0] === ':') { - // This is a value - params.push(key.slice(1)); - key = ':value'; - } - name += key + '/'; - - // Set the key into the method tree - if (typeof currentMethodTree[key] === 'undefined') { - currentMethodTree[key] = {}; - } - - // Dig deeper - currentMethodTree = currentMethodTree[key]; - - } - - if (_.isEmpty(currentMethodTree[':ref'])) { - currentMethodTree[':ref'] = { - name: name, - params: params - }; - } - - return currentMethodTree[':ref']; -}; - -// This method should be optimized for speed since its called on allmost every -// http call to the server so we return null as soon as we know its not a method -_methodHTTP.getMethod = function(name) { - // Check if the - if (!_methodHTTP.nameFollowsConventions(name)) { - return null; - } - var list = _methodHTTP.getNameList(name); - // Check if we got a correct list - if (!list || !list.length) { - return null; - } - // Set current refernce in the _methodHTTP.methodTree - var currentMethodTree = _methodHTTP.methodTree; - // Buffer for values to hand on later - var values = []; - // Iterate over the method name and check if its found in the method tree - for (var i = 0; i < list.length; i++) { - // get the key name - var key = list[i]; - // We expect to find the key or :value if not we break - if (typeof currentMethodTree[key] !== 'undefined' || - typeof currentMethodTree[':value'] !== 'undefined') { - // We got a result now check if its a value - if (typeof currentMethodTree[key] === 'undefined') { - // Push the value - values.push(key); - // Set the key to :value to dig deeper - key = ':value'; - } - - } else { - // Break - method call not found - return null; - } - - // Dig deeper - currentMethodTree = currentMethodTree[key]; - } - - // Extract reference pointer - var reference = currentMethodTree && currentMethodTree[':ref']; - if (typeof reference !== 'undefined') { - return { - name: reference.name, - params: _methodHTTP.createObject(reference.params, values), - handle: _methodHTTP.methodHandlers[reference.name] - }; - } else { - // Did not get any reference to the method - return null; - } -}; - -// This method retrieves the userId from the token and makes sure that the token -// is valid and not expired -_methodHTTP.getUserId = function() { - var self = this; - - // // Get ip, x-forwarded-for can be comma seperated ips where the first is the - // // client ip - // var ip = self.req.headers['x-forwarded-for'] && - // // Return the first item in ip list - // self.req.headers['x-forwarded-for'].split(',')[0] || - // // or return the remoteAddress - // self.req.connection.remoteAddress; - - // Check authentication - var userToken = self.query.token; - - // Check if we are handed strings - try { - userToken && check(userToken, String); - } catch(err) { - throw new Meteor.Error(404, 'Error user token and id not of type strings, Error: ' + (err.stack || err.message)); - } - - // Set the this.userId - if (userToken) { - // Look up user to check if user exists and is loggedin via token - var user = Meteor.users.findOne({ - $or: [ - {'services.resume.loginTokens.hashedToken': Accounts._hashLoginToken(userToken)}, - {'services.resume.loginTokens.token': userToken} - ] - }); - // TODO: check 'services.resume.loginTokens.when' to have the token expire - - // Set the userId in the scope - return user && user._id; - } - - return null; -}; - -// Expose the default auth for calling from custom authentication handlers. -HTTP.defaultAuth = _methodHTTP.getUserId; - -/* - -Add default support for options - -*/ -_methodHTTP.defaultOptionsHandler = function(methodObject) { - // List of supported methods - var allowMethods = []; - // The final result object - var result = {}; - - // Iterate over the methods - // XXX: We should have a way to extend this - We should have some schema model - // for our methods... - _.each(methodObject, function(f, methodName) { - // Skip the stream and auth functions - they are not public / accessible - if (methodName !== 'stream' && methodName !== 'auth') { - - // Create an empty description - result[methodName] = { description: '', parameters: {} }; - // Add method name to headers - allowMethods.push(methodName); - - } - }); - - // Lets play nice - this.setStatusCode(200); - - // We have to set some allow headers here - this.addHeader('Allow', allowMethods.join(',')); - - // Return json result - Pretty print - return JSON.stringify(result, null, '\t'); -}; - -// Public interface for adding server-side http methods - if setting a method to -// 'false' it would actually remove the method (can be used to unpublish a method) -HTTP.methods = function(newMethods) { - _.each(newMethods, function(func, name) { - if (_methodHTTP.nameFollowsConventions(name)) { - // Check if we got a function - //if (typeof func === 'function') { - var method = _methodHTTP.addToMethodTree(name); - // The func is good - if (typeof _methodHTTP.methodHandlers[method.name] !== 'undefined') { - if (func === false) { - // If the method is set to false then unpublish - delete _methodHTTP.methodHandlers[method.name]; - // Delete the reference in the _methodHTTP.methodTree - delete method.name; - delete method.params; - } else { - // We should not allow overwriting - following Meteor.methods - throw new Error('HTTP method "' + name + '" is already registered'); - } - } else { - // We could have a function or a object - // The object could have: - // '/test/': { - // auth: function() ... returning the userId using over default - // - // method: function() ... - // or - // post: function() ... - // put: - // get: - // delete: - // head: - // } - - /* - We conform to the object format: - { - auth: - post: - put: - get: - delete: - head: - } - This way we have a uniform reference - */ - - var uniObj = {}; - if (typeof func === 'function') { - uniObj = { - 'auth': _methodHTTP.getUserId, - 'stream': false, - 'POST': func, - 'PUT': func, - 'GET': func, - 'DELETE': func, - 'HEAD': func, - 'OPTIONS': _methodHTTP.defaultOptionsHandler - }; - } else { - uniObj = { - 'stream': func.stream || false, - 'auth': func.auth || _methodHTTP.getUserId, - 'POST': func.post || func.method, - 'PUT': func.put || func.method, - 'GET': func.get || func.method, - 'DELETE': func.delete || func.method, - 'HEAD': func.head || func.get || func.method, - 'OPTIONS': func.options || _methodHTTP.defaultOptionsHandler - }; - } - - // Registre the method - _methodHTTP.methodHandlers[method.name] = uniObj; // func; - - } - // } else { - // // We do require a function as a function to execute later - // throw new Error('HTTP.methods failed: ' + name + ' is not a function'); - // } - } else { - // We have to follow the naming spec defined in nameFollowsConventions - throw new Error('HTTP.method "' + name + '" invalid naming of method'); - } - }); -}; - -var sendError = function(res, code, message) { - if (code) { - res.writeHead(code); - } else { - res.writeHead(500); - } - res.end(message); -}; - -// This handler collects the header data into either an object (if json) or the -// raw data. The data is passed to the callback -var requestHandler = function(req, res, callback) { - if (typeof callback !== 'function') { - return null; - } - - // Container for buffers and a sum of the length - var bufferData = [], dataLen = 0; - - // Extract the body - req.on('data', function(data) { - bufferData.push(data); - dataLen += data.length; - - // We have to check the data length in order to spare the server - if (dataLen > HTTP.methodsMaxDataLength) { - dataLen = 0; - bufferData = []; - // Flood attack or faulty client - sendError(res, 413, 'Flood attack or faulty client'); - req.connection.destroy(); - } - }); - - // When message is ready to be passed on - req.on('end', function() { - if (res.finished) { - return; - } - - // Allow the result to be undefined if so - var result; - - // If data found the work it - either buffer or json - if (dataLen > 0) { - result = new Buffer(dataLen); - // Merge the chunks into one buffer - for (var i = 0, ln = bufferData.length, pos = 0; i < ln; i++) { - bufferData[i].copy(result, pos); - pos += bufferData[i].length; - delete bufferData[i]; - } - // Check if we could be dealing with json - if (result[0] == 0x7b && result[1] === 0x22) { - try { - // Convert the body into json and extract the data object - result = EJSON.parse(result.toString()); - } catch(err) { - // Could not parse so we return the raw data - } - } - } // Else result will be undefined - - try { - callback(result); - } catch(err) { - sendError(res, 500, 'Error in requestHandler callback, Error: ' + (err.stack || err.message) ); - } - }); - -}; - -// This is the simplest handler - it simply passes req stream as data to the -// method -var streamHandler = function(req, res, callback) { - try { - callback(); - } catch(err) { - sendError(res, 500, 'Error in requestHandler callback, Error: ' + (err.stack || err.message) ); - } -}; - -/* - Allow file uploads in cordova cfs -*/ -var setCordovaHeaders = function(request, response) { - var origin = request.headers.origin; - // Match http://localhost: for Cordova clients in Meteor 1.3 - // and http://meteor.local for earlier versions - if (origin && (origin === 'http://meteor.local' || /^http:\/\/localhost/.test(origin))) { - // We need to echo the origin provided in the request - response.setHeader("Access-Control-Allow-Origin", origin); - - response.setHeader("Access-Control-Allow-Methods", "PUT"); - response.setHeader("Access-Control-Allow-Headers", "Content-Type"); - } -}; - -// Handle the actual connection -WebApp.connectHandlers.use(function(req, res, next) { - - // Check to se if this is a http method call - var method = _methodHTTP.getMethod(req._parsedUrl.pathname); - - // If method is null then it wasn't and we pass the request along - if (method === null) { - return next(); - } - - var dataHandle = (method.handle && method.handle.stream)?streamHandler:requestHandler; - - dataHandle(req, res, function(data) { - // If methodsHandler not found or somehow the methodshandler is not a - // function then return a 404 - if (typeof method.handle === 'undefined') { - sendError(res, 404, 'Error HTTP method handler "' + method.name + '" is not found'); - return; - } - - // Set CORS headers for Meteor Cordova clients - setCordovaHeaders(req, res); - - // Set fiber scope - var fiberScope = { - // Pointers to Request / Response - req: req, - res: res, - // Request / Response helpers - statusCode: 200, - method: req.method, - // Headers for response - headers: { - 'Content-Type': 'text/html' // Set default type - }, - // Arguments - data: data, - query: req.query, - params: method.params, - // Method reference - reference: method.name, - methodObject: method.handle, - _streamsWaiting: 0 - }; - - // Helper functions this scope - Fiber = Npm.require('fibers'); - runServerMethod = Fiber(function(self) { - var result, resultBuffer; - - // We fetch methods data from methodsHandler, the handler uses the this.addItem() - // function to populate the methods, this way we have better check control and - // better error handling + messages - - // The scope for the user methodObject callbacks - var thisScope = { - // The user whos id and token was used to run this method, if set/found - userId: null, - // The id of the data - _id: null, - // Set the query params ?token=1&id=2 -> { token: 1, id: 2 } - query: self.query, - // Set params /foo/:name/test/:id -> { name: '', id: '' } - params: self.params, - // Method GET, PUT, POST, DELETE, HEAD - method: self.method, - // User agent - userAgent: req.headers['user-agent'], - // All request headers - requestHeaders: req.headers, - // Add the request object it self - request: req, - // Set the userId - setUserId: function(id) { - this.userId = id; - }, - // We dont simulate / run this on the client at the moment - isSimulation: false, - // Run the next method in a new fiber - This is default at the moment - unblock: function() {}, - // Set the content type in header, defaults to text/html? - setContentType: function(type) { - self.headers['Content-Type'] = type; - }, - setStatusCode: function(code) { - self.statusCode = code; - }, - addHeader: function(key, value) { - self.headers[key] = value; - }, - createReadStream: function() { - self._streamsWaiting++; - return req; - }, - createWriteStream: function() { - self._streamsWaiting++; - return res; - }, - Error: function(err) { - - if (err instanceof Meteor.Error) { - // Return controlled error - sendError(res, err.error, err.message); - } else if (err instanceof Error) { - // Return error trace - this is not intented - sendError(res, 503, 'Error in method "' + self.reference + '", Error: ' + (err.stack || err.message) ); - } else { - sendError(res, 503, 'Error in method "' + self.reference + '"' ); - } - - }, - // getData: function() { - // // XXX: TODO if we could run the request handler stuff eg. - // // in here in a fiber sync it could be cool - and the user did - // // not have to specify the stream=true flag? - // } - }; - - // This function sends the final response. Depending on the - // timing of the streaming, we might have to wait for all - // streaming to end, or we might have to wait for this function - // to finish after streaming ends. The checks in this function - // and the fact that we call it twice ensure that we will always - // send the response if we haven't sent an error response, but - // we will not send it too early. - function sendResponseIfDone() { - res.statusCode = self.statusCode; - // If no streams are waiting - if (self._streamsWaiting === 0 && - (self.statusCode === 200 || self.statusCode === 206) && - self.done && - !self._responseSent && - !res.finished) { - self._responseSent = true; - res.end(resultBuffer); - } - } - - var methodCall = self.methodObject[self.method]; - - // If the method call is set for the POST/PUT/GET or DELETE then run the - // respective methodCall if its a function - if (typeof methodCall === 'function') { - - // Get the userId - This is either set as a method specific handler and - // will allways default back to the builtin getUserId handler - try { - // Try to set the userId - thisScope.userId = self.methodObject.auth.apply(self); - } catch(err) { - sendError(res, err.error, (err.message || err.stack)); - return; - } - - // This must be attached before there's any chance of `createReadStream` - // or `createWriteStream` being called, which means before we do - // `methodCall.apply` below. - req.on('end', function() { - self._streamsWaiting--; - sendResponseIfDone(); - }); - - // Get the result of the methodCall - try { - if (self.method === 'OPTIONS') { - result = methodCall.apply(thisScope, [self.methodObject]) || ''; - } else { - result = methodCall.apply(thisScope, [self.data]) || ''; - } - } catch(err) { - if (err instanceof Meteor.Error) { - // Return controlled error - sendError(res, err.error, err.message); - } else { - // Return error trace - this is not intented - sendError(res, 503, 'Error in method "' + self.reference + '", Error: ' + (err.stack || err.message) ); - } - return; - } - - // Set headers - _.each(self.headers, function(value, key) { - // If value is defined then set the header, this allows for unsetting - // the default content-type - if (typeof value !== 'undefined') - res.setHeader(key, value); - }); - - // If OK / 200 then Return the result - if (self.statusCode === 200 || self.statusCode === 206) { - - if (self.method !== "HEAD") { - // Return result - if (typeof result === 'string') { - resultBuffer = new Buffer(result); - } else { - resultBuffer = new Buffer(JSON.stringify(result)); - } - - // Check if user wants to overwrite content length for some reason? - if (typeof self.headers['Content-Length'] === 'undefined') { - self.headers['Content-Length'] = resultBuffer.length; - } - - } - - self.done = true; - sendResponseIfDone(); - - } else { - // Allow user to alter the status code and send a message - sendError(res, self.statusCode, result); - } - - } else { - sendError(res, 404, 'Service not found'); - } - - - }); - // Run http methods handler - try { - runServerMethod.run(fiberScope); - } catch(err) { - sendError(res, 500, 'Error running the server http method handler, Error: ' + (err.stack || err.message)); - } - - }); // EO Request handler - - -}); diff --git a/packages/wekan-cfs-http-methods/http.methods.tests.js b/packages/wekan-cfs-http-methods/http.methods.tests.js deleted file mode 100644 index 7157feb18..000000000 --- a/packages/wekan-cfs-http-methods/http.methods.tests.js +++ /dev/null @@ -1,117 +0,0 @@ -function equals(a, b) { - return EJSON.stringify(a) === EJSON.stringify(b); -} - -Tinytest.add('http-methods - test environment', function(test) { - test.isTrue(typeof _methodHTTP !== 'undefined', 'test environment not initialized _methodHTTP'); - test.isTrue(typeof HTTP !== 'undefined', 'test environment not initialized HTTP'); - test.isTrue(typeof HTTP.methods !== 'undefined', 'test environment not initialized HTTP.methods'); - -}); - -Tinytest.add('http-methods - nameFollowsConventions', function(test) { - test.isFalse(_methodHTTP.nameFollowsConventions(), 'Tested methods naming convention 1'); - test.isFalse(_methodHTTP.nameFollowsConventions(''), 'Tested methods naming convention 2'); - test.isFalse(_methodHTTP.nameFollowsConventions({}), 'Tested methods naming convention 3'); - test.isFalse(_methodHTTP.nameFollowsConventions([1]), 'Tested methods naming convention 4'); - test.isFalse(_methodHTTP.nameFollowsConventions(-1), 'Tested methods naming convention 5'); - test.isFalse(_methodHTTP.nameFollowsConventions(1), 'Tested methods naming convention 6'); - test.isFalse(_methodHTTP.nameFollowsConventions(0.1), 'Tested methods naming convention 7'); - test.isFalse(_methodHTTP.nameFollowsConventions(-0.1), 'Tested methods naming convention 8'); - - test.isTrue(_methodHTTP.nameFollowsConventions('/test/test'), 'Tested methods naming convention leading slash'); - test.isTrue(_methodHTTP.nameFollowsConventions('test/test'), 'Tested methods naming convention'); -}); - -Tinytest.add('http-methods - getNameList', function(test) { - test.equal(EJSON.stringify(_methodHTTP.getNameList()), '[]', 'Name list failed'); - test.equal(EJSON.stringify(_methodHTTP.getNameList('')), '[]', 'Name list failed'); - test.equal(EJSON.stringify(_methodHTTP.getNameList('/')), '[]', 'Name list failed'); - test.equal(EJSON.stringify(_methodHTTP.getNameList('//')), '["",""]', 'Name list failed'); - - test.equal(EJSON.stringify(_methodHTTP.getNameList('/1/')), '["1",""]', 'Name list failed'); - test.equal(EJSON.stringify(_methodHTTP.getNameList('/1/2')), '["1","2"]', 'Name list failed'); - test.equal(EJSON.stringify(_methodHTTP.getNameList('/1/:name/2')), '["1",":name","2"]', 'Name list failed'); - test.equal(EJSON.stringify(_methodHTTP.getNameList('/1//2')), '["1","","2"]', 'Name list failed'); -}); - - -Tinytest.add('http-methods - createObject', function(test) { - test.equal(EJSON.stringify(_methodHTTP.createObject()), '{}', 'createObject failed'); - test.equal(EJSON.stringify(_methodHTTP.createObject(2, 4)), '{}', 'createObject failed'); - test.equal(EJSON.stringify(_methodHTTP.createObject(['foo'], [])), '{"foo":""}', 'createObject failed'); - test.equal(EJSON.stringify(_methodHTTP.createObject(['foo'], ['bar'])), '{"foo":"bar"}', 'createObject failed'); - test.equal(EJSON.stringify(_methodHTTP.createObject(['foo'], [3])), '{"foo":"3"}', 'createObject failed'); - test.equal(EJSON.stringify(_methodHTTP.createObject(['foo'], ['bar', 3])), '{"foo":"bar"}', 'createObject failed'); - test.equal(EJSON.stringify(_methodHTTP.createObject(['foo', 'foo'], ['bar', 3])), '{"foo":"3"}', 'createObject failed'); - test.equal(EJSON.stringify(_methodHTTP.createObject([''], ['bar', 3])), '{"":"bar"}', 'createObject failed'); - test.equal(EJSON.stringify(_methodHTTP.createObject(['', ''], ['bar', 3])), '{"":"3"}', 'createObject failed'); -}); - -Tinytest.add('http-methods - addToMethodTree', function(test) { - var original = _methodHTTP.methodTree; - _methodHTTP.methodTree = {}; - _methodHTTP.addToMethodTree('login'); - test.equal(EJSON.stringify(_methodHTTP.methodTree), '{"login":{":ref":{"name":"/login/","params":[]}}}', 'addToMethodTree failed'); - - _methodHTTP.methodTree = {}; - _methodHTTP.addToMethodTree('/foo/bar'); - test.equal(EJSON.stringify(_methodHTTP.methodTree), '{"foo":{"bar":{":ref":{"name":"/foo/bar/","params":[]}}}}', 'addToMethodTree failed'); - - _methodHTTP.methodTree = {}; - _methodHTTP.addToMethodTree('/foo/:name/bar'); - test.equal(EJSON.stringify(_methodHTTP.methodTree), '{"foo":{":value":{"bar":{":ref":{"name":"/foo/:value/bar/","params":["name"]}}}}}', 'addToMethodTree failed'); - - _methodHTTP.addToMethodTree('/foo/:name/bar'); - test.equal(EJSON.stringify(_methodHTTP.methodTree), '{"foo":{":value":{"bar":{":ref":{"name":"/foo/:value/bar/","params":["name"]}}}}}', 'addToMethodTree failed'); - - _methodHTTP.addToMethodTree('/foo/name/bar'); - test.equal(EJSON.stringify(_methodHTTP.methodTree), '{"foo":{":value":{"bar":{":ref":{"name":"/foo/:value/bar/","params":["name"]}}},"name":{"bar":{":ref":{"name":"/foo/name/bar/","params":[]}}}}}', 'addToMethodTree failed'); - - _methodHTTP.methodTree = original; -}); - -Tinytest.add('http-methods - getMethod', function(test) { - // Basic tests - test.equal(EJSON.stringify(_methodHTTP.getMethod('')), 'null', 'getMethod failed'); - test.equal(EJSON.stringify(_methodHTTP.getMethod('//')), 'null', 'getMethod failed'); - - _methodHTTP.addToMethodTree('login'); - test.equal(EJSON.stringify(_methodHTTP.getMethod('login')), '{"name":"/login/","params":{}}', 'getMethod failed'); - test.equal(EJSON.stringify(_methodHTTP.getMethod('/login')), '{"name":"/login/","params":{}}', 'getMethod failed'); - test.equal(EJSON.stringify(_methodHTTP.getMethod('login/')), 'null', 'getMethod failed'); - test.equal(EJSON.stringify(_methodHTTP.getMethod('/login/')), 'null', 'getMethod failed'); - test.equal(EJSON.stringify(_methodHTTP.getMethod('login/test')), 'null', 'getMethod failed'); - - _methodHTTP.addToMethodTree('/login/'); - test.equal(EJSON.stringify(_methodHTTP.getMethod('login')), '{"name":"/login/","params":{}}', 'getMethod failed'); - - // - - _methodHTTP.addToMethodTree('/login/foo'); - test.equal(EJSON.stringify(_methodHTTP.getMethod('login/foo')), '{"name":"/login/foo/","params":{}}', 'getMethod failed'); - - _methodHTTP.addToMethodTree('/login/:name/foo'); - test.equal(EJSON.stringify(_methodHTTP.getMethod('login/bar/foo')), '{"name":"/login/:value/foo/","params":{"name":"bar"}}', 'getMethod failed'); - test.equal(EJSON.stringify(_methodHTTP.getMethod('login/foo')), '{"name":"/login/foo/","params":{}}', 'getMethod failed'); - -}); - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equal(actual, expected, message, not) -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) diff --git a/packages/wekan-cfs-http-methods/package.js b/packages/wekan-cfs-http-methods/package.js deleted file mode 100644 index dc1266407..000000000 --- a/packages/wekan-cfs-http-methods/package.js +++ /dev/null @@ -1,31 +0,0 @@ -Package.describe({ - git: 'https://github.com/zcfs/Meteor-http-methods.git', - name: 'wekan-cfs-http-methods', - version: '0.0.32', - summary: 'Adds HTTP.methods RESTful' -}); - -Package.onUse(function(api) { - api.versionsFrom('1.0'); - - api.use(['webapp', 'underscore', 'ejson'], 'server'); - - api.use('http', { weak: true }); - - api.export && api.export('HTTP'); - - api.export && api.export('_methodHTTP', { testOnly: true }); - - api.addFiles('http.methods.client.api.js', 'client'); - api.addFiles('http.methods.server.api.js', 'server'); - -}); - -Package.onTest(function (api) { - api.use('wekan-cfs-http-methods', ['server']); - api.use('test-helpers', 'server'); - api.use(['tinytest', 'underscore', 'ejson', 'ordered-dict', - 'random', 'deps']); - - api.addFiles('http.methods.tests.js', 'server'); -}); diff --git a/packages/wekan-cfs-http-publish/.editorconfig b/packages/wekan-cfs-http-publish/.editorconfig deleted file mode 100644 index 37a7d486e..000000000 --- a/packages/wekan-cfs-http-publish/.editorconfig +++ /dev/null @@ -1,18 +0,0 @@ -# .editorconfig -# Meteor adapted EditorConfig, http://EditorConfig.org -# By RaiX 2013 - -root = true - -[*.js] -end_of_line = lf -insert_final_newline = true -indent_style = space -indent_size = 2 -trim_trailing_whitespace = true -charset = utf-8 -max_line_length = 80 -indent_brace_style = 1TBS -spaces_around_operators = true -quote_type = auto -# curly_bracket_next_line = true diff --git a/packages/wekan-cfs-http-publish/.gitignore b/packages/wekan-cfs-http-publish/.gitignore deleted file mode 100644 index 29c66e308..000000000 --- a/packages/wekan-cfs-http-publish/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -/versions.json -.build* -smart.lock -/nbproject/ \ No newline at end of file diff --git a/packages/wekan-cfs-http-publish/.jshintrc b/packages/wekan-cfs-http-publish/.jshintrc deleted file mode 100644 index 52d24acf2..000000000 --- a/packages/wekan-cfs-http-publish/.jshintrc +++ /dev/null @@ -1,97 +0,0 @@ -{ - // JSHint Meteor Configuration File - // Match the Meteor Style Guide - // - // By @raix with contributions from @aldeed and @awatson1978 - // Source https://github.com/raix/Meteor-jshintrc - // - // See http://jshint.com/docs/ for more details - - "maxerr": 50, - "bitwise": true, - "camelcase": true, - "curly": true, - "eqeqeq": true, - "forin": true, - "immed": false, - "indent": 2, - "latedef": false, - "newcap": false, - "noarg": true, - "noempty": true, - "nonew": false, - "plusplus": false, - "quotmark": false, - "undef": true, - "unused": true, - "strict": true, - "trailing": true, - "maxparams": false, - "maxdepth": false, - "maxstatements": false, - "maxcomplexity": false, - "maxlen": 80, - "asi": false, - "boss": false, - "debug": false, - "eqnull": false, - "es5": false, - "esnext": false, - "moz": false, - "evil": false, - "expr": false, - "funcscope": false, - "globalstrict": true, - "iterator": false, - "lastsemic": false, - "laxbreak": false, - "laxcomma": false, - "loopfunc": false, - "multistr": false, - "proto": false, - "scripturl": false, - "smarttabs": false, - "shadow": false, - "sub": false, - "supernew": false, - "validthis": false, - "browser": true, - "couch": false, - "devel": true, - "dojo": false, - "jquery": false, - "mootools": false, - "node": false, - "nonstandard": false, - "prototypejs": false, - "rhino": false, - "worker": false, - "wsh": false, - "yui": false, - "nomen": false, - "onevar": false, - "passfail": false, - "white": false, - "predef": [ - "Meteor", - "Accounts", - "Session", - "Template", - "check", - "Match", - "Deps", - "EJSON", - "Email", - "Package", - "Tinytest", - "Npm", - "Assets", - "Packages", - "process", - "LocalCollection", - "_", - "Random", - "HTTP", - "_methodHTTP" - ] -} \ No newline at end of file diff --git a/packages/wekan-cfs-http-publish/.travis.yml b/packages/wekan-cfs-http-publish/.travis.yml deleted file mode 100644 index 6a4640033..000000000 --- a/packages/wekan-cfs-http-publish/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - "0.10" -before_install: - - "curl -L http://git.io/s0Zu-w | /bin/sh" \ No newline at end of file diff --git a/packages/wekan-cfs-http-publish/LICENSE.md b/packages/wekan-cfs-http-publish/LICENSE.md deleted file mode 100644 index 2a5c5339e..000000000 --- a/packages/wekan-cfs-http-publish/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 [@raix](https://github.com/raix), aka Morten N.O. Nørgaard Henriksen, mh@gi-software.com - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/wekan-cfs-http-publish/README.md b/packages/wekan-cfs-http-publish/README.md deleted file mode 100644 index 33ff66c49..000000000 --- a/packages/wekan-cfs-http-publish/README.md +++ /dev/null @@ -1,129 +0,0 @@ -wekan-cfs-http-publish [![Build Status](https://travis-ci.org/CollectionFS/Meteor-http-publish.png?branch=master)](https://travis-ci.org/CollectionFS/Meteor-http-publish) -============ - -This package add the ability to add `HTTP` server publish to your project. It's a server-side package only. - -DEPRECATING: Use https://atmospherejs.com/simple/rest instead - -## Usage -HTTP.publish creates a http crud restpoint for a collection *- only one cursor is allowed pr. publish* - -### Security -`CRUD+L` - Create Read Update Delete + List are common rest point operations. - -All `CUD` methods are the exact same as the `ddp` methods handlers - This means that `Meteor.allow` and `Meteor.deny` are setting the access rules for both `ddp` and `http` collection methods. - -All `R+L` methods are limited to the publish function. - -### Fully mounted -If handed a collection and a publish function the HTTP.publish will mount on follow urls and methods: -* `GET` - `/api/list` *- all published data* -* `POST` - `/api/list` *- insert a document into collection* -* `GET` - `/api/list/:id` *- find one published document* -* `PUT` - `/api/list/:id` *- update a document* -* `DELETE` - `/api/list/:id` *- remove a document* - -```js - myCollection = new Meteor.Collection('list'); - - // Add access points for `GET`, `POST`, `PUT`, `DELETE` - HTTP.publish({collection: myCollection}, function(data) { - // this.userId, this.query, this.params - return myCollection.find({}); - }); -``` - -### Publish view only -If handed a mount name and a publish function the HTTP.publish will mount: -* `GET` - `/mylist` *- all published data* - -```js - myCollection = new Meteor.Collection('list'); - - // Add access points for `GET` - HTTP.publish({name: 'mylist'}, function(data) { - // this.userId, this.query, this.params - return myCollection.find({}); - }); -``` - -### Create Update Delete only -If handed a collection only the HTTP.publish will mount: -* `POST` - `/api/list` *- insert a document into collection* -* `PUT` - `/api/list/:id` *- update a document* -* `DELETE` - `/api/list/:id` *- remove a document* - -```js - myCollection = new Meteor.Collection('list'); - - // Add access points for `POST`, `PUT`, `DELETE` - HTTP.publish({collection: myCollection}); -``` - -## Publish scope -The publish scope contains different kinds of inputs. We can also get user details if logged in. - -* `this.userId` The user whos id and token was used to run this method, if set/found -* `this.query` - query params `?token=1` -> { token: 1 } -* `this.params` - Set params /foo/:name/test/:id -> { name: '', id: '' } - -## Passing data via header -From the client: -```js - HTTP.get('/api/list', { - data: { foo: 'bar' } - }, function(err, result) { - console.log('Content in parsed json: '); - console.log(result.data); - }); -``` - -HTTP Server method: -```js - HTTP.publish({collection: myCollection}, function(data) { - // data === { foo: 'bar' } - }); -``` - -## Authentication -For details on authentication of http calls please read the [Authentication part in HTTP.methods package](https://github.com/raix/Meteor-http-methods#authentication) - -*The publish will have the `this.userId` set if an authenticated user is making the request.* - -## Format handlers -The query parametre `format` is used to set different output formats. The buildin format is `json` *(EJSON since we are on Meteor)* - -Example: *(`json` is buildin)* -```js - // Format the output into json - HTTP.publishFormats({ - 'json': function(result) { - // Set the method scope content type to json - this.setContentType('application/json'); - // Return EJSON string - return EJSON.stringify(result); - } - }); -``` - -`GET` url: `/api/list?format=json` -```js - HTTP.get('/api/list', { - params: { - format: 'json' - } - }, function(err, result) { - console.log('Back from update'); - if (err) { - console.log('Got error'); - } - console.log('Got json back: ' + result.content); - }); -``` - -## Unpublish -For `api` integrity theres added an `HTTP.unpublish` method that takes a collection or name of mount point to remove. - -## API Documentation - -[Here](api.md) diff --git a/packages/wekan-cfs-http-publish/api.md b/packages/wekan-cfs-http-publish/api.md deleted file mode 100644 index b6ca5c8dd..000000000 --- a/packages/wekan-cfs-http-publish/api.md +++ /dev/null @@ -1,153 +0,0 @@ -## http-publish Public API ## - -Adds HTTP.publish and HTTP.unpublish RESTful - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -- - -### _publishHTTP {any}  Server ### - -``` -GET /note -GET /note/:id -POST /note -PUT /note/:id -DELETE /note/:id -``` - -> ```_publishHTTP = { ...``` [http.publish.server.api.js:20](http.publish.server.api.js#L20) - - - -- -Could be cool if we could serve some api doc or even an api script -user could do and be served -a client-side javascript api? -Eg. -HTTP.api.note.create(); -HTTP.api.login(username, password); -HTTP.api.logout -- - -### *http*.publishFormats(newHandlers)  Server ### - -*This method __publishFormats__ is defined in `HTTP`* - -__Arguments__ - -* __newHandlers__ *{Object}* - -__Returns__ *{undefined}* - - -Add publish formats. Example: -```js -HTTP.publishFormats({ -json: function(inputObject) { -// Set the method scope content type to json -this.setContentType('application/json'); -// Return EJSON string -return EJSON.stringify(inputObject); -} -}); -``` - -> ```HTTP.publishFormats = function httpPublishFormats(newHandlers) { ...``` [http.publish.server.api.js:215](http.publish.server.api.js#L215) - - -- - -### *http*.publish(options, [name], [collection], [publishFunc])  Server ### - -*This method __publish__ is defined in `HTTP`* - -__Arguments__ - -* __options__ *{Object}* - * __defaultFormat__ *{String}* (Optional, Default = 'json') - - Format to use for responses when `format` is not found in the query string. - - * __collectionGet__ *{String}* (Optional, Default = true) - - Add GET restpoint for collection? Requires a publish function. - - * __collectionPost__ *{String}* (Optional, Default = true) - - Add POST restpoint for adding documents to the collection? - - * __documentGet__ *{String}* (Optional, Default = true) - - Add GET restpoint for documents in collection? Requires a publish function. - - * __documentPut__ *{String}* (Optional, Default = true) - - Add PUT restpoint for updating a document in the collection? - - * __documentDelete__ *{String}* (Optional, Default = true) - - Add DELETE restpoint for deleting a document in the collection? - -* __name__ *{String}* (Optional) - - Restpoint name (url prefix). Optional if `collection` is passed. Will mount on `/api/collectionName` by default. - -* __collection__ *{[Meteor.Collection](#Meteor.Collection)}* (Optional) - - Meteor.Collection instance. Required for all restpoints except collectionGet - -* __publishFunc__ *{Function}* (Optional) - - A publish function. Required to mount GET restpoints. - - -__Returns__ *{undefined}* - - -Publishes one or more restpoints, mounted on "name" ("/api/collectionName/" -by default). The GET restpoints are subscribed to the document set (cursor) -returned by the publish function you supply. The other restpoints forward -requests to Meteor's built-in DDP methods (insert, update, remove), meaning -that full allow/deny security is automatic. - -__Usage:__ - -Publish only: - -HTTP.publish({name: 'mypublish'}, publishFunc); - -Publish and mount crud rest point for collection /api/myCollection: - -HTTP.publish({collection: myCollection}, publishFunc); - -Mount CUD rest point for collection and documents without GET: - -HTTP.publish({collection: myCollection}); - - -> ```HTTP.publish = function httpPublish(options, publishFunc) { ...``` [http.publish.server.api.js:256](http.publish.server.api.js#L256) - - -- - -### *http*.unpublish([name])  Server ### - -*This method __unpublish__ is defined in `HTTP`* - -__Arguments__ - -* __name__ *{String|[Meteor.Collection](#Meteor.Collection)}* (Optional) - - The method name or collection - - -__Returns__ *{undefined}* - - -Unpublishes all HTTP methods that were published with the given name or -for the given collection. Call with no arguments to unpublish all. - -> ```HTTP.unpublish = _publishHTTP.unpublish;``` [http.publish.server.api.js:453](http.publish.server.api.js#L453) - - diff --git a/packages/wekan-cfs-http-publish/http.publish.client.api.js b/packages/wekan-cfs-http-publish/http.publish.client.api.js deleted file mode 100644 index 62339351c..000000000 --- a/packages/wekan-cfs-http-publish/http.publish.client.api.js +++ /dev/null @@ -1,12 +0,0 @@ -// Client-side is not implemented -HTTP.publish = function() { - throw new Error('HTTP.publish not implemented on client-side'); -}; - -HTTP.publishFormats = function() { - throw new Error('HTTP.publishFormats not implemented on client-side'); -}; - -HTTP.unpublish = function() { - throw new Error('HTTP.unpublish not implemented on client-side'); -}; diff --git a/packages/wekan-cfs-http-publish/http.publish.server.api.js b/packages/wekan-cfs-http-publish/http.publish.server.api.js deleted file mode 100644 index 6fcc44854..000000000 --- a/packages/wekan-cfs-http-publish/http.publish.server.api.js +++ /dev/null @@ -1,466 +0,0 @@ -/* - -GET /note -GET /note/:id -POST /note -PUT /note/:id -DELETE /note/:id - -*/ - -// Could be cool if we could serve some api doc or even an api script -// user could do and be served -// a client-side javascript api? -// Eg. -// HTTP.api.note.create(); -// HTTP.api.login(username, password); -// HTTP.api.logout - - -_publishHTTP = {}; - -// Cache the names of all http methods we've published -_publishHTTP.currentlyPublished = []; - -var defaultAPIPrefix = '/api/'; - -/** - * @method _publishHTTP.getPublishScope - * @private - * @param {Object} scope - * @returns {httpPublishGetPublishScope.publishScope} - * - * Creates a nice scope for the publish method - */ -_publishHTTP.getPublishScope = function httpPublishGetPublishScope(scope) { - var publishScope = {}; - publishScope.userId = scope.userId; - publishScope.params = scope.params; - publishScope.query = scope.query; - // TODO: Additional scoping - // publishScope.added - // publishScope.ready - return publishScope; -}; - -_publishHTTP.formatHandlers = {}; - -/** - * @method _publishHTTP.formatHandlers.json - * @private - * @param {Object} result - The result object - * @returns {String} JSON - * - * Formats the output into JSON and sets the appropriate content type on `this` - */ -_publishHTTP.formatHandlers.json = function httpPublishJSONFormatHandler(result) { - // Set the method scope content type to json - this.setContentType('application/json'); - // Return EJSON string - return EJSON.stringify(result); -}; - -/** - * @method _publishHTTP.formatResult - * @private - * @param {Object} result - The result object - * @param {Object} scope - * @param {String} [defaultFormat='json'] - Default format to use if format is not in query string. - * @returns {Any} The formatted result - * - * Formats the result into the format selected by querystring eg. "&format=json" - */ -_publishHTTP.formatResult = function httpPublishFormatResult(result, scope, defaultFormat) { - - // Get the format in lower case and default to json - var format = scope && scope.query && scope.query.format || defaultFormat || 'json'; - - // Set the format handler found - var formatHandlerFound = !!(typeof _publishHTTP.formatHandlers[format] === 'function'); - - // Set the format handler and fallback to default json if handler not found - var formatHandler = _publishHTTP.formatHandlers[(formatHandlerFound) ? format : 'json']; - - // Check if format handler is a function - if (typeof formatHandler !== 'function') { - // We break things the user could have overwritten the default json handler - throw new Error('The default json format handler not found'); - } - - if (!formatHandlerFound) { - scope.setStatusCode(500); - return '{"error":"Format handler for: `' + format + '` not found"}'; - } - - // Execute the format handler - try { - return formatHandler.apply(scope, [result]); - } catch(err) { - scope.setStatusCode(500); - return '{"error":"Format handler for: `' + format + '` Error: ' + err.message + '"}'; - } -}; - -/** - * @method _publishHTTP.error - * @private - * @param {String} statusCode - The status code - * @param {String} message - The message - * @param {Object} scope - * @returns {Any} The formatted result - * - * Responds with error message in the expected format - */ -_publishHTTP.error = function httpPublishError(statusCode, message, scope) { - var result = _publishHTTP.formatResult(message, scope); - scope.setStatusCode(statusCode); - return result; -}; - -/** - * @method _publishHTTP.getMethodHandler - * @private - * @param {Meteor.Collection} collection - The Meteor.Collection instance - * @param {String} methodName - The method name - * @returns {Function} The server method - * - * Returns the DDP connection handler, already setup and secured - */ -_publishHTTP.getMethodHandler = function httpPublishGetMethodHandler(collection, methodName) { - if (collection instanceof Meteor.Collection) { - if (collection._connection && collection._connection.method_handlers) { - return collection._connection.method_handlers[collection._prefix + methodName]; - } else { - throw new Error('HTTP publish does not work with current version of Meteor'); - } - } else { - throw new Error('_publishHTTP.getMethodHandler expected a collection'); - } -}; - -/** - * @method _publishHTTP.unpublishList - * @private - * @param {Array} names - List of method names to unpublish - * @returns {undefined} - * - * Unpublishes all HTTP methods that have names matching the given list. - */ -_publishHTTP.unpublishList = function httpPublishUnpublishList(names) { - if (!names.length) { - return; - } - - // Carry object for methods - var methods = {}; - - // Unpublish the rest points by setting them to false - for (var i = 0, ln = names.length; i < ln; i++) { - methods[names[i]] = false; - } - - HTTP.methods(methods); - - // Remove the names from our list of currently published methods - _publishHTTP.currentlyPublished = _.difference(_publishHTTP.currentlyPublished, names); -}; - -/** - * @method _publishHTTP.unpublish - * @private - * @param {String|Meteor.Collection} [name] - The method name or collection - * @returns {undefined} - * - * Unpublishes all HTTP methods that were published with the given name or - * for the given collection. Call with no arguments to unpublish all. - */ -_publishHTTP.unpublish = function httpPublishUnpublish(/* name or collection, options */) { - - // Determine what method name we're unpublishing - var name = (arguments[0] instanceof Meteor.Collection) ? - defaultAPIPrefix + arguments[0]._name : arguments[0]; - - // Unpublish name and name/id - if (name && name.length) { - _publishHTTP.unpublishList([name, name + '/:id']); - } - - // If no args, unpublish all - else { - _publishHTTP.unpublishList(_publishHTTP.currentlyPublished); - } - -}; - -/** - * @method HTTP.publishFormats - * @public - * @param {Object} newHandlers - * @returns {undefined} - * - * Add publish formats. Example: - ```js - HTTP.publishFormats({ - - json: function(inputObject) { - // Set the method scope content type to json - this.setContentType('application/json'); - // Return EJSON string - return EJSON.stringify(inputObject); - } - - }); - ``` - */ -HTTP.publishFormats = function httpPublishFormats(newHandlers) { - _.extend(_publishHTTP.formatHandlers, newHandlers); -}; - -/** - * @method HTTP.publish - * @public - * @param {Object} options - * @param {String} [name] - Restpoint name (url prefix). Optional if `collection` is passed. Will mount on `/api/collectionName` by default. - * @param {Meteor.Collection} [collection] - Meteor.Collection instance. Required for all restpoints except collectionGet - * @param {String} [options.defaultFormat='json'] - Format to use for responses when `format` is not found in the query string. - * @param {String} [options.collectionGet=true] - Add GET restpoint for collection? Requires a publish function. - * @param {String} [options.collectionPost=true] - Add POST restpoint for adding documents to the collection? - * @param {String} [options.documentGet=true] - Add GET restpoint for documents in collection? Requires a publish function. - * @param {String} [options.documentPut=true] - Add PUT restpoint for updating a document in the collection? - * @param {String} [options.documentDelete=true] - Add DELETE restpoint for deleting a document in the collection? - * @param {Function} [publishFunc] - A publish function. Required to mount GET restpoints. - * @returns {undefined} - * @todo this should use options argument instead of optional args - * - * Publishes one or more restpoints, mounted on "name" ("/api/collectionName/" - * by default). The GET restpoints are subscribed to the document set (cursor) - * returned by the publish function you supply. The other restpoints forward - * requests to Meteor's built-in DDP methods (insert, update, remove), meaning - * that full allow/deny security is automatic. - * - * __Usage:__ - * - * Publish only: - * - * HTTP.publish({name: 'mypublish'}, publishFunc); - * - * Publish and mount crud rest point for collection /api/myCollection: - * - * HTTP.publish({collection: myCollection}, publishFunc); - * - * Mount CUD rest point for collection and documents without GET: - * - * HTTP.publish({collection: myCollection}); - * - */ -HTTP.publish = function httpPublish(options, publishFunc) { - options = _.extend({ - name: null, - auth: null, - collection: null, - defaultFormat: null, - collectionGet: true, - collectionPost: true, - documentGet: true, - documentPut: true, - documentDelete: true - }, options || {}); - - var collection = options.collection; - - // Use provided name or build one - var name = (typeof options.name === "string") ? options.name : defaultAPIPrefix + collection._name; - - // Make sure we have a name - if (typeof name !== "string") { - throw new Error('HTTP.publish expected a collection or name option'); - } - - var defaultFormat = options.defaultFormat; - - // Rig the methods for the CRUD interface - var methods = {}; - - // console.log('HTTP restpoint: ' + name); - - // list and create - methods[name] = {}; - - if (options.collectionGet && publishFunc) { - // Return the published documents - methods[name].get = function(data) { - // Format the scope for the publish method - var publishScope = _publishHTTP.getPublishScope(this); - // Get the publish cursor - var cursor = publishFunc.apply(publishScope, [data]); - - // Check if its a cursor - if (cursor && cursor.fetch) { - // Fetch the data fron cursor - var result = cursor.fetch(); - // Return the data - return _publishHTTP.formatResult(result, this, defaultFormat); - } else { - // We didnt get any - return _publishHTTP.error(200, [], this); - } - }; - } - - if (collection) { - // If we have a collection then add insert method - if (options.collectionPost) { - methods[name].post = function(data) { - var insertMethodHandler = _publishHTTP.getMethodHandler(collection, 'insert'); - // Make sure that _id isset else create a Meteor id - data._id = data._id || Random.id(); - // Create the document - try { - // We should be passed a document in data - insertMethodHandler.apply(this, [data]); - // Return the data - return _publishHTTP.formatResult({ _id: data._id }, this, defaultFormat); - } catch(err) { - // This would be a Meteor.error? - return _publishHTTP.error(err.error, { error: err.message }, this); - } - }; - } - - // We also add the findOne, update and remove methods - methods[name + '/:id'] = {}; - - if (options.documentGet && publishFunc) { - // We have to have a publish method inorder to publish id? The user could - // just write a publish all if needed - better to make this explicit - methods[name + '/:id'].get = function(data) { - // Get the mongoId - var mongoId = this.params.id; - - // We would allways expect a string but it could be empty - if (mongoId !== '') { - - // Format the scope for the publish method - var publishScope = _publishHTTP.getPublishScope(this); - - // Get the publish cursor - var cursor = publishFunc.apply(publishScope, [data]); - - // Result will contain the document if found - var result; - - // Check to see if document is in published cursor - if (cursor) { - cursor.forEach(function(doc) { - if (!result) { - if (doc._id === mongoId) { - result = doc; - } - } - }); - } - - // If the document is found the return - if (result) { - return _publishHTTP.formatResult(result, this, defaultFormat); - } else { - // We do a check to see if the doc id exists - var exists = collection.findOne({ _id: mongoId }); - // If it exists its not published to the user - if (exists) { - // Unauthorized - return _publishHTTP.error(401, { error: 'Unauthorized' }, this); - } else { - // Not found - return _publishHTTP.error(404, { error: 'Document with id ' + mongoId + ' not found' }, this); - } - } - - } else { - return _publishHTTP.error(400, { error: 'Method expected a document id' }, this); - } - }; - } - - if (options.documentPut) { - methods[name + '/:id'].put = function(data) { - // Get the mongoId - var mongoId = this.params.id; - - // We would allways expect a string but it could be empty - if (mongoId !== '') { - - var updateMethodHandler = _publishHTTP.getMethodHandler(collection, 'update'); - // Create the document - try { - // We should be passed a document in data - updateMethodHandler.apply(this, [{ _id: mongoId }, data]); - // Return the data - return _publishHTTP.formatResult({ _id: mongoId }, this, defaultFormat); - } catch(err) { - // This would be a Meteor.error? - return _publishHTTP.error(err.error, { error: err.message }, this); - } - - } else { - return _publishHTTP.error(400, { error: 'Method expected a document id' }, this); - } - }; - } - - if (options.documentDelete) { - methods[name + '/:id'].delete = function(data) { - // Get the mongoId - var mongoId = this.params.id; - - // We would allways expect a string but it could be empty - if (mongoId !== '') { - - var removeMethodHandler = _publishHTTP.getMethodHandler(collection, 'remove'); - // Create the document - try { - // We should be passed a document in data - removeMethodHandler.apply(this, [{ _id: mongoId }]); - // Return the data - return _publishHTTP.formatResult({ _id: mongoId }, this, defaultFormat); - } catch(err) { - // This would be a Meteor.error? - return _publishHTTP.error(err.error, { error: err.message }, this); - } - - } else { - return _publishHTTP.error(400, { error: 'Method expected a document id' }, this); - } - }; - } - - } - - // Authenticate with our own auth method: https://github.com/zcfs/Meteor-http-methods#authentication - if (options.auth) { - if (methods[name]) { - methods[name].auth = options.auth; - } - if (methods[name + '/:id']) { - methods[name + '/:id'].auth = options.auth; - } - } - - // Publish the methods - HTTP.methods(methods); - - // Mark these method names as currently published - _publishHTTP.currentlyPublished = _.union(_publishHTTP.currentlyPublished, _.keys(methods)); - -}; // EO Publish - -/** - * @method HTTP.unpublish - * @public - * @param {String|Meteor.Collection} [name] - The method name or collection - * @returns {undefined} - * - * Unpublishes all HTTP methods that were published with the given name or - * for the given collection. Call with no arguments to unpublish all. - */ -HTTP.unpublish = _publishHTTP.unpublish; \ No newline at end of file diff --git a/packages/wekan-cfs-http-publish/http.publish.tests.client.js b/packages/wekan-cfs-http-publish/http.publish.tests.client.js deleted file mode 100644 index 185abea23..000000000 --- a/packages/wekan-cfs-http-publish/http.publish.tests.client.js +++ /dev/null @@ -1,175 +0,0 @@ -function equals(a, b) { - return !!(EJSON.stringify(a) === EJSON.stringify(b)); -} - -list = new Meteor.Collection('list'); -console.log('Client url: ' + Meteor.absoluteUrl('api')); - -Tinytest.add('http-publish - client - test environment', function(test) { - test.isTrue(typeof _publishHTTP === 'undefined', 'test environment not initialized _publishHTTP'); - test.isTrue(typeof HTTP !== 'undefined', 'test environment not initialized HTTP'); - test.isTrue(typeof HTTP.publish !== 'undefined', 'test environment not initialized HTTP.publish'); - test.isTrue(typeof HTTP.unpublish !== 'undefined', 'test environment not initialized HTTP.unpublish'); - test.isTrue(typeof HTTP.publishFormats !== 'undefined', 'test environment not initialized HTTP.publishFormats'); -}); - -Tinytest.addAsync('http-publish - client - clearTest', function (test, onComplete) { - test.isTrue(true); - Meteor.call('clearTest', function(err, result) { - test.isTrue(result); - onComplete(); - }); - test.isTrue(true); -}); - -id = ''; -removedId = ''; - -Tinytest.addAsync('http-publish - client - get list', function (test, onComplete) { - - HTTP.get(Meteor.absoluteUrl('api/list'), function(err, result) { - // Test the length of array result - var len = result.data && result.data.length; - test.isTrue(!!len, 'Result was empty'); - // Get the object - var obj = result.data && result.data[0] || {}; - test.equal(obj.text, 'OK', 'Didnt get the expected result'); - // Set the id for the next test - id = obj._id; - onComplete(); - }); - -}); - -Tinytest.addAsync('http-publish - client - get list from custom prefix', function (test, onComplete) { - - // Now test the one we added with a custom prefix - HTTP.get(Meteor.absoluteUrl('api2/list'), function(err, result) { - // Test the length of array result - var len = result.data && result.data.length; - test.isTrue(!!len, 'Result was empty'); - // Get the object - var obj = result.data && result.data[0] || {}; - test.equal(obj.text, 'OK', 'Didnt get the expected result'); - onComplete(); - }); - -}); - -Tinytest.addAsync('http-publish - client - unmountCustom', function (test, onComplete) { - // Now unmount the methods with custom prefix - test.isTrue(true); - Meteor.call('unmountCustom', function(err, result) { - test.isTrue(result); - onComplete(); - }); - test.isTrue(true); -}); - -Tinytest.addAsync('http-publish - client - custom unmounted', function (test, onComplete) { - - // Now test the one we added with a custom prefix - HTTP.get(Meteor.absoluteUrl('api2/list'), function(err, result) { - test.isTrue(!!err, "Should have received an error since we unmounted the custom rest points"); - onComplete(); - }); - -}); - -Tinytest.addAsync('http-publish - client - put list', function (test, onComplete) { - - test.isTrue(id !== '', 'No id is set?'); - - // Update the data - HTTP.put(Meteor.absoluteUrl('api/list/' + id), { - data: { - $set: { text: 'UPDATED' } - } - }, function(err, result) { - var resultId = result.data && result.data._id; - test.isTrue(resultId !== undefined, 'Didnt get the expected id in result'); - - // Check if data is updated - HTTP.get(Meteor.absoluteUrl('api/list'), function(err, result) { - var len = result.data && result.data.length; - test.isTrue(!!len, 'Result was empty'); - var obj = result.data && result.data[0] || {}; - test.equal(obj.text, 'UPDATED', 'Didnt get the expected result'); - onComplete(); - }); - }); - -}); - -Tinytest.addAsync('http-publish - client - insert/remove list', function (test, onComplete) { - - // Insert a doc - HTTP.post(Meteor.absoluteUrl('api/list'), { - data: { - text: 'INSERTED' - } - }, function(err, result) { - var resultId = result.data && result.data._id; - test.isTrue(resultId !== undefined, 'Didnt get the expected id in result'); - // Delete the doc - HTTP.del(Meteor.absoluteUrl('api/list/' + resultId), function(err, result) { - removedId = result.data && result.data._id; - test.isTrue(removedId !== undefined, 'Didnt get the expected id in result'); - onComplete(); - }); - }); - -}); - -Tinytest.addAsync('http-publish - client - check removed', function (test, onComplete) { - - test.isTrue(removedId !== '', 'No removedId is set?'); - - HTTP.get(Meteor.absoluteUrl('api/list/' + removedId), function(err, result) { - var obj = result.data || {}; - test.isTrue(obj._id === undefined, 'Item was not removed'); - test.isTrue(err.response.statusCode === 404, 'Item was not removed'); - onComplete(); - }); - -}); - -Tinytest.addAsync('http-publish - client - check findOne', function (test, onComplete) { - - test.isTrue(id !== '', 'No id is set?'); - - HTTP.get(Meteor.absoluteUrl('api/list/' + id), function(err, result) { - var obj = result.data || {}; - test.isTrue(obj._id !== undefined, 'expected a document'); - test.isTrue(obj.text === 'UPDATED', 'expected text === UPDATED'); - - onComplete(); - }); - -}); - - - // Check if removedId found - - // Check if id still found - - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-http-publish/http.publish.tests.server.js b/packages/wekan-cfs-http-publish/http.publish.tests.server.js deleted file mode 100644 index 94ca58a87..000000000 --- a/packages/wekan-cfs-http-publish/http.publish.tests.server.js +++ /dev/null @@ -1,149 +0,0 @@ -function equals(a, b) { - return !!(EJSON.stringify(a) === EJSON.stringify(b)); -} - -Tinytest.add('http-publish - server - test environment', function(test) { - test.isTrue(typeof _publishHTTP !== 'undefined', 'test environment not initialized _publishHTTP'); - test.isTrue(typeof HTTP !== 'undefined', 'test environment not initialized HTTP'); - test.isTrue(typeof HTTP.publish !== 'undefined', 'test environment not initialized HTTP.publish'); - test.isTrue(typeof HTTP.unpublish !== 'undefined', 'test environment not initialized HTTP.unpublish'); - test.isTrue(typeof HTTP.publishFormats !== 'undefined', 'test environment not initialized HTTP.publishFormats'); - -}); - -list = new Meteor.Collection('list'); -console.log('Server url: ' + Meteor.absoluteUrl()); - -list.allow({ - insert: function() { return true; }, - update: function() { return true; }, - remove: function() { return true; } -}); - -console.log('Rig publish'); -HTTP.publish({collection: list}, function() { - return list.find(); -}); - -// Test custom prefix, too -HTTP.publish({collection: list, name: '/api2/list'}, function() { - return list.find(); -}); - -Meteor.methods({ - clearTest: function() { - console.log('Client called clearTest'); - // Empty test db - list.remove({}); - - // Insert one text - list.insert({ text: 'OK' }); - - // Count - var count = list.find().count(); - - return !!(count === 1); - }, - unmountCustom: function() { - console.log('Client called unmountCustom'); - _publishHTTP.unpublish('/api2/list'); - return true; - } -}); - - -Tinytest.add('http-publish - server - getMethodHandler', function(test) { - - try { - var methodHandler = _publishHTTP.getMethodHandler(list, 'insert'); - - test.isTrue(typeof methodHandler === 'function', 'expected getMethodHandler to return a function'); - - } catch(err) { - test.fail(err.message); - } - -}); - - -Tinytest.add('http-publish - server - formatHandlers', function(test) { - - test.isTrue(typeof _publishHTTP.formatHandlers.json === 'function', 'Cant find formatHandler for json'); - - var testScope = { - code: 0, - setContentType: function(code) { - this.code = code; - } - }; - var resultFormatHandler = _publishHTTP.formatHandlers.json.apply(testScope, [{test:'ok'}]); - - test.equal(testScope.code, 'application/json', 'json formatHandler have not set setContentType'); - - test.equal(resultFormatHandler, '{"test":"ok"}', 'json formatHandler returned a bad result'); - -}); - -Tinytest.add('http-publish - server - getPublishScope', function(test) { - - var oldScope = { - userId: '1', - params: '2', - query: '3', - oldStuff: 'hmmm' - }; - - var newScope = _publishHTTP.getPublishScope(oldScope); - - test.isUndefined(newScope.oldStuff, 'This oldStuff should not be in the new scope'); - - test.equal(newScope.userId, '1', 'userId not set in the new scope'); - test.equal(newScope.params, '2', 'params not set in the new scope'); - test.equal(newScope.query, '3', 'query not set in the new scope'); - -}); - -Tinytest.add('http-publish - server - formatResult', function(test) { - - var oldScope = { - statusCode: 200, - userId: '1', - params: '2', - query: '3', - oldStuff: 'hmmm', - setStatusCode: function(code) { - this.statusCode = code; - }, - code: 0, - setContentType: function(code) { - this.code = code; - } - }; - - var result = _publishHTTP.formatResult({test: 'ok'}, oldScope); - - test.equal(oldScope.code, 'application/json', 'json formatHandler have not set setContentType'); - - test.equal(result, '{"test":"ok"}', 'json formatHandler returned a bad result'); - -}); - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-http-publish/internal.api.md b/packages/wekan-cfs-http-publish/internal.api.md deleted file mode 100644 index ce31a3e53..000000000 --- a/packages/wekan-cfs-http-publish/internal.api.md +++ /dev/null @@ -1,330 +0,0 @@ -## Public and Private API ## - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -*** - -__File: ["http.publish.server.api.js"](http.publish.server.api.js) Where: {server}__ - -*** - -### _publishHTTP {any}  Server ### - -``` -GET /note -GET /note/:id -POST /note -PUT /note/:id -DELETE /note/:id -``` - -> ```_publishHTTP = { ...``` [http.publish.server.api.js:20](http.publish.server.api.js#L20) - - - -- -Could be cool if we could serve some api doc or even an api script -user could do and be served -a client-side javascript api? -Eg. -HTTP.api.note.create(); -HTTP.api.login(username, password); -HTTP.api.logout -- - -### *_publishhttp*.getPublishScope(scope)  Server ### - -*This method is private* -*This method __getPublishScope__ is defined in `_publishHTTP`* - -__Arguments__ - -* __scope__ *{Object}* - -__Returns__ *{httpPublishGetPublishScope.publishScope}* - - -Creates a nice scope for the publish method - -> ```_publishHTTP.getPublishScope = function httpPublishGetPublishScope(scope) { ...``` [http.publish.server.api.js:35](http.publish.server.api.js#L35) - - -- - -### *_publishhttpformathandlers*.json(result)  Server ### - -*This method is private* -*This method __json__ is defined in `_publishHTTP.formatHandlers`* - -__Arguments__ - -* __result__ *{Object}* - - The result object - - -__Returns__ *{String}* -JSON - - -Formats the output into JSON and sets the appropriate content type on `this` - -> ```_publishHTTP.formatHandlers.json = function httpPublishJSONFormatHandler(result) { ...``` [http.publish.server.api.js:56](http.publish.server.api.js#L56) - - -- - -### *_publishhttp*.formatResult(result, scope, [defaultFormat])  Server ### - -*This method is private* -*This method __formatResult__ is defined in `_publishHTTP`* - -__Arguments__ - -* __result__ *{Object}* - - The result object - -* __scope__ *{Object}* -* __defaultFormat__ *{String}* (Optional, Default = 'json') - - Default format to use if format is not in query string. - - -__Returns__ *{Any}* -The formatted result - - -Formats the result into the format selected by querystring eg. "&format=json" - -> ```_publishHTTP.formatResult = function httpPublishFormatResult(result, scope, defaultFormat) { ...``` [http.publish.server.api.js:73](http.publish.server.api.js#L73) - - -- - -### *_publishhttp*.error(statusCode, message, scope)  Server ### - -*This method is private* -*This method __error__ is defined in `_publishHTTP`* - -__Arguments__ - -* __statusCode__ *{String}* - - The status code - -* __message__ *{String}* - - The message - -* __scope__ *{Object}* - -__Returns__ *{Any}* -The formatted result - - -Responds with error message in the expected format - -> ```_publishHTTP.error = function httpPublishError(statusCode, message, scope) { ...``` [http.publish.server.api.js:114](http.publish.server.api.js#L114) - - -- - -### *_publishhttp*.getMethodHandler(collection, methodName)  Server ### - -*This method is private* -*This method __getMethodHandler__ is defined in `_publishHTTP`* - -__Arguments__ - -* __collection__ *{[Meteor.Collection](#Meteor.Collection)}* - - The Meteor.Collection instance - -* __methodName__ *{String}* - - The method name - - -__Returns__ *{Function}* -The server method - - -Returns the DDP connection handler, already setup and secured - -> ```_publishHTTP.getMethodHandler = function httpPublishGetMethodHandler(collection, methodName) { ...``` [http.publish.server.api.js:129](http.publish.server.api.js#L129) - - -- - -### *_publishhttp*.unpublishList(names)  Server ### - -*This method is private* -*This method __unpublishList__ is defined in `_publishHTTP`* - -__Arguments__ - -* __names__ *{Array}* - - List of method names to unpublish - - -__Returns__ *{undefined}* - - -Unpublishes all HTTP methods that have names matching the given list. - -> ```_publishHTTP.unpublishList = function httpPublishUnpublishList(names) { ...``` [http.publish.server.api.js:149](http.publish.server.api.js#L149) - - -- - -### *_publishhttp*.unpublish([name])  Server ### - -*This method is private* -*This method __unpublish__ is defined in `_publishHTTP`* - -__Arguments__ - -* __name__ *{String|[Meteor.Collection](#Meteor.Collection)}* (Optional) - - The method name or collection - - -__Returns__ *{undefined}* - - -Unpublishes all HTTP methods that were published with the given name or -for the given collection. Call with no arguments to unpublish all. - -> ```_publishHTTP.unpublish = function httpPublishUnpublish(``` [http.publish.server.api.js:177](http.publish.server.api.js#L177) - - -- - -### *http*.publishFormats(newHandlers)  Server ### - -*This method __publishFormats__ is defined in `HTTP`* - -__Arguments__ - -* __newHandlers__ *{Object}* - -__Returns__ *{undefined}* - - -Add publish formats. Example: -```js -HTTP.publishFormats({ -json: function(inputObject) { -// Set the method scope content type to json -this.setContentType('application/json'); -// Return EJSON string -return EJSON.stringify(inputObject); -} -}); -``` - -> ```HTTP.publishFormats = function httpPublishFormats(newHandlers) { ...``` [http.publish.server.api.js:215](http.publish.server.api.js#L215) - - -- - -### *http*.publish(options, [name], [collection], [publishFunc])  Server ### - -*This method __publish__ is defined in `HTTP`* - -__Arguments__ - -* __options__ *{Object}* - * __defaultFormat__ *{String}* (Optional, Default = 'json') - - Format to use for responses when `format` is not found in the query string. - - * __collectionGet__ *{String}* (Optional, Default = true) - - Add GET restpoint for collection? Requires a publish function. - - * __collectionPost__ *{String}* (Optional, Default = true) - - Add POST restpoint for adding documents to the collection? - - * __documentGet__ *{String}* (Optional, Default = true) - - Add GET restpoint for documents in collection? Requires a publish function. - - * __documentPut__ *{String}* (Optional, Default = true) - - Add PUT restpoint for updating a document in the collection? - - * __documentDelete__ *{String}* (Optional, Default = true) - - Add DELETE restpoint for deleting a document in the collection? - -* __name__ *{String}* (Optional) - - Restpoint name (url prefix). Optional if `collection` is passed. Will mount on `/api/collectionName` by default. - -* __collection__ *{[Meteor.Collection](#Meteor.Collection)}* (Optional) - - Meteor.Collection instance. Required for all restpoints except collectionGet - -* __publishFunc__ *{Function}* (Optional) - - A publish function. Required to mount GET restpoints. - - -__Returns__ *{undefined}* - -__TODO__ -``` -* this should use options argument instead of optional args -``` - - -Publishes one or more restpoints, mounted on "name" ("/api/collectionName/" -by default). The GET restpoints are subscribed to the document set (cursor) -returned by the publish function you supply. The other restpoints forward -requests to Meteor's built-in DDP methods (insert, update, remove), meaning -that full allow/deny security is automatic. - -__Usage:__ - -Publish only: - -HTTP.publish({name: 'mypublish'}, publishFunc); - -Publish and mount crud rest point for collection /api/myCollection: - -HTTP.publish({collection: myCollection}, publishFunc); - -Mount CUD rest point for collection and documents without GET: - -HTTP.publish({collection: myCollection}); - - -> ```HTTP.publish = function httpPublish(options, publishFunc) { ...``` [http.publish.server.api.js:256](http.publish.server.api.js#L256) - - -- - -### *http*.unpublish([name])  Server ### - -*This method __unpublish__ is defined in `HTTP`* - -__Arguments__ - -* __name__ *{String|[Meteor.Collection](#Meteor.Collection)}* (Optional) - - The method name or collection - - -__Returns__ *{undefined}* - - -Unpublishes all HTTP methods that were published with the given name or -for the given collection. Call with no arguments to unpublish all. - -> ```HTTP.unpublish = _publishHTTP.unpublish;``` [http.publish.server.api.js:453](http.publish.server.api.js#L453) - - diff --git a/packages/wekan-cfs-http-publish/package.js b/packages/wekan-cfs-http-publish/package.js deleted file mode 100644 index 7a16373cc..000000000 --- a/packages/wekan-cfs-http-publish/package.js +++ /dev/null @@ -1,34 +0,0 @@ -Package.describe({ - git: 'https://github.com/zcfs/Meteor-http-publish.git', - name: 'wekan-cfs-http-publish', - version: '0.0.13', - summary: 'Adds HTTP.publish and HTTP.unpublish RESTful' -}); - -Package.onUse(function(api) { - api.versionsFrom('1.0'); - - api.use(['webapp', 'underscore', 'ejson', 'random'], 'server'); - - api.use('wekan-cfs-http-methods@0.0.27'); - - api.imply && api.imply('wekan-cfs-http-methods'); - - api.export && api.export('_publishHTTP', { testOnly: true }); - - api.addFiles('http.publish.client.api.js', 'client'); - api.addFiles('http.publish.server.api.js', 'server'); - -}); - -Package.onTest(function (api) { - api.use('wekan-cfs-http-publish', ['client', 'server']); - api.use('test-helpers', ['client', 'server']); - api.use('http', 'client'); - - api.use(['tinytest', 'underscore', 'ejson', 'ordered-dict', - 'random', 'deps']); - - api.addFiles('http.publish.tests.server.js', 'server'); - api.addFiles('http.publish.tests.client.js', 'client'); -}); diff --git a/packages/wekan-cfs-http-publish/packages/.gitignore b/packages/wekan-cfs-http-publish/packages/.gitignore deleted file mode 100644 index 3683f43ae..000000000 --- a/packages/wekan-cfs-http-publish/packages/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/http-publish -/http-methods diff --git a/packages/wekan-cfs-power-queue/.editorconfig b/packages/wekan-cfs-power-queue/.editorconfig deleted file mode 100644 index a2cc1c1fe..000000000 --- a/packages/wekan-cfs-power-queue/.editorconfig +++ /dev/null @@ -1,18 +0,0 @@ -# .editorconfig -# Meteor adapted EditorConfig, http://EditorConfig.org -# By RaiX 2013 - -root = true - -[*.js] -end_of_line = lf -insert_final_newline = true -indent_style = space -indent_size = 2 -trim_trailing_whitespace = true -charset = utf-8 -max_line_length = 80 -indent_brace_style = 1TBS -spaces_around_operators = true -quote_type = auto -# curly_bracket_next_line = true \ No newline at end of file diff --git a/packages/wekan-cfs-power-queue/.gitignore b/packages/wekan-cfs-power-queue/.gitignore deleted file mode 100644 index dc163f991..000000000 --- a/packages/wekan-cfs-power-queue/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/versions.json -/nbproject/private/ -.build* diff --git a/packages/wekan-cfs-power-queue/.jshintrc b/packages/wekan-cfs-power-queue/.jshintrc deleted file mode 100644 index 2bc2606c4..000000000 --- a/packages/wekan-cfs-power-queue/.jshintrc +++ /dev/null @@ -1,114 +0,0 @@ -//.jshintrc -{ - // JSHint Meteor Configuration File - // Match the Meteor Style Guide - // - // By @raix with contributions from @aldeed and @awatson1978 - // Source https://github.com/raix/Meteor-jshintrc - // - // See http://jshint.com/docs/ for more details - - "maxerr" : 50, // {int} Maximum error before stopping - - // Enforcing - "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.) - "camelcase" : true, // true: Identifiers must be in camelCase - "curly" : true, // true: Require {} for every new block or scope - "eqeqeq" : true, // true: Require triple equals (===) for comparison - "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty() - "immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());` - "indent" : 2, // {int} Number of spaces to use for indentation - "latedef" : false, // true: Require variables/functions to be defined before being used - "newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()` - "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee` - "noempty" : true, // true: Prohibit use of empty blocks - "nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment) - "plusplus" : false, // true: Prohibit use of `++` & `--` - "quotmark" : false, // Quotation mark consistency: - // false : do nothing (default) - // true : ensure whatever is used is consistent - // "single" : require single quotes - // "double" : require double quotes - "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks) - "unused" : true, // true: Require all defined variables be used - "strict" : true, // true: Requires all functions run in ES5 Strict Mode - "trailing" : true, // true: Prohibit trailing whitespaces - "maxparams" : false, // {int} Max number of formal params allowed per function - "maxdepth" : false, // {int} Max depth of nested blocks (within functions) - "maxstatements" : false, // {int} Max number statements per function - "maxcomplexity" : false, // {int} Max cyclomatic complexity per function - "maxlen" : 80, // {int} Max number of characters per line - - // Relaxing - "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons) - "boss" : false, // true: Tolerate assignments where comparisons would be expected - "debug" : false, // true: Allow debugger statements e.g. browser breakpoints. - "eqnull" : false, // true: Tolerate use of `== null` - "es5" : false, // true: Allow ES5 syntax (ex: getters and setters) - "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`) - "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features) - // (ex: `for each`, multiple try/catch, function expression…) - "evil" : false, // true: Tolerate use of `eval` and `new Function()` - "expr" : false, // true: Tolerate `ExpressionStatement` as Programs - "funcscope" : false, // true: Tolerate defining variables inside control statements" - "globalstrict" : true, // true: Allow global "use strict" (also enables 'strict') - "iterator" : false, // true: Tolerate using the `__iterator__` property - "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block - "laxbreak" : false, // true: Tolerate possibly unsafe line breakings - "laxcomma" : false, // true: Tolerate comma-first style coding - "loopfunc" : false, // true: Tolerate functions being defined in loops - "multistr" : false, // true: Tolerate multi-line strings - "proto" : false, // true: Tolerate using the `__proto__` property - "scripturl" : false, // true: Tolerate script-targeted URLs - "smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment - "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;` - "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation - "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;` - "validthis" : false, // true: Tolerate using this in a non-constructor function - - // Environments - "browser" : true, // Web Browser (window, document, etc) - "couch" : false, // CouchDB - "devel" : true, // Development/debugging (alert, confirm, etc) - "dojo" : false, // Dojo Toolkit - "jquery" : false, // jQuery - "mootools" : false, // MooTools - "node" : false, // Node.js - "nonstandard" : false, // Widely adopted globals (escape, unescape, etc) - "prototypejs" : false, // Prototype and Scriptaculous - "rhino" : false, // Rhino - "worker" : false, // Web Workers - "wsh" : false, // Windows Scripting Host - "yui" : false, // Yahoo User Interface - //"meteor" : false, // Meteor.js - - // Legacy - "nomen" : false, // true: Prohibit dangling `_` in variables - "onevar" : false, // true: Allow only one `var` statement per function - "passfail" : false, // true: Stop on first error - "white" : false, // true: Check against strict whitespace and indentation rules - - // Custom Globals - "predef" : [ - "Meteor", - "Accounts", - "Session", - "Template", - "check", - "Match", - "Deps", - "EJSON", - "Email", - "Package", - "Tinytest", - "Npm", - "Assets", - "Packages", - "process", - "GroundDB", - "_gDB", - "LocalCollection", - "_", - "Random" - ] // additional predefined global variables -} diff --git a/packages/wekan-cfs-power-queue/.travis.yml b/packages/wekan-cfs-power-queue/.travis.yml deleted file mode 100644 index 6a4640033..000000000 --- a/packages/wekan-cfs-power-queue/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - "0.10" -before_install: - - "curl -L http://git.io/s0Zu-w | /bin/sh" \ No newline at end of file diff --git a/packages/wekan-cfs-power-queue/LICENSE.md b/packages/wekan-cfs-power-queue/LICENSE.md deleted file mode 100644 index 2a5c5339e..000000000 --- a/packages/wekan-cfs-power-queue/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 [@raix](https://github.com/raix), aka Morten N.O. Nørgaard Henriksen, mh@gi-software.com - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/wekan-cfs-power-queue/README.md b/packages/wekan-cfs-power-queue/README.md deleted file mode 100644 index 7b889a7c0..000000000 --- a/packages/wekan-cfs-power-queue/README.md +++ /dev/null @@ -1,136 +0,0 @@ -wekan-cfs-power-queue [![Build Status](https://travis-ci.org/CollectionFS/Meteor-powerqueue.png?branch=master)](https://travis-ci.org/CollectionFS/Meteor-powerqueue) -========= - -~~Looking for maintainers - please reach out!~~ -This package is to be archived due to inability to find contributors, thanks to everyone who helped make it possible. - -**If you're looking for an alternative, we highly recommend [Meteor-Files](https://github.com/VeliovGroup/Meteor-Files) by [VeliovGroup](https://github.com/VeliovGroup)** - ---- - -PowerQueue is a native Meteor package for memory-backed job queue processing. Features include: -* async tasks -* throttling resource usage -* retrying failed tasks -* managing sub-queues -* powered by Meteor's reactive sugar -* etc. - -PowerQueue can use one of two [spinal-queue](https://github.com/zcfs/Meteor-power-queue/blob/master/spinal-queue.spec.md) packages, [ReactiveList](https://github.com/zcfs/Meteor-reactive-list) or [MicroQueue](https://github.com/zcfs/Meteor-micro-queue). - -## Demos - -**Check out the cool [live queue demo](http://power-queue-test.meteor.com) and [live sub queue example](http://power-queue-sub-test.meteor.com).** - -Source code for both can be found in the two branches of the [power-queue-example repo](https://github.com/zcfs/power-queue-example). - - -Kind regards, -Eric(@aldeed) and Morten(@raix) - -Happy coding! - -# API -All getters and setters are reactive. - -[API Documentation](api.md) - -## Helpers / Getters / Setters: -* PowerQueue.length - Number of tasks in queue -* PowerQueue.progress - Current progress in percent -* PowerQueue.usage - Current load in percent -* PowerQueue.total - Sum of tasks to run in current queue -* PowerQueue.isPaused - True if queue is paused -* PowerQueue.isHalted - True if queue is paused or stopped -* PowerQueue.processing - Number of tasks being processed -* PowerQueue.errors - Failures where task is passed to the errorHandler -* PowerQueue.failures - Number of failures in current queue -* PowerQueue.isRunning - True if queue is active -* PowerQueue.maxProcessing - Getter + Setter for max tasks to run in parallel -* PowerQueue.autostart - Getter + Setter for autostart flag - Allow add task to start the queue -* PowerQueue.maxFailures - Max allowed retries for failing tasks before marked as an error -* options.queue - Use custom micro-queue compatible queue -* options.onEnded - Called when queue has ended -* options.onRelease(remainingTasks) - Called when queue has ended or paused -* options.onAutostart - Called when queue was autostarted - -## Methods -* PowerQueue.add(data) - Add a task to queue -* PowerQueue.run() - Start the queue -* PowerQueue.pause() - Pause the queue -* PowerQueue.resume() - Resume the queue if paused -* PowerQueue.reset() - Reset the queue -* PowerQueue.taskHandler(data, next, failures) - Default task handler, where data is a `function(done)`, can be overwritten -* PowerQueue.errorHandler(data, addTask, failures) - Default error handler, can be overwritten - -# Example 1 -```js - var queue = new PowerQueue({ - isPaused: true - }); - - queue.add(function(done) { - console.log('task 1'); - done(); - }); - queue.add(function(done) { - console.log('task 2'); - done(); - }); - queue.add(function(done) { - console.log('task 3'); - done(); - }); - - console.log('Ready to run queue'); - queue.run(); -``` - -# Example 2 - -This is a very rough example of how to make custom task handling. - -```js - - queue.errorHandler = function(data, addTask) { - // This error handler lets the task drop, but we could use addTask to - // Put the task into the queue again - tasks.update({ _id: data.id }, { $set: { status: 'error'} }); - }; - - queue.taskHandler = function(data, next) { - - // The task is now processed... - tasks.update({ _id: data.id }, { $set: { status: 'processing'} }); - - Meteor.setTimeout(function() { - if (Math.random() > 0.5) { - // We random fail the task - tasks.update({ _id: data.id }, { $set: { status: 'failed'} }); - // Returning error to next - next('Error: Fail task'); - } else { - // We are done! - tasks.update({ _id: data.id }, { $set: { status: 'done'} }); - // Trigger next task - next(); - } - // This async task duration is between 500 - 1000ms - }, Math.round(500 + 500 * Math.random())); - }; - - // Add the task: - var taskId = 0; - queue.add({ id: tasks.insert({ status: 'added', index: ++taskId }) }); -``` - -# Contribute - -Here's the [complete API documentation](internal.api.md), including private methods. - -To update the docs, run `npm install docmeteor` then `docmeteor`. - - -## TODO / Wishlist - -* scheduling jobs to run in the future, like [meteor-queue](https://github.com/artwells/meteor-queue#features) - see [issue #15](https://github.com/zcfs/Meteor-power-queue/issues/15) diff --git a/packages/wekan-cfs-power-queue/api.md b/packages/wekan-cfs-power-queue/api.md deleted file mode 100644 index 435610d8f..000000000 --- a/packages/wekan-cfs-power-queue/api.md +++ /dev/null @@ -1,420 +0,0 @@ - -#### new PowerQueue([options])  Anywhere #### -``` -Creates an instance of a power queue -[Check out demo](http://power-queue-test.meteor.com/) -``` -- - -__Arguments__ - -* __options__ *{object}* (Optional) -Settings - - __filo__ *{boolean}* (Default = false) -Make it a first in last out queue - - __isPaused__ *{boolean}* (Default = false) -Set queue paused - - __autostart__ *{boolean}* (Default = true) -May adding a task start the queue - - __name__ *{string}* (Default = "Queue") -Name of the queue - - __maxProcessing__ *{number}* (Default = 1) -Limit of simultanous running tasks - - __maxFailures__ *{number}* (Default = 5) -Limit retries of failed tasks, if 0 or below we allow infinite failures - - __jumpOnFailure__ *{number}* (Default = true) -Jump to next task and retry failed task later - - __debug__ *{boolean}* (Default = false) -Log verbose messages to the console - - __reactive__ *{boolean}* (Default = true) -Set whether or not this queue should be reactive - - __spinalQueue__ *{[SpinalQueue](spinal-queue.spec.md)}* (Optional) -Set spinal queue uses pr. default `MicroQueue` or `ReactiveList` if added to the project - -- - - - -> ```PowerQueue = function(options) { ...``` [power-queue.js:27](power-queue.js#L27) - -- - -#### *powerqueue*.onEnded  Anywhere #### -- -*This callback __onEnded__ is defined in `PowerQueue`* -Is called when queue is ended - -> ```self.onEnded = options && options.onEnded || function() { ...``` [power-queue.js:103](power-queue.js#L103) - -- - -#### *powerqueue*.onRelease  Anywhere #### -- -*This callback __onRelease__ is defined in `PowerQueue`* -Is called when queue is released - -> ```self.onRelease = options && options.onRelease || function() { ...``` [power-queue.js:110](power-queue.js#L110) - -- - -#### *powerqueue*.onAutostart  Anywhere #### -- -*This callback __onAutostart__ is defined in `PowerQueue`* -Is called when queue is auto started - -> ```self.onAutostart = options && options.onAutostart || function() { ...``` [power-queue.js:115](power-queue.js#L115) - -- - -#### *powerqueue*.total()  Anywhere #### -- -*This method __total__ is defined in `PowerQueue`* - -__Returns__ *{number}* __(is reactive)__ -The total number of tasks added to this queue - -> ```self.total = self._maxLength.get;``` [power-queue.js:123](power-queue.js#L123) - -- - -#### *powerqueue*.isPaused()  Anywhere #### -- -*This method __isPaused__ is defined in `PowerQueue`* - -__Returns__ *{boolean}* __(is reactive)__ -Status of the paused state of the queue - -> ```self.isPaused = self._paused.get;``` [power-queue.js:129](power-queue.js#L129) - -- - -#### *powerqueue*.processing()  Anywhere #### -- -*This method __processing__ is defined in `PowerQueue`* - -__Returns__ *{number}* __(is reactive)__ -Number of tasks currently being processed - -> ```self.processing = self._isProcessing.get;``` [power-queue.js:135](power-queue.js#L135) - -- - -#### *powerqueue*.errors()  Anywhere #### -- -*This method __errors__ is defined in `PowerQueue`* - -__Returns__ *{number}* __(is reactive)__ -The total number of errors -Errors are triggered when [maxFailures](PowerQueue.maxFailures) are exeeded - -> ```self.errors = self._errors.get;``` [power-queue.js:142](power-queue.js#L142) - -- - -#### *powerqueue*.failures()  Anywhere #### -- -*This method __failures__ is defined in `PowerQueue`* - -__Returns__ *{number}* __(is reactive)__ -The total number of failed tasks - -> ```self.failures = self._failures.get;``` [power-queue.js:148](power-queue.js#L148) - -- - -#### *powerqueue*.isRunning()  Anywhere #### -- -*This method __isRunning__ is defined in `PowerQueue`* - -__Returns__ *{boolean}* __(is reactive)__ -True if the queue is running -> NOTE: The task can be paused but marked as running - -> ```self.isRunning = self._running.get;``` [power-queue.js:155](power-queue.js#L155) - -- - -#### *powerqueue*.maxProcessing([max])  Anywhere #### -- -*This method __maxProcessing__ is defined in `PowerQueue`* - -__Arguments__ - -* __max__ *{number}* (Optional) -If not used this function works as a getter - -- - -__Returns__ *{number}* __(is reactive)__ -Maximum number of simultaneous processing tasks - -Example: -```js - foo.maxProcessing(); // Works as a getter and returns the current value - foo.maxProcessing(20); // This sets the value to 20 -``` - -> ```self.maxProcessing = self._maxProcessing.getset;``` [power-queue.js:168](power-queue.js#L168) - -- - -#### *powerqueue*.autostart([autorun])  Anywhere #### -- -*This method __autostart__ is defined in `PowerQueue`* - -__Arguments__ - -* __autorun__ *{boolean}* (Optional) -If not used this function works as a getter - -- - -__Returns__ *{boolean}* __(is reactive)__ -If adding a task may trigger the queue to start - -Example: -```js - foo.autostart(); // Works as a getter and returns the current value - foo.autostart(true); // This sets the value to true -``` - -> ```self.autostart = self._autostart.getset;``` [power-queue.js:189](power-queue.js#L189) - -- - -#### *powerqueue*.maxFailures([max])  Anywhere #### -- -*This method __maxFailures__ is defined in `PowerQueue`* - -__Arguments__ - -* __max__ *{number}* (Optional) -If not used this function works as a getter - -- - -__Returns__ *{number}* __(is reactive)__ -The maximum for failures pr. task before triggering an error - -Example: -```js - foo.maxFailures(); // Works as a getter and returns the current value - foo.maxFailures(10); // This sets the value to 10 -``` - -> ```self.maxFailures = self._maxFailures.getset;``` [power-queue.js:202](power-queue.js#L202) - -- - -#### *powerqueue*.processList()  Anywhere #### -- -*This method __processList__ is defined in `prototype` of `PowerQueue`* - -__Returns__ *{array}* __(is reactive)__ -List of tasks currently being processed - -> ```PowerQueue.prototype.processingList = function() { ...``` [power-queue.js:209](power-queue.js#L209) - -- - -#### *powerqueue*.isHalted()  Anywhere #### -- -*This method __isHalted__ is defined in `prototype` of `PowerQueue`* - -__Returns__ *{boolean}* __(is reactive)__ -True if the queue is not running or paused - -> ```PowerQueue.prototype.isHalted = function() { ...``` [power-queue.js:218](power-queue.js#L218) - -- - -#### *powerqueue*.length()  Anywhere #### -- -*This method __length__ is defined in `prototype` of `PowerQueue`* - -__Returns__ *{number}* __(is reactive)__ -Number of tasks left in queue to be processed - -> ```PowerQueue.prototype.length = function() { ...``` [power-queue.js:227](power-queue.js#L227) - -- - -#### *powerqueue*.progress()  Anywhere #### -- -*This method __progress__ is defined in `prototype` of `PowerQueue`* - -__Returns__ *{number}* __(is reactive)__ -0 .. 100 % Indicates the status of the queue - -> ```PowerQueue.prototype.progress = function() { ...``` [power-queue.js:236](power-queue.js#L236) - -- - -#### *powerqueue*.usage()  Anywhere #### -- -*This method __usage__ is defined in `prototype` of `PowerQueue`* - -__Returns__ *{number}* __(is reactive)__ -0 .. 100 % Indicates ressource usage of the queue - -> ```PowerQueue.prototype.usage = function() { ...``` [power-queue.js:249](power-queue.js#L249) - -- - -#### *powerqueue*.reset()  Anywhere #### -- -*This method __reset__ is defined in `prototype` of `PowerQueue`* -Calling this will: -* stop the queue -* paused to false -* Discart all queue data - -> NOTE: At the moment if the queue has processing tasks they can change -> the `errors` and `failures` counters. This could change in the future or -> be prevented by creating a whole new instance of the `PowerQueue` - -> ```PowerQueue.prototype.reset = function() { ...``` [power-queue.js:264](power-queue.js#L264) - -- - -#### *powerqueue*.add(data, [failures])  Anywhere #### -- -*This method __add__ is defined in `prototype` of `PowerQueue`* - -__Arguments__ - -* __data__ *{any}* -The task to be handled -* __failures__ *{number}* (Optional) -Internally used to Pass on number of failures. - -- - -> ```PowerQueue.prototype.add = function(data, failures, id) { ...``` [power-queue.js:316](power-queue.js#L316) - -- - -#### *powerqueue*.next([err])  Anywhere #### -- -*This method __next__ is defined in `prototype` of `PowerQueue`* - -__Arguments__ - -* __err__ *{string}* (Optional) -Error message if task failed - -- -> * Can pass in `null` to start the queue -> * Passing in a string to `next` will trigger a failure -> * Passing nothing will simply let the next task run -`next` is handed into the [taskHandler](PowerQueue.taskHandler) as a -callback to mark an error or end of current task - -> ```PowerQueue.prototype.next = function(err) { ...``` [power-queue.js:394](power-queue.js#L394) - -- - -#### *powerqueue*.queueTaskHandler()  Anywhere #### -- -*This method __queueTaskHandler__ is defined in `prototype` of `PowerQueue`* -This method handles tasks that are sub queues - -> ```PowerQueue.prototype.queueTaskHandler = function(subQueue, next, failures) { ...``` [power-queue.js:555](power-queue.js#L555) - -- - -#### *powerqueue*.taskHandler  Anywhere #### -- -*This callback __taskHandler__ is defined in `prototype` of `PowerQueue`* - -__Arguments__ - -* __data__ *{any}* -This can be data or functions -* __next__ *{function}* -Function `next` call this to end task -* __failures__ *{number}* -Number of failures on this task - -- - -Default task handler expects functions as data: -```js - self.taskHandler = function(data, next, failures) { - // This default task handler expects invocation to be a function to run - if (typeof data !== 'function') { - throw new Error('Default task handler expects a function'); - } - try { - // Have the function call next - data(next, failures); - } catch(err) { - // Throw to fail this task - next(err); - } - }; -``` - -> ```PowerQueue.prototype.taskHandler = function(data, next, failures) { ...``` [power-queue.js:601](power-queue.js#L601) - -- - -#### *powerqueue*.errorHandler  Anywhere #### -- -*This callback __errorHandler__ is defined in `prototype` of `PowerQueue`* - -__Arguments__ - -* __data__ *{any}* -This can be data or functions -* __addTask__ *{function}* -Use this function to insert the data into the queue again -* __failures__ *{number}* -Number of failures on this task - -- - -The default callback: -```js - var foo = new PowerQueue(); - - // Overwrite the default action - foo.errorHandler = function(data, addTask, failures) { - // This could be overwritten the data contains the task data and addTask - // is a helper for adding the task to the queue - // try again: addTask(data); - // console.log('Terminate at ' + failures + ' failures'); - }; -``` - -> ```PowerQueue.prototype.errorHandler = function(data, addTask, failures) { ...``` [power-queue.js:634](power-queue.js#L634) - -- - -#### *powerqueue*.pause()  Anywhere #### -- -*This method __pause__ is defined in `prototype` of `PowerQueue`* - -> ```PowerQueue.prototype.pause = function() { ...``` [power-queue.js:645](power-queue.js#L645) - -- - -#### *powerqueue*.resume()  Anywhere #### -- -*This method __resume__ is defined in `prototype` of `PowerQueue`* - -> This will not start a stopped queue - -> ```PowerQueue.prototype.resume = function() { ...``` [power-queue.js:665](power-queue.js#L665) - -- - -#### *powerqueue*.run()  Anywhere #### -- -*This method __run__ is defined in `prototype` of `PowerQueue`* -> Using this command will resume a paused queue and will -> start a stopped queue. - -> ```PowerQueue.prototype.run = function() { ...``` [power-queue.js:677](power-queue.js#L677) - -- diff --git a/packages/wekan-cfs-power-queue/internal.api.md b/packages/wekan-cfs-power-queue/internal.api.md deleted file mode 100644 index 797f1f454..000000000 --- a/packages/wekan-cfs-power-queue/internal.api.md +++ /dev/null @@ -1,535 +0,0 @@ -> File: ["power-queue.js"](power-queue.js) -> Where: {client|server} - -- - -#### new PowerQueue([options])  Anywhere #### -``` -Creates an instance of a power queue -[Check out demo](http://power-queue-test.meteor.com/) -``` -- - -__Arguments__ - -* __options__ *{object}* (Optional) -Settings - - __filo__ *{boolean}* (Default = false) -Make it a first in last out queue - - __isPaused__ *{boolean}* (Default = false) -Set queue paused - - __autostart__ *{boolean}* (Default = true) -May adding a task start the queue - - __name__ *{string}* (Default = "Queue") -Name of the queue - - __maxProcessing__ *{number}* (Default = 1) -Limit of simultanous running tasks - - __maxFailures__ *{number}* (Default = 5) -Limit retries of failed tasks, if 0 or below we allow infinite failures - - __jumpOnFailure__ *{number}* (Default = true) -Jump to next task and retry failed task later - - __debug__ *{boolean}* (Default = false) -Log verbose messages to the console - - __reactive__ *{boolean}* (Default = true) -Set whether or not this queue should be reactive - - __spinalQueue__ *{[SpinalQueue](spinal-queue.spec.md)}* (Optional) -Set spinal queue uses pr. default `MicroQueue` or `ReactiveList` if added to the project - -- - - - -> ```PowerQueue = function(options) { ...``` [power-queue.js:27](power-queue.js#L27) - -- - -#### *powerqueue*.onEnded  Anywhere #### -- -*This callback __onEnded__ is defined in `PowerQueue`* -Is called when queue is ended - -> ```self.onEnded = options && options.onEnded || function() { ...``` [power-queue.js:103](power-queue.js#L103) - -- - -#### *powerqueue*.onRelease  Anywhere #### -- -*This callback __onRelease__ is defined in `PowerQueue`* -Is called when queue is released - -> ```self.onRelease = options && options.onRelease || function() { ...``` [power-queue.js:110](power-queue.js#L110) - -- - -#### *powerqueue*.onAutostart  Anywhere #### -- -*This callback __onAutostart__ is defined in `PowerQueue`* -Is called when queue is auto started - -> ```self.onAutostart = options && options.onAutostart || function() { ...``` [power-queue.js:115](power-queue.js#L115) - -- - -#### *powerqueue*.total()  Anywhere #### -- -*This method __total__ is defined in `PowerQueue`* - -__Returns__ *{number}* __(is reactive)__ -The total number of tasks added to this queue - -> ```self.total = self._maxLength.get;``` [power-queue.js:123](power-queue.js#L123) - -- - -#### *powerqueue*.isPaused()  Anywhere #### -- -*This method __isPaused__ is defined in `PowerQueue`* - -__Returns__ *{boolean}* __(is reactive)__ -Status of the paused state of the queue - -> ```self.isPaused = self._paused.get;``` [power-queue.js:129](power-queue.js#L129) - -- - -#### *powerqueue*.processing()  Anywhere #### -- -*This method __processing__ is defined in `PowerQueue`* - -__Returns__ *{number}* __(is reactive)__ -Number of tasks currently being processed - -> ```self.processing = self._isProcessing.get;``` [power-queue.js:135](power-queue.js#L135) - -- - -#### *powerqueue*.errors()  Anywhere #### -- -*This method __errors__ is defined in `PowerQueue`* - -__Returns__ *{number}* __(is reactive)__ -The total number of errors -Errors are triggered when [maxFailures](PowerQueue.maxFailures) are exeeded - -> ```self.errors = self._errors.get;``` [power-queue.js:142](power-queue.js#L142) - -- - -#### *powerqueue*.failures()  Anywhere #### -- -*This method __failures__ is defined in `PowerQueue`* - -__Returns__ *{number}* __(is reactive)__ -The total number of failed tasks - -> ```self.failures = self._failures.get;``` [power-queue.js:148](power-queue.js#L148) - -- - -#### *powerqueue*.isRunning()  Anywhere #### -- -*This method __isRunning__ is defined in `PowerQueue`* - -__Returns__ *{boolean}* __(is reactive)__ -True if the queue is running -> NOTE: The task can be paused but marked as running - -> ```self.isRunning = self._running.get;``` [power-queue.js:155](power-queue.js#L155) - -- - -#### *powerqueue*.maxProcessing([max])  Anywhere #### -- -*This method __maxProcessing__ is defined in `PowerQueue`* - -__Arguments__ - -* __max__ *{number}* (Optional) -If not used this function works as a getter - -- - -__Returns__ *{number}* __(is reactive)__ -Maximum number of simultaneous processing tasks - -Example: -```js - foo.maxProcessing(); // Works as a getter and returns the current value - foo.maxProcessing(20); // This sets the value to 20 -``` - -> ```self.maxProcessing = self._maxProcessing.getset;``` [power-queue.js:168](power-queue.js#L168) - -- - -#### *powerqueue*.autostart([autorun])  Anywhere #### -- -*This method __autostart__ is defined in `PowerQueue`* - -__Arguments__ - -* __autorun__ *{boolean}* (Optional) -If not used this function works as a getter - -- - -__Returns__ *{boolean}* __(is reactive)__ -If adding a task may trigger the queue to start - -Example: -```js - foo.autostart(); // Works as a getter and returns the current value - foo.autostart(true); // This sets the value to true -``` - -> ```self.autostart = self._autostart.getset;``` [power-queue.js:189](power-queue.js#L189) - -- - -#### *powerqueue*.maxFailures([max])  Anywhere #### -- -*This method __maxFailures__ is defined in `PowerQueue`* - -__Arguments__ - -* __max__ *{number}* (Optional) -If not used this function works as a getter - -- - -__Returns__ *{number}* __(is reactive)__ -The maximum for failures pr. task before triggering an error - -Example: -```js - foo.maxFailures(); // Works as a getter and returns the current value - foo.maxFailures(10); // This sets the value to 10 -``` - -> ```self.maxFailures = self._maxFailures.getset;``` [power-queue.js:202](power-queue.js#L202) - -- - -#### *powerqueue*.processList()  Anywhere #### -- -*This method __processList__ is defined in `prototype` of `PowerQueue`* - -__Returns__ *{array}* __(is reactive)__ -List of tasks currently being processed - -> ```PowerQueue.prototype.processingList = function() { ...``` [power-queue.js:209](power-queue.js#L209) - -- - -#### *powerqueue*.isHalted()  Anywhere #### -- -*This method __isHalted__ is defined in `prototype` of `PowerQueue`* - -__Returns__ *{boolean}* __(is reactive)__ -True if the queue is not running or paused - -> ```PowerQueue.prototype.isHalted = function() { ...``` [power-queue.js:218](power-queue.js#L218) - -- - -#### *powerqueue*.length()  Anywhere #### -- -*This method __length__ is defined in `prototype` of `PowerQueue`* - -__Returns__ *{number}* __(is reactive)__ -Number of tasks left in queue to be processed - -> ```PowerQueue.prototype.length = function() { ...``` [power-queue.js:227](power-queue.js#L227) - -- - -#### *powerqueue*.progress()  Anywhere #### -- -*This method __progress__ is defined in `prototype` of `PowerQueue`* - -__Returns__ *{number}* __(is reactive)__ -0 .. 100 % Indicates the status of the queue - -> ```PowerQueue.prototype.progress = function() { ...``` [power-queue.js:236](power-queue.js#L236) - -- - -#### *powerqueue*.usage()  Anywhere #### -- -*This method __usage__ is defined in `prototype` of `PowerQueue`* - -__Returns__ *{number}* __(is reactive)__ -0 .. 100 % Indicates ressource usage of the queue - -> ```PowerQueue.prototype.usage = function() { ...``` [power-queue.js:249](power-queue.js#L249) - -- - -#### *powerqueue*.reset()  Anywhere #### -- -*This method __reset__ is defined in `prototype` of `PowerQueue`* -Calling this will: -* stop the queue -* paused to false -* Discart all queue data - -> NOTE: At the moment if the queue has processing tasks they can change -> the `errors` and `failures` counters. This could change in the future or -> be prevented by creating a whole new instance of the `PowerQueue` - -> ```PowerQueue.prototype.reset = function() { ...``` [power-queue.js:264](power-queue.js#L264) - -- - -#### *powerqueue*._autoStartTasks()  Anywhere #### -- -*This method is private* -*This method ___autoStartTasks__ is defined in `PowerQueue`* - -This method defines the autostart algorithm that allows add task to trigger -a start of the queue if queue is not paused. - -> ```PowerQueue.prototype._autoStartTasks = function() { ...``` [power-queue.js:289](power-queue.js#L289) - -- - -#### *powerqueue*.add(data, [failures])  Anywhere #### -- -*This method __add__ is defined in `prototype` of `PowerQueue`* - -__Arguments__ - -* __data__ *{any}* -The task to be handled -* __failures__ *{number}* (Optional) -Internally used to Pass on number of failures. - -- - -> ```PowerQueue.prototype.add = function(data, failures, id) { ...``` [power-queue.js:316](power-queue.js#L316) - -- - -#### *powerqueue*.updateThrottleUp()  Anywhere #### -- -*This method is private* -*This method __updateThrottleUp__ is defined in `prototype` of `PowerQueue`* - -Calling this method will update the throttle on the queue adding tasks. - -> Note: Currently we only support the PowerQueue - but we could support -> a more general interface for pauseable tasks or other usecases. - -> ```PowerQueue.prototype.updateThrottleUp = function() { ...``` [power-queue.js:342](power-queue.js#L342) - -- - -#### *powerqueue*.updateThrottleDown()  Anywhere #### -- -*This method is private* -*This method __updateThrottleDown__ is defined in `prototype` of `PowerQueue`* - -Calling this method will update the throttle on the queue pause tasks. - -> Note: Currently we only support the PowerQueue - but we could support -> a more general interface for pauseable tasks or other usecases. - -> ```PowerQueue.prototype.updateThrottleDown = function() { ...``` [power-queue.js:367](power-queue.js#L367) - -- - -#### *powerqueue*.next([err])  Anywhere #### -- -*This method __next__ is defined in `prototype` of `PowerQueue`* - -__Arguments__ - -* __err__ *{string}* (Optional) -Error message if task failed - -- -> * Can pass in `null` to start the queue -> * Passing in a string to `next` will trigger a failure -> * Passing nothing will simply let the next task run -`next` is handed into the [taskHandler](PowerQueue.taskHandler) as a -callback to mark an error or end of current task - -> ```PowerQueue.prototype.next = function(err) { ...``` [power-queue.js:394](power-queue.js#L394) - -- - -#### done  Anywhere #### -- - -__Arguments__ - -* __feedback__ *{[Meteor.Error ](#Meteor.Error )|[ Error ](# Error )|[ String ](# String )|[ null](# null)}* (Optional) -This allows the task to communicate with the queue - -- - -Explaination of `feedback` -* `Meteor.Error` This means that the task failed in a controlled manner and is allowed to rerun -* `Error` This will throw the passed error - as its an unitended error -* `null` The task is not done yet, rerun later -* `String` The task can perform certain commands on the queue - * "pause" - pause the queue - * "stop" - stop the queue - * "reset" - reset the queue - * "cancel" - cancel the queue - - -> ```PowerQueue.prototype.runTaskDone = function(feedback, invocation) { ...``` [power-queue.js:452](power-queue.js#L452) - -- - -#### *powerqueue*.runTaskDone([feedback], invocation)  Anywhere #### -- -*This method is private* -*This method __runTaskDone__ is defined in `prototype` of `PowerQueue`* - -__Arguments__ - -* __feedback__ *{[Meteor.Error ](#Meteor.Error )|[ Error ](# Error )|[ String ](# String )|[ null](# null)}* (Optional) -This allows the task to communicate with the queue -* __invocation__ *{object}* - -- - -> Note: `feedback` is explained in [Done callback](#done) - - -> ```PowerQueue.prototype.runTaskDone = function(feedback, invocation) { ...``` [power-queue.js:452](power-queue.js#L452) - -- - -#### *powerqueue*.runTask(invocation)  Anywhere #### -- -*This method is private* -*This method __runTask__ is defined in `prototype` of `PowerQueue`* - -__Arguments__ - -* __invocation__ *{object}* -The object stored in the micro-queue - -- - -> ```PowerQueue.prototype.runTask = function(invocation) { ...``` [power-queue.js:521](power-queue.js#L521) - -- - -#### *powerqueue*.queueTaskHandler()  Anywhere #### -- -*This method __queueTaskHandler__ is defined in `prototype` of `PowerQueue`* -This method handles tasks that are sub queues - -> ```PowerQueue.prototype.queueTaskHandler = function(subQueue, next, failures) { ...``` [power-queue.js:555](power-queue.js#L555) - -- - -#### *powerqueue*.taskHandler  Anywhere #### -- -*This callback __taskHandler__ is defined in `prototype` of `PowerQueue`* - -__Arguments__ - -* __data__ *{any}* -This can be data or functions -* __next__ *{function}* -Function `next` call this to end task -* __failures__ *{number}* -Number of failures on this task - -- - -Default task handler expects functions as data: -```js - self.taskHandler = function(data, next, failures) { - // This default task handler expects invocation to be a function to run - if (typeof data !== 'function') { - throw new Error('Default task handler expects a function'); - } - try { - // Have the function call next - data(next, failures); - } catch(err) { - // Throw to fail this task - next(err); - } - }; -``` - -> ```PowerQueue.prototype.taskHandler = function(data, next, failures) { ...``` [power-queue.js:601](power-queue.js#L601) - -- - -#### *powerqueue*.errorHandler  Anywhere #### -- -*This callback __errorHandler__ is defined in `prototype` of `PowerQueue`* - -__Arguments__ - -* __data__ *{any}* -This can be data or functions -* __addTask__ *{function}* -Use this function to insert the data into the queue again -* __failures__ *{number}* -Number of failures on this task - -- - -The default callback: -```js - var foo = new PowerQueue(); - - // Overwrite the default action - foo.errorHandler = function(data, addTask, failures) { - // This could be overwritten the data contains the task data and addTask - // is a helper for adding the task to the queue - // try again: addTask(data); - // console.log('Terminate at ' + failures + ' failures'); - }; -``` - -> ```PowerQueue.prototype.errorHandler = function(data, addTask, failures) { ...``` [power-queue.js:634](power-queue.js#L634) - -- - -#### *powerqueue*.pause()  Anywhere #### -- -*This method __pause__ is defined in `prototype` of `PowerQueue`* - -__TODO__ -``` -* We should have it pause all processing tasks -``` - -> ```PowerQueue.prototype.pause = function() { ...``` [power-queue.js:645](power-queue.js#L645) - -- - -#### *powerqueue*.resume()  Anywhere #### -- -*This method __resume__ is defined in `prototype` of `PowerQueue`* - -__TODO__ -``` -* We should have it resume all processing tasks -``` - -> This will not start a stopped queue - -> ```PowerQueue.prototype.resume = function() { ...``` [power-queue.js:665](power-queue.js#L665) - -- - -#### *powerqueue*.run()  Anywhere #### -- -*This method __run__ is defined in `prototype` of `PowerQueue`* -> Using this command will resume a paused queue and will -> start a stopped queue. - -> ```PowerQueue.prototype.run = function() { ...``` [power-queue.js:677](power-queue.js#L677) - -- diff --git a/packages/wekan-cfs-power-queue/package.js b/packages/wekan-cfs-power-queue/package.js deleted file mode 100644 index 757fd06c2..000000000 --- a/packages/wekan-cfs-power-queue/package.js +++ /dev/null @@ -1,27 +0,0 @@ -Package.describe({ - name: 'wekan-cfs-power-queue', - version: '0.9.11', - summary: "PowerQueue is a powerful tool for handling async tasks, throtling etc.", - git: 'https://github.com/zcfs/Meteor-power-queue.git' -}); - -Package.onUse(function (api) { - api.versionsFrom('1.0'); - - api.use(['deps', 'wekan-cfs-reactive-property@0.0.4'], ['client', 'server']); - - // We let the user decide what spinal queue to use - We support both - // reactive-list and micro-queue they obey the spinal-queue spec - api.use(['wekan-cfs-reactive-list@0.0.9', 'wekan-cfs-micro-queue@0.0.6'], ['client', 'server'], { weak: true }); - - api.export && api.export('PowerQueue'); - api.addFiles(['power-queue.js'], ['client', 'server']); -}); - -Package.onTest(function (api) { - api.use(['wekan-cfs-power-queue', 'wekan-cfs-reactive-list']); - api.use('test-helpers', ['server', 'client']); - api.use('tinytest'); - - api.addFiles('tests.js'); -}); diff --git a/packages/wekan-cfs-power-queue/power-queue.js b/packages/wekan-cfs-power-queue/power-queue.js deleted file mode 100644 index e1e323163..000000000 --- a/packages/wekan-cfs-power-queue/power-queue.js +++ /dev/null @@ -1,727 +0,0 @@ -// Rig weak dependencies -if (typeof MicroQueue === 'undefined' && Package['micro-queue']) { - MicroQueue = Package['micro-queue'].MicroQueue; -} -if (typeof ReactiveList === 'undefined' && Package['reactive-list']) { - ReactiveList = Package['reactive-list'].ReactiveList; -} - -// Rig weak dependencies in +0.9.1 -if (typeof MicroQueue === 'undefined' && Package['wekan-cfs-micro-queue']) { - MicroQueue = Package['wekan-cfs-micro-queue'].MicroQueue; -} -if (typeof ReactiveList === 'undefined' && Package['wekan-cfs-reactive-list']) { - ReactiveList = Package['wekan-cfs-reactive-list'].ReactiveList; -} - -/** - * Creates an instance of a power queue // Testing inline comment - * [Check out demo](http://power-queue-test.meteor.com/) - * - * @constructor - * @self powerqueue - * @param {object} [options] Settings - * @param {boolean} [options.filo=false] Make it a first in last out queue - * @param {boolean} [options.isPaused=false] Set queue paused - * @param {boolean} [options.autostart=true] May adding a task start the queue - * @param {string} [options.name="Queue"] Name of the queue - * @param {number} [options.maxProcessing=1] Limit of simultanous running tasks - * @param {number} [options.maxFailures = 5] Limit retries of failed tasks, if 0 or below we allow infinite failures - * @param {number} [options.jumpOnFailure = true] Jump to next task and retry failed task later - * @param {boolean} [options.debug=false] Log verbose messages to the console - * @param {boolean} [options.reactive=true] Set whether or not this queue should be reactive - * @param {boolean} [options.onAutostart] Callback for the queue autostart event - * @param {boolean} [options.onPaused] Callback for the queue paused event - * @param {boolean} [options.onReleased] Callback for the queue release event - * @param {boolean} [options.onEnded] Callback for the queue end event - * @param {[SpinalQueue](spinal-queue.spec.md)} [options.spinalQueue] Set spinal queue uses pr. default `MicroQueue` or `ReactiveList` if added to the project - */ -PowerQueue = function(options) { - var self = this; - var test = 5; - - self.reactive = (options && options.reactive === false) ? false : true; - - // Allow user to use another micro-queue #3 - // We try setting the ActiveQueue to MicroQueue if installed in the app - var ActiveQueue = (typeof MicroQueue !== 'undefined') && MicroQueue || undefined; - - // If ReactiveList is added to the project we use this over MicroQueue - ActiveQueue = (typeof ReactiveList !== 'undefined') && ReactiveList || ActiveQueue; - - // We allow user to overrule and set a custom spinal-queue spec complient queue - if (options && typeof options.spinalQueue !== 'undefined') { - ActiveQueue = options.spinalQueue; - } - - if (typeof ActiveQueue === 'undefined') { - console.log('Error: You need to add a spinal queue to the project'); - console.log('Please add "micro-queue", "reactive-list" to the project'); - throw new Error('Please add "micro-queue", "reactive-list" or other spinalQueue compatible packages'); - } - - // Default is fifo lilo - self.invocations = new ActiveQueue({ - // - sort: (options && (options.filo || options.lifo)), - reactive: self.reactive - }); - //var self.invocations = new ReactiveList(queueOrder); - - // List of current tasks being processed - self._processList = new ActiveQueue({ - reactive: self.reactive - }); //ReactiveList(); - - // Max number of simultanious tasks being processed - self._maxProcessing = new ReactiveProperty(options && options.maxProcessing || 1, self.reactive); - - // Reactive number of tasks being processed - self._isProcessing = new ReactiveProperty(0, self.reactive); - - // Boolean indicating if queue is paused or not - self._paused = new ReactiveProperty((options && options.isPaused || false), self.reactive); - - // Boolean indicator for queue status active / running (can still be paused) - self._running = new ReactiveProperty(false, self.reactive); - - // Counter for errors, errors are triggered if maxFailures is exeeded - self._errors = new ReactiveProperty(0, self.reactive); - - // Counter for task failures, contains error count - self._failures = new ReactiveProperty(0, self.reactive); - - // On failure jump to new task - if false the current task is rerun until error - self._jumpOnFailure = (options && options.jumpOnFailure === false) ? false : true; - - // Count of all added tasks - self._maxLength = new ReactiveProperty(0, self.reactive); - - // Boolean indicate whether or not a "add" task is allowed to start the queue - self._autostart = new ReactiveProperty( ((options && options.autostart === false) ? false : true), self.reactive); - - // Limit times a task is allowed to fail and be rerun later before triggering an error - self._maxFailures = new ReactiveProperty( (options && options.maxFailures || 5), self.reactive); - - // Name / title of this queue - Not used - should deprecate - self.title = options && options.name || 'Queue'; - - // debug - will print error / failures passed to next - self.debug = !!(options && options.debug); - - /** @method PowerQueue.total - * @reactive - * @returns {number} The total number of tasks added to this queue - */ - self.total = self._maxLength.get; - - /** @method PowerQueue.isPaused - * @reactive - * @returns {boolean} Status of the paused state of the queue - */ - self.isPaused = self._paused.get; - - /** @method PowerQueue.processing - * @reactive - * @returns {number} Number of tasks currently being processed - */ - self.processing = self._isProcessing.get; - - /** @method PowerQueue.errors - * @reactive - * @returns {number} The total number of errors - * Errors are triggered when [maxFailures](PowerQueue.maxFailures) are exeeded - */ - self.errors = self._errors.get; - - /** @method PowerQueue.failures - * @reactive - * @returns {number} The total number of failed tasks - */ - self.failures = self._failures.get; - - /** @method PowerQueue.isRunning - * @reactive - * @returns {boolean} True if the queue is running - * > NOTE: The task can be paused but marked as running - */ - self.isRunning = self._running.get; - - /** @method PowerQueue.maxProcessing Get setter for maxProcessing - * @param {number} [max] If not used this function works as a getter - * @reactive - * @returns {number} Maximum number of simultaneous processing tasks - * - * Example: - * ```js - * foo.maxProcessing(); // Works as a getter and returns the current value - * foo.maxProcessing(20); // This sets the value to 20 - * ``` - */ - self.maxProcessing = self._maxProcessing.getset; - - self._maxProcessing.onChange = function() { - // The user can change the max allowed processing tasks up or down here... - // Update the throttle up - self.updateThrottleUp(); - // Update the throttle down - self.updateThrottleDown(); - }; - - /** @method PowerQueue.autostart Get setter for autostart - * @param {boolean} [autorun] If not used this function works as a getter - * @reactive - * @returns {boolean} If adding a task may trigger the queue to start - * - * Example: - * ```js - * foo.autostart(); // Works as a getter and returns the current value - * foo.autostart(true); // This sets the value to true - * ``` - */ - self.autostart = self._autostart.getset; - - /** @method PowerQueue.maxFailures Get setter for maxFailures - * @param {number} [max] If not used this function works as a getter - * @reactive - * @returns {number} The maximum for failures pr. task before triggering an error - * - * Example: - * ```js - * foo.maxFailures(); // Works as a getter and returns the current value - * foo.maxFailures(10); // This sets the value to 10 - * ``` - */ - self.maxFailures = self._maxFailures.getset; - - /** @callback PowerQueue.onPaused - * Is called when queue is ended - */ - self.onPaused = options && options.onPaused || function() { - self.debug && console.log(self.title + ' ENDED'); - }; - - /** @callback PowerQueue.onEnded - * Is called when queue is ended - */ - self.onEnded = options && options.onEnded || function() { - self.debug && console.log(self.title + ' ENDED'); - }; - - /** @callback PowerQueue.onRelease - * Is called when queue is released - */ - self.onRelease = options && options.onRelease || function() { - self.debug && console.log(self.title + ' RELEASED'); - }; - - /** @callback PowerQueue.onAutostart - * Is called when queue is auto started - */ - self.onAutostart = options && options.onAutostart || function() { - self.debug && console.log(self.title + ' Autostart'); - }; -}; - - /** @method PowerQueue.prototype.processList - * @reactive - * @returns {array} List of tasks currently being processed - */ - PowerQueue.prototype.processingList = function() { - var self = this; - return self._processList.fetch(); - }; - - /** @method PowerQueue.prototype.isHalted - * @reactive - * @returns {boolean} True if the queue is not running or paused - */ - PowerQueue.prototype.isHalted = function() { - var self = this; - return (!self._running.get() || self._paused.get()); - }; - - /** @method PowerQueue.prototype.length - * @reactive - * @returns {number} Number of tasks left in queue to be processed - */ - PowerQueue.prototype.length = function() { - var self = this; - return self.invocations.length(); - }; - - /** @method PowerQueue.prototype.progress - * @reactive - * @returns {number} 0 .. 100 % Indicates the status of the queue - */ - PowerQueue.prototype.progress = function() { - var self = this; - var progress = self._maxLength.get() - self.invocations.length() - self._isProcessing.get(); - if (self._maxLength.value > 0) { - return Math.round(progress / self._maxLength.value * 100); - } - return 0; - }; - - /** @method PowerQueue.prototype.usage - * @reactive - * @returns {number} 0 .. 100 % Indicates resource usage of the queue - */ - PowerQueue.prototype.usage = function() { - var self = this; - return Math.round(self._isProcessing.get() / self._maxProcessing.get() * 100); - }; - - /** @method PowerQueue.prototype.reset Reset the queue - * Calling this will: - * * stop the queue - * * paused to false - * * Discart all queue data - * - * > NOTE: At the moment if the queue has processing tasks they can change - * > the `errors` and `failures` counters. This could change in the future or - * > be prevented by creating a whole new instance of the `PowerQueue` - */ - PowerQueue.prototype.reset = function() { - var self = this; - self.debug && console.log(self.title + ' RESET'); - self._running.set(false); - self._paused.set(false); - self.invocations.reset(); - self._processList.reset(); - - // // Loop through the processing tasks and reset these - // self._processList.forEach(function(data) { - // if (data.queue instanceof PowerQueue) { - // data.queue.reset(); - // } - // }, true); - self._maxLength.set(0); - self._failures.set(0); - self._errors.set(0); - }; - - /** @method PowerQueue._autoStartTasks - * @private - * - * This method defines the autostart algorithm that allows add task to trigger - * a start of the queue if queue is not paused. - */ - PowerQueue.prototype._autoStartTasks = function() { - var self = this; - - // We dont start anything by ourselfs if queue is paused - if (!self._paused.value) { - - // Queue is not running and we are set to autostart so we start the queue - if (!self._running.value && self._autostart.value) { - // Trigger callback / event - self.onAutostart(); - // Set queue as running - self._running.set(true); - } - - // Make sure that we use all available resources - if (self._running.value) { - // Call next to start up the queue - self.next(null); - } - - } - }; - - /** @method PowerQueue.prototype.add - * @param {any} data The task to be handled - * @param {number} [failures] Used internally to Pass on number of failures. - */ - PowerQueue.prototype.add = function(data, failures, id) { - var self = this; - - // Assign new id to task - var assignNewId = self._jumpOnFailure || typeof id === 'undefined'; - - // Set the task id - var taskId = (assignNewId) ? self._maxLength.value + 1 : id; - - // self.invocations.add({ _id: currentId, data: data, failures: failures || 0 }, reversed); - self.invocations.insert(taskId, { _id: taskId, data: data, failures: failures || 0 }); - - // If we assigned new id then increase length - if (assignNewId) self._maxLength.inc(); - - self._autoStartTasks(); - }; - - /** @method PowerQueue.prototype.updateThrottleUp - * @private - * - * Calling this method will update the throttle on the queue adding tasks. - * - * > Note: Currently we only support the PowerQueue - but we could support - * > a more general interface for pauseable tasks or other usecases. - */ - PowerQueue.prototype.updateThrottleUp = function() { - var self = this; - - // How many additional tasks can we handle? - var availableSlots = self._maxProcessing.value - self._isProcessing.value; - // If we can handle more, we have more, we're running, and we're not paused - if (!self._paused.value && self._running.value && availableSlots > 0 && self.invocations._length > 0) { - // Increase counter of current number of tasks being processed - self._isProcessing.inc(); - // Run task - self.runTask(self.invocations.getFirstItem()); - // Repeat recursively; this is better than a for loop to avoid blocking the UI - self.updateThrottleUp(); - } - - }; - - /** @method PowerQueue.prototype.updateThrottleDown - * @private - * - * Calling this method will update the throttle on the queue pause tasks. - * - * > Note: Currently we only support the PowerQueue - but we could support - * > a more general interface for pauseable tasks or other usecases. - */ - PowerQueue.prototype.updateThrottleDown = function() { - var self = this; - // Calculate the differece between acutuall processing tasks and target - var diff = self._isProcessing.value - self._maxProcessing.value; - - // If the diff is more than 0 then we have many tasks processing. - if (diff > 0) { - // We pause the latest added tasks - self._processList.forEachReverse(function(data) { - if (diff > 0 && data.queue instanceof PowerQueue) { - diff--; - // We dont mind calling pause on multiple times on each task - // theres a simple check going on preventing any duplicate actions - data.queue.pause(); - } - }, true); - } - }; - - /** @method PowerQueue.prototype.next - * @param {string} [err] Error message if task failed - * > * Can pass in `null` to start the queue - * > * Passing in a string to `next` will trigger a failure - * > * Passing nothing will simply let the next task run - * `next` is handed into the [taskHandler](PowerQueue.taskHandler) as a - * callback to mark an error or end of current task - */ - PowerQueue.prototype.next = function(err) { - var self = this; - // Primary concern is to throttle up because we are either: - // 1. Starting the queue - // 2. Starting next task - // - // This function does not shut down running tasks - self.updateThrottleUp(); - - // We are running, no tasks are being processed even we just updated the - // throttle up and we got no errors. - // 1. We are paused and releasing tasks - // 2. We are done - if (self._running.value && self._isProcessing.value === 0 && err !== null) { - - // We have no tasks processing so this queue is now releasing resources - // this could be that the queue is paused or stopped, in that case the - // self.invocations._length would be > 0 - // If on the other hand the self.invocations._length is 0 then we have no more - // tasks in the queue so the queue has ended - self.onRelease(self.invocations._length); - - if (!self.invocations._length) { // !self._paused.value && - // Check if queue is done working - // Stop the queue - self._running.set(false); - // self.invocations.reset(); // This should be implicit - self.onEnded(); - } - - } - }; - - /** @callback done - * @param {Meteor.Error | Error | String | null} [feedback] This allows the task to communicate with the queue - * - * Explaination of `feedback` - * * `Meteor.Error` This means that the task failed in a controlled manner and is allowed to rerun - * * `Error` This will throw the passed error - as its an unitended error - * * `null` The task is not done yet, rerun later - * * `String` The task can perform certain commands on the queue - * * "pause" - pause the queue - * * "stop" - stop the queue - * * "reset" - reset the queue - * * "cancel" - cancel the queue - * - */ - - - /** @method PowerQueue.prototype.runTaskDone - * @private - * @param {Meteor.Error | Error | String | null} [feedback] This allows the task to communicate with the queue - * @param {object} invocation - * - * > Note: `feedback` is explained in [Done callback](#done) - * - */ - // Rig the callback function - PowerQueue.prototype.runTaskDone = function(feedback, invocation) { - var self = this; - - // If the task handler throws an error then add it to the queue again - // we allow this for a max of self._maxFailures - // If the error is null then we add the task silently back into the - // microQueue in reverse... This could be due to pause or throttling - if (feedback instanceof Meteor.Error) { - // We only count failures if maxFailures are above 0 - if (self._maxFailures.value > 0) invocation.failures++; - self._failures.inc(); - - // If the user has set the debug flag we print out failures/errors - self.debug && console.error('Error: "' + self.title + '" ' + feedback.message + ', ' + feedback.stack); - - if (invocation.failures < self._maxFailures.value) { - // Add the task again with the increased failures - self.add(invocation.data, invocation.failures, invocation._id); - } else { - self._errors.inc(); - self.errorHandler(invocation.data, self.add, invocation.failures); - } - - // If a error is thrown we assume its not intended - } else if (feedback instanceof Error) throw feedback; - - if (feedback) - - // We use null to throttle pauseable tasks - if (feedback === null) { - // We add this task into the queue, no questions asked - self.invocations.insert(invocation._id, { data: invocation.data, failures: invocation.failures, _id: invocation._id }); - } - - // If the user returns a string we got a command - if (feedback === ''+feedback) { - var command = { - 'pause': function() { self.pause(); }, - 'stop': function() { self.stop(); }, - 'reset': function() { self.reset(); }, - 'cancel': function() { self.cancel(); }, - }; - if (typeof command[feedback] === 'function') { - // Run the command on this queue - command[feedback](); - } else { - // We dont recognize this command, throw an error - throw new Error('Unknown queue command "' + feedback + '"'); - } - } - // Decrease the number of tasks being processed - // make sure we dont go below 0 - if (self._isProcessing.value > 0) self._isProcessing.dec(); - // Task has ended we remove the task from the process list - self._processList.remove(invocation._id); - - invocation.data = null; - invocation.failures = null; - invocation._id = null; - invocation = null; - delete invocation; - // Next task - Meteor.setTimeout(function() { - self.next(); - }, 0); - - }; - - - /** @method PowerQueue.prototype.runTask - * @private // This is not part of the open api - * @param {object} invocation The object stored in the micro-queue - */ - PowerQueue.prototype.runTask = function(invocation) { - var self = this; - - // We start the fitting task handler - // Currently we only support the PowerQueue but we could have a more general - // interface for tasks that allow throttling - try { - if (invocation.data instanceof PowerQueue) { - - // Insert PowerQueue into process list - self._processList.insert(invocation._id, { id: invocation._id, queue: invocation.data }); - // Handle task - self.queueTaskHandler(invocation.data, function subQueueCallbackDone(feedback) { - self.runTaskDone(feedback, invocation); - }, invocation.failures); - - } else { - - // Insert task into process list - self._processList.insert(invocation._id, invocation.data); - // Handle task - self.taskHandler(invocation.data, function taskCallbackDone(feedback) { - self.runTaskDone(feedback, invocation); - }, invocation.failures); - - } - } catch(err) { - throw new Error('Error while running taskHandler for queue, Error: ' + err.message); - } - }; - - /** @method PowerQueue.prototype.queueTaskHandler - * This method handles tasks that are sub queues - */ - PowerQueue.prototype.queueTaskHandler = function(subQueue, next, failures) { - var self = this; - // Monitor sub queue task releases - subQueue.onRelease = function(remaining) { - // Ok, we were paused - this could be throttling so we respect this - // So when the queue is halted we add it back into the main queue - if (remaining > 0) { - // We get out of the queue but dont repport error and add to run later - next(null); - } else { - // Queue has ended - // We simply trigger next task when the sub queue is complete - next(); - // When running subqueues it doesnt make sense to track failures and retry - // the sub queue - this is sub queue domain - } - }; - - // Start the queue - subQueue.run(); - }; - - /** @callback PowerQueue.prototype.taskHandler - * @param {any} data This can be data or functions - * @param {function} next Function `next` call this to end task - * @param {number} failures Number of failures on this task - * - * Default task handler expects functions as data: - * ```js - * self.taskHandler = function(data, next, failures) { - * // This default task handler expects invocation to be a function to run - * if (typeof data !== 'function') { - * throw new Error('Default task handler expects a function'); - * } - * try { - * // Have the function call next - * data(next, failures); - * } catch(err) { - * // Throw to fail this task - * next(err); - * } - * }; - * ``` - */ - - // Can be overwrittin by the user - PowerQueue.prototype.taskHandler = function(data, next, failures) { - var self = this; - // This default task handler expects invocation to be a function to run - if (typeof data !== 'function') { - throw new Error('Default task handler expects a function'); - } - try { - // Have the function call next - data(next, failures); - } catch(err) { - // Throw to fail this task - next(err); - } - }; - - /** @callback PowerQueue.prototype.errorHandler - * @param {any} data This can be data or functions - * @param {function} addTask Use this function to insert the data into the queue again - * @param {number} failures Number of failures on this task - * - * The default callback: - * ```js - * var foo = new PowerQueue(); - * - * // Overwrite the default action - * foo.errorHandler = function(data, addTask, failures) { - * // This could be overwritten the data contains the task data and addTask - * // is a helper for adding the task to the queue - * // try again: addTask(data); - * // console.log('Terminate at ' + failures + ' failures'); - * }; - * ``` - */ - PowerQueue.prototype.errorHandler = function(data, addTask, failures) { - var self = this; - // This could be overwritten the data contains the task data and addTask - // is a helper for adding the task to the queue - // try again: addTask(data); - self.debug && console.log('Terminate at ' + failures + ' failures'); - }; - - /** @method PowerQueue.prototype.pause Pause the queue - * @todo We should have it pause all processing tasks - */ - PowerQueue.prototype.pause = function() { - var self = this; - if (!self._paused.value) { - - self._paused.set(true); - // Loop through the processing tasks and pause these - self._processList.forEach(function(data) { - if (data.queue instanceof PowerQueue) { - // Pause the sub queue - data.queue.pause(); - } - }, true); - - // Trigger callback - self.onPaused(); - } - }; - - /** @method PowerQueue.prototype.resume Start a paused queue - * @todo We should have it resume all processing tasks - * - * > This will not start a stopped queue - */ - PowerQueue.prototype.resume = function() { - var self = this; - self.run(); - }; - - /** @method PowerQueue.prototype.run Starts the queue - * > Using this command will resume a paused queue and will - * > start a stopped queue. - */ - PowerQueue.prototype.run = function() { - var self = this; - //not paused and already running or queue empty or paused subqueues - if (!self._paused.value && self._running.value || !self.invocations._length) { - return; - } - - self._paused.set(false); - self._running.set(true); - self.next(null); - }; - - /** @method PowerQueue.prototype.stop Stops the queue - */ - PowerQueue.prototype.stop = function() { - var self = this; - self._running.set(false); - }; - - /** @method PowerQueue.prototype.cancel Cancel the queue - */ - PowerQueue.prototype.cancel = function() { - var self = this; - self.reset(); - }; - diff --git a/packages/wekan-cfs-power-queue/spinal-queue.spec.md b/packages/wekan-cfs-power-queue/spinal-queue.spec.md deleted file mode 100644 index cb2e50eb1..000000000 --- a/packages/wekan-cfs-power-queue/spinal-queue.spec.md +++ /dev/null @@ -1,151 +0,0 @@ -#Spinal Queue Spec -This specification declares the interface for the "spinal" queue in `PowerQueue`. -We allready have two implementations the [MicroQueue](https://github.com/zcfs/Meteor-micro-queue) and [ReactiveList](https://github.com/zcfs/Meteor-reactive-list) - -#SpinalQueue -Provides a simple reactive list interface - -#### new SpinalQueue(lifo)  Anywhere #### -- - -__Arguments__ - -* __lifo__ *{boolean}* -Set the order of the queue default is `fifo` - -- -Example: -```js - var list = new SpinalQueue(); - list.insert(1, { text: 'Hello id: 1' }); - list.insert(2, { text: 'Hello id: 2' }); - list.insert(3, { text: 'Hello id: 3' }); - list.update(2, { text: 'Updated 2'}); - list.remove(1); - - list.forEach(function(value, key) { - console.log('GOT: ' + value.text); - }, true); // Set noneReactive = true, default behaviour is reactive - // Return from Template: - Template.hello.list = function() { - return list.fetch(); - }; -``` - -- - -#### *SpinalQueue*.length()  Anywhere #### -- -*This method __length__ is defined in `SpinalQueue`* - -__Returns__ *{number}* __(is reactive)__ -Length of the reactive list - -- - -#### *SpinalQueue*.reset()  Anywhere #### -- -*This method __reset__ is defined in `SpinalQueue`* - -- - -#### *SpinalQueue*.update(key, value)  Anywhere #### -- -*This method __update__ is defined in `SpinalQueue`* - -__Arguments__ - -* __key__ *{string|number}* -Key to update -* __value__ *{any}* -Update with this value - -> Note: Method is currently not used by `PowerQueue` - -- - -#### *SpinalQueue*.insert(key, value)  Anywhere #### -- -*This method __insert__ is defined in `SpinalQueue`* - -__Arguments__ - -* __key__ *{string|number}* -Key to insert -* __value__ *{any}* -Insert item with this value - -- - -#### *SpinalQueue*.remove(key)  Anywhere #### -- -*This method __remove__ is defined in `SpinalQueue`* - -__Arguments__ - -* __key__ *{string|number}* -Key to remove - -- - -#### *SpinalQueue*.getLastItem()  Anywhere #### -- -*This method __getLastItem__ is defined in `SpinalQueue`* - -__Returns__ *{any}* -Pops last item from the list - removes the item from the list - -> Note: Method is currently not used by `PowerQueue` - -- - -#### *SpinalQueue*.getFirstItem()  Anywhere #### -- -*This method __getFirstItem__ is defined in `SpinalQueue`* - -__Returns__ *{any}* -Pops first item from the list - removes the item from the list - - -#### *SpinalQueue*.forEach(f, [noneReactive], [reverse])  Anywhere #### -- -*This method __forEach__ is defined in `SpinalQueue`* - -__Arguments__ - -* __f__ *{function}* -Callback `funciton(value, key)` -* __noneReactive__ *{boolean}* (Optional = false) -Set true if want to disable reactivity - -- - - -#### *SpinalQueue*.forEachReverse(f, [noneReactive])  Anywhere #### -- -*This method __forEachReverse__ is defined in `SpinalQueue`* - -__Arguments__ - -* __f__ *{function}* -Callback `funciton(value, key)` -* __noneReactive__ *{boolean}* (Optional = false) -Set true if want to disable reactivity - -- - -#### *SpinalQueue*.fetch([noneReactive])  Anywhere #### -- -*This method __fetch__ is defined in `SpinalQueue`* - -__Arguments__ - -* __noneReactive__ *{boolean}* (Optional = false) -Set true if want to disable reactivity - -- - -__Returns__ *{array}* __(is reactive)__ -List of items - -- diff --git a/packages/wekan-cfs-power-queue/tests.js b/packages/wekan-cfs-power-queue/tests.js deleted file mode 100644 index 01cdd6b1f..000000000 --- a/packages/wekan-cfs-power-queue/tests.js +++ /dev/null @@ -1,198 +0,0 @@ -"use strict"; - -function equals(a, b) { - return !!(JSON.stringify(a) === JSON.stringify(b)); -} - -Tinytest.add('PowerQueue - scope', function(test) { - - test.isTrue(typeof PowerQueue !== 'undefined', 'The PowerQueue scope is missing, please add the power-queue package'); - - -}); - - -// We run 5 tasks in serial mode -Tinytest.addAsync('PowerQueue - test serial run', function (test, onComplete) { - var queue = new PowerQueue({ - name: 'test queue 1', - autostart: false, - maxProcessing: 1, - debug: true, - // When this task is released we do our tests - onEnded: function() { - console.log('It ended'); - // Check that we ran the expected number of tasks - test.equal(counter, 5, 'counter did not match number of tasks'); - // Check that the result was correct - test.equal(result, expectedResult, 'result was unexpected'); - // We are done testing - onComplete(); - } - }); - - var result = ''; - var expectedResult = '12345'; - var counter = 0; - - var checkCounter = function(id, next) { - console.log('test queue 1 - Run task: ' + id); - // Keep a counter - counter++; - // push id to result - result += id; - // call next task - next(); - }; - - - // Add the tasks to the queue - queue.add(function(next) { checkCounter('1', next); }); - queue.add(function(next) { checkCounter('2', next); }); - queue.add(function(next) { checkCounter('3', next); }); - queue.add(function(next) { checkCounter('4', next); }); - queue.add(function(next) { checkCounter('5', next); }); - - // Run the queue - queue.run(); -}); - -// We run 5 tasks in serial mode but pause the queue on 3 -Tinytest.addAsync('PowerQueue - test serial pause', function (test, onComplete) { - var queue = new PowerQueue({ - name: 'test queue 2', - autostart: false, - maxProcessing: 1, - debug: true, - // When this task is released we do our tests - onPaused: function() { - console.log('Its paused'); - // Check that we ran the expected number of tasks - test.equal(counter, 3, 'counter did not match number of tasks'); - // Check that the result was correct - test.equal(result, expectedResult, 'result was unexpected'); - // We are done testing - onComplete(); - } - }); - - var result = ''; - var expectedResult = '123'; - var counter = 0; - - var checkCounter = function(id, next) { - console.log('test queue 2 - Run task: ' + id); - // Keep a counter - counter++; - // push id to result - result += id; - // call next task - if (id === '3') - next('pause') - else - next(); - }; - - - // Add the tasks to the queue - queue.add(function(next) { checkCounter('1', next); }); - queue.add(function(next) { checkCounter('2', next); }); - queue.add(function(next) { checkCounter('3', next); }); - queue.add(function(next) { checkCounter('4', next); }); - queue.add(function(next) { checkCounter('5', next); }); - - // Run the queue - queue.run(); -}); - -// We run 5 tasks in serial mode but pause the queue on 3 -Tinytest.addAsync('PowerQueue - test 2 task in parallel', function (test, onComplete) { - var queue = new PowerQueue({ - name: 'test queue 3', - autostart: false, - maxProcessing: 2, - debug: true, - // When this task is released we do our tests - onEnded: function() { - console.log('Its paused'); - // Check that we ran the expected number of tasks - test.equal(counter, 10, 'counter did not match number of tasks'); - // Check that the result was correct - test.equal(result, expectedResult, 'result was unexpected'); - // We are done testing - onComplete(); - } - }); - - // start 1-----3-------4-------6------------------------9-----------------------X - // 2-----------------5---------------7--------8-----------10------X - // ms 0 5 10 15 20 25 30 35 40 45 50 55 60 65 70 75 80 85 90 95 100 - // result 1 2 3 4 5 6 7 8 9 10 - // result 1 3 2 4 5 7 6 8 10 9 - - var wait = { - '1': 10, - '2': 25, - '3': 10, - '4': 10, - '5': 20, - '6': 30, - '7': 10, - '8': 15, - '9': 30, - '10': 10, - }; - - // 1324 - - var result = ''; - var expectedResult = '13245768109'; - var counter = 0; - - var checkCounter = function(id, next) { - console.log('test queue 3 - Run task: ' + id); - // Keep a counter - counter++; - // push id to result - Meteor.setTimeout(function() { - result += id; - // call next task - next(); - }, wait[id] * 5); // give it a factor 2 to make sure we get the correct result - }; - - - // Add the tasks to the queue - queue.add(function(next) { checkCounter('1', next); }); - queue.add(function(next) { checkCounter('2', next); }); - queue.add(function(next) { checkCounter('3', next); }); - queue.add(function(next) { checkCounter('4', next); }); - queue.add(function(next) { checkCounter('5', next); }); - queue.add(function(next) { checkCounter('6', next); }); - queue.add(function(next) { checkCounter('7', next); }); - queue.add(function(next) { checkCounter('8', next); }); - queue.add(function(next) { checkCounter('9', next); }); - queue.add(function(next) { checkCounter('10', next); }); - - // Run the queue - queue.run(); -}); -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equal(actual, expected, message, not) -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-reactive-list/.editorconfig b/packages/wekan-cfs-reactive-list/.editorconfig deleted file mode 100644 index a2cc1c1fe..000000000 --- a/packages/wekan-cfs-reactive-list/.editorconfig +++ /dev/null @@ -1,18 +0,0 @@ -# .editorconfig -# Meteor adapted EditorConfig, http://EditorConfig.org -# By RaiX 2013 - -root = true - -[*.js] -end_of_line = lf -insert_final_newline = true -indent_style = space -indent_size = 2 -trim_trailing_whitespace = true -charset = utf-8 -max_line_length = 80 -indent_brace_style = 1TBS -spaces_around_operators = true -quote_type = auto -# curly_bracket_next_line = true \ No newline at end of file diff --git a/packages/wekan-cfs-reactive-list/.gitignore b/packages/wekan-cfs-reactive-list/.gitignore deleted file mode 100644 index 45353da68..000000000 --- a/packages/wekan-cfs-reactive-list/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/versions.json -.build* diff --git a/packages/wekan-cfs-reactive-list/.jshintrc b/packages/wekan-cfs-reactive-list/.jshintrc deleted file mode 100644 index 3f0dbcc61..000000000 --- a/packages/wekan-cfs-reactive-list/.jshintrc +++ /dev/null @@ -1,115 +0,0 @@ -//.jshintrc -{ - // JSHint Meteor Configuration File - // Match the Meteor Style Guide - // - // By @raix with contributions from @aldeed and @awatson1978 - // Source https://github.com/raix/Meteor-jshintrc - // - // See http://jshint.com/docs/ for more details - - "maxerr" : 50, // {int} Maximum error before stopping - - // Enforcing - "bitwise" : true, // true: Prohibit bitwise operators (&, |, ^, etc.) - "camelcase" : true, // true: Identifiers must be in camelCase - "curly" : true, // true: Require {} for every new block or scope - "eqeqeq" : true, // true: Require triple equals (===) for comparison - "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty() - "immed" : false, // true: Require immediate invocations to be wrapped in parens e.g. `(function () { } ());` - "indent" : 2, // {int} Number of spaces to use for indentation - "latedef" : false, // true: Require variables/functions to be defined before being used - "newcap" : false, // true: Require capitalization of all constructor functions e.g. `new F()` - "noarg" : true, // true: Prohibit use of `arguments.caller` and `arguments.callee` - "noempty" : true, // true: Prohibit use of empty blocks - "nonew" : false, // true: Prohibit use of constructors for side-effects (without assignment) - "plusplus" : false, // true: Prohibit use of `++` & `--` - "quotmark" : false, // Quotation mark consistency: - // false : do nothing (default) - // true : ensure whatever is used is consistent - // "single" : require single quotes - // "double" : require double quotes - "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks) - "unused" : true, // true: Require all defined variables be used - "strict" : true, // true: Requires all functions run in ES5 Strict Mode - "trailing" : true, // true: Prohibit trailing whitespaces - "maxparams" : false, // {int} Max number of formal params allowed per function - "maxdepth" : false, // {int} Max depth of nested blocks (within functions) - "maxstatements" : false, // {int} Max number statements per function - "maxcomplexity" : false, // {int} Max cyclomatic complexity per function - "maxlen" : 80, // {int} Max number of characters per line - - // Relaxing - "asi" : false, // true: Tolerate Automatic Semicolon Insertion (no semicolons) - "boss" : false, // true: Tolerate assignments where comparisons would be expected - "debug" : false, // true: Allow debugger statements e.g. browser breakpoints. - "eqnull" : false, // true: Tolerate use of `== null` - "es5" : false, // true: Allow ES5 syntax (ex: getters and setters) - "esnext" : false, // true: Allow ES.next (ES6) syntax (ex: `const`) - "moz" : false, // true: Allow Mozilla specific syntax (extends and overrides esnext features) - // (ex: `for each`, multiple try/catch, function expression…) - "evil" : false, // true: Tolerate use of `eval` and `new Function()` - "expr" : false, // true: Tolerate `ExpressionStatement` as Programs - "funcscope" : false, // true: Tolerate defining variables inside control statements" - "globalstrict" : true, // true: Allow global "use strict" (also enables 'strict') - "iterator" : false, // true: Tolerate using the `__iterator__` property - "lastsemic" : false, // true: Tolerate omitting a semicolon for the last statement of a 1-line block - "laxbreak" : false, // true: Tolerate possibly unsafe line breakings - "laxcomma" : false, // true: Tolerate comma-first style coding - "loopfunc" : false, // true: Tolerate functions being defined in loops - "multistr" : false, // true: Tolerate multi-line strings - "proto" : false, // true: Tolerate using the `__proto__` property - "scripturl" : false, // true: Tolerate script-targeted URLs - "smarttabs" : false, // true: Tolerate mixed tabs/spaces when used for alignment - "shadow" : false, // true: Allows re-define variables later in code e.g. `var x=1; x=2;` - "sub" : false, // true: Tolerate using `[]` notation when it can still be expressed in dot notation - "supernew" : false, // true: Tolerate `new function () { ... };` and `new Object;` - "validthis" : false, // true: Tolerate using this in a non-constructor function - - // Environments - "browser" : true, // Web Browser (window, document, etc) - "couch" : false, // CouchDB - "devel" : true, // Development/debugging (alert, confirm, etc) - "dojo" : false, // Dojo Toolkit - "jquery" : false, // jQuery - "mootools" : false, // MooTools - "node" : false, // Node.js - "nonstandard" : false, // Widely adopted globals (escape, unescape, etc) - "prototypejs" : false, // Prototype and Scriptaculous - "rhino" : false, // Rhino - "worker" : false, // Web Workers - "wsh" : false, // Windows Scripting Host - "yui" : false, // Yahoo User Interface - //"meteor" : false, // Meteor.js - - // Legacy - "nomen" : false, // true: Prohibit dangling `_` in variables - "onevar" : false, // true: Allow only one `var` statement per function - "passfail" : false, // true: Stop on first error - "white" : false, // true: Check against strict whitespace and indentation rules - - // Custom Globals - "predef" : [ - "Meteor", - "Accounts", - "Session", - "Template", - "check", - "Match", - "Deps", - "EJSON", - "Email", - "Package", - "Tinytest", - "Npm", - "Assets", - "Packages", - "process", - "GroundDB", - "_gDB", - "LocalCollection", - "ReactiveList", - "_", - "Random" - ] // additional predefined global variables -} diff --git a/packages/wekan-cfs-reactive-list/.travis.yml b/packages/wekan-cfs-reactive-list/.travis.yml deleted file mode 100644 index 6a4640033..000000000 --- a/packages/wekan-cfs-reactive-list/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - "0.10" -before_install: - - "curl -L http://git.io/s0Zu-w | /bin/sh" \ No newline at end of file diff --git a/packages/wekan-cfs-reactive-list/LICENSE.md b/packages/wekan-cfs-reactive-list/LICENSE.md deleted file mode 100644 index 2a5c5339e..000000000 --- a/packages/wekan-cfs-reactive-list/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 [@raix](https://github.com/raix), aka Morten N.O. Nørgaard Henriksen, mh@gi-software.com - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/wekan-cfs-reactive-list/README.md b/packages/wekan-cfs-reactive-list/README.md deleted file mode 100644 index a05b0f7d8..000000000 --- a/packages/wekan-cfs-reactive-list/README.md +++ /dev/null @@ -1,82 +0,0 @@ -wekan-cfs-reactive-list [![Build Status](https://travis-ci.org/CollectionFS/Meteor-reactive-list.png?branch=master)](https://travis-ci.org/CollectionFS/Meteor-reactive-list) -========= - -~~Looking for maintainers - please reach out!~~ -This package is to be archived due to inability to find contributors, thanks to everyone who helped make it possible. - -**If you're looking for an alternative, we highly recommend [Meteor-Files](https://github.com/VeliovGroup/Meteor-Files) by [VeliovGroup](https://github.com/VeliovGroup)** - ---- - -ReactiveList keeps a sortable reactive list of key+value items. It's simple and fast. - -And... It's powered by Meteor's reactive sugar :) - -Kind regards, -Eric (@aldeed) and Morten (@raix) - -Happy coding!! - -#API -[API Documentation](api.md) - -From the docs: -#### new ReactiveList([options], sort)  Anywhere #### -- - -__Arguments__ - -* __options__ *{object}* (Optional) -* __sort__ *{function}* -The sort algorithm to use - -- -Example: -```js - var list = new ReactiveList(); - list.insert(1, { text: 'Hello id: 1' }); - list.insert(2, { text: 'Hello id: 2' }); - list.insert(3, { text: 'Hello id: 3' }); - list.update(2, { text: 'Updated 2'}); - list.remove(1); - - list.forEach(function(value, key) { - console.log('GOT: ' + value.text); - }, true); // Set noneReactive = true, default behaviour is reactive - // Return from Template: - Template.hello.list = function() { - return list.fetch(); - }; -``` - -#### Example of a sort algorithm -Sort can be used to define the order of the list -```js - var list = new ReactiveList({ - sort: function(a, b) { - // a and b are type of { key, value } - // here we sort by the key: - return a.key < b.key; - } - }); -``` -### Object chain -``` - first last - undefined - obj - obj - obj - undefined - (prev value next) (prev value next) (prev value next) -``` - -``` -ReactiveList = function(options) { ... -``` - -See more at [reactive-list.js:46](reactive-list.js#L46). - -# Contribute - -Here's the [complete API documentation](internal.api.md). To update the docs, run `npm install docmeteor`, then - -```bash -$ docmeteor -``` diff --git a/packages/wekan-cfs-reactive-list/api.md b/packages/wekan-cfs-reactive-list/api.md deleted file mode 100644 index 0f7eaa5a3..000000000 --- a/packages/wekan-cfs-reactive-list/api.md +++ /dev/null @@ -1,195 +0,0 @@ -#ReactiveList -Provides a simple reactive list interface - -#### new ReactiveList([options], sort)  Anywhere #### -- - -__Arguments__ - -* __options__ *{object}* (Optional) -* __sort__ *{function}* -The sort algorithm to use - -- -Example: -```js - var list = new ReactiveList(); - list.insert(1, { text: 'Hello id: 1' }); - list.insert(2, { text: 'Hello id: 2' }); - list.insert(3, { text: 'Hello id: 3' }); - list.update(2, { text: 'Updated 2'}); - list.remove(1); - - list.forEach(function(value, key) { - console.log('GOT: ' + value.text); - }, true); // Set noneReactive = true, default behaviour is reactive - // Return from Template: - Template.hello.list = function() { - return list.fetch(); - }; -``` -####Example of a sort algorithm -Sort can be used to define the order of the list -```js - var list = new ReactiveList({ - sort: function(a, b) { - // a and b are type of { key, value } - // here we sort by the key: - return a.key < b.key; - } - }); -``` -###Object chain -``` - first last - undefined - obj - obj - obj - undefined - (prev value next) (prev value next) (prev value next) -``` - -> ```ReactiveList = function(options) { ...``` [reactive-list.js:46](reactive-list.js#L46) - -- - -#### *reactivelist*.length()  Anywhere #### -- -*This method __length__ is defined in `prototype` of `ReactiveList`* - -__Returns__ *{number}* __(is reactive)__ -Length of the reactive list - -> ```ReactiveList.prototype.length = function() { ...``` [reactive-list.js:73](reactive-list.js#L73) - -- - -#### *reactivelist*.reset()  Anywhere #### -- -*This method __reset__ is defined in `prototype` of `ReactiveList`* - -> ```ReactiveList.prototype.reset = function() { ...``` [reactive-list.js:83](reactive-list.js#L83) - -- - -#### *reactivelist*.update(key, value)  Anywhere #### -- -*This method __update__ is defined in `prototype` of `ReactiveList`* - -__Arguments__ - -* __key__ *{string|number}* -Key to update -* __value__ *{any}* -Update with this value - -- - -> ```ReactiveList.prototype.update = function(key, value) { ...``` [reactive-list.js:102](reactive-list.js#L102) - -- - -#### *reactivelist*.insert(key, value)  Anywhere #### -- -*This method __insert__ is defined in `prototype` of `ReactiveList`* - -__Arguments__ - -* __key__ *{string|number}* -Key to insert -* __value__ *{any}* -Insert item with this value - -- - -> ```ReactiveList.prototype.insert = function(key, value) { ...``` [reactive-list.js:118](reactive-list.js#L118) - -- - -#### *reactivelist*.remove(key)  Anywhere #### -- -*This method __remove__ is defined in `prototype` of `ReactiveList`* - -__Arguments__ - -* __key__ *{string|number}* -Key to remove - -- - -> ```ReactiveList.prototype.remove = function(key) { ...``` [reactive-list.js:180](reactive-list.js#L180) - -- - -#### *reactivelist*.getLastItem()  Anywhere #### -- -*This method __getLastItem__ is defined in `prototype` of `ReactiveList`* - -__Returns__ *{any}* -Pops last item from the list - removes the item from the list - -> ```ReactiveList.prototype.getLastItem = function(first) { ...``` [reactive-list.js:221](reactive-list.js#L221) - -- - -#### *reactivelist*.getFirstItem()  Anywhere #### -- -*This method __getFirstItem__ is defined in `prototype` of `ReactiveList`* - -__Returns__ *{any}* -Pops first item from the list - removes the item from the list - -> ```ReactiveList.prototype.getFirstItem = function() { ...``` [reactive-list.js:239](reactive-list.js#L239) - -- - -#### *reactivelist*.forEach(f, [noneReactive], [reverse])  Anywhere #### -- -*This method __forEach__ is defined in `prototype` of `ReactiveList`* - -__Arguments__ - -* __f__ *{function}* -Callback `funciton(value, key)` -* __noneReactive__ *{boolean}* (Optional = false) -Set true if want to disable reactivity -* __reverse__ *{boolean}* (Optional = false) -Set true to reverse iteration `forEachReverse` - -- - -> ```ReactiveList.prototype.forEach = function(f, noneReactive, reverse) { ...``` [reactive-list.js:249](reactive-list.js#L249) - -- - -#### *reactivelist*.forEachReverse(f, [noneReactive])  Anywhere #### -- -*This method __forEachReverse__ is defined in `prototype` of `ReactiveList`* - -__Arguments__ - -* __f__ *{function}* -Callback `funciton(value, key)` -* __noneReactive__ *{boolean}* (Optional = false) -Set true if want to disable reactivity - -- - -> ```ReactiveList.prototype.forEachReverse = function(f, noneReactive) { ...``` [reactive-list.js:272](reactive-list.js#L272) - -- - -#### *reactivelist*.fetch([noneReactive])  Anywhere #### -- -*This method __fetch__ is defined in `prototype` of `ReactiveList`* - -__Arguments__ - -* __noneReactive__ *{boolean}* (Optional = false) -Set true if want to disable reactivity - -- - -__Returns__ *{array}* __(is reactive)__ -List of items - -> ```ReactiveList.prototype.fetch = function(noneReactive) { ...``` [reactive-list.js:282](reactive-list.js#L282) - -- diff --git a/packages/wekan-cfs-reactive-list/internal.api.md b/packages/wekan-cfs-reactive-list/internal.api.md deleted file mode 100644 index 3eb92996d..000000000 --- a/packages/wekan-cfs-reactive-list/internal.api.md +++ /dev/null @@ -1,203 +0,0 @@ -> File: ["reactive-list.js"](reactive-list.js) -> Where: {client|server} - -- -#ReactiveList -Provides a simple reactive list interface - -#### new ReactiveList([options], sort)  Anywhere #### -- - -__Arguments__ - -* __options__ *{object}* (Optional) -* __sort__ *{function}* -The sort algorithm to use - -- -Example: -```js - var list = new ReactiveList(); - list.insert(1, { text: 'Hello id: 1' }); - list.insert(2, { text: 'Hello id: 2' }); - list.insert(3, { text: 'Hello id: 3' }); - list.update(2, { text: 'Updated 2'}); - list.remove(1); - - list.forEach(function(value, key) { - console.log('GOT: ' + value.text); - }, true); // Set noneReactive = true, default behaviour is reactive - // Return from Template: - Template.hello.list = function() { - return list.fetch(); - }; -``` -####Example of a sort algorithm -Sort can be used to define the order of the list -```js - var list = new ReactiveList({ - sort: function(a, b) { - // a and b are type of { key, value } - // here we sort by the key: - return a.key < b.key; - } - }); -``` -###Object chain -``` - first last - undefined - obj - obj - obj - undefined - (prev value next) (prev value next) (prev value next) -``` - -> ```ReactiveList = function(options) { ...``` [reactive-list.js:46](reactive-list.js#L46) - -- - -#### *reactivelist*.length()  Anywhere #### -- -*This method __length__ is defined in `prototype` of `ReactiveList`* - -__Returns__ *{number}* __(is reactive)__ -Length of the reactive list - -> ```ReactiveList.prototype.length = function() { ...``` [reactive-list.js:73](reactive-list.js#L73) - -- - -#### *reactivelist*.reset()  Anywhere #### -- -*This method __reset__ is defined in `prototype` of `ReactiveList`* -__TODO__ -``` -* Check for memory leaks, if so we have to iterate over lookup and delete the items -``` - -> ```ReactiveList.prototype.reset = function() { ...``` [reactive-list.js:83](reactive-list.js#L83) - -- - -#### *reactivelist*.update(key, value)  Anywhere #### -- -*This method __update__ is defined in `prototype` of `ReactiveList`* - -__Arguments__ - -* __key__ *{string|number}* -Key to update -* __value__ *{any}* -Update with this value - -- - -> ```ReactiveList.prototype.update = function(key, value) { ...``` [reactive-list.js:102](reactive-list.js#L102) - -- - -#### *reactivelist*.insert(key, value)  Anywhere #### -- -*This method __insert__ is defined in `prototype` of `ReactiveList`* - -__Arguments__ - -* __key__ *{string|number}* -Key to insert -* __value__ *{any}* -Insert item with this value - -- - -> ```ReactiveList.prototype.insert = function(key, value) { ...``` [reactive-list.js:118](reactive-list.js#L118) - -- - -#### *reactivelist*.remove(key)  Anywhere #### -- -*This method __remove__ is defined in `prototype` of `ReactiveList`* - -__Arguments__ - -* __key__ *{string|number}* -Key to remove - -- - -> ```ReactiveList.prototype.remove = function(key) { ...``` [reactive-list.js:180](reactive-list.js#L180) - -- - -#### *reactivelist*.getLastItem()  Anywhere #### -- -*This method __getLastItem__ is defined in `prototype` of `ReactiveList`* - -__Returns__ *{any}* -Pops last item from the list - removes the item from the list - -> ```ReactiveList.prototype.getLastItem = function(first) { ...``` [reactive-list.js:221](reactive-list.js#L221) - -- - -#### *reactivelist*.getFirstItem()  Anywhere #### -- -*This method __getFirstItem__ is defined in `prototype` of `ReactiveList`* - -__Returns__ *{any}* -Pops first item from the list - removes the item from the list - -> ```ReactiveList.prototype.getFirstItem = function() { ...``` [reactive-list.js:239](reactive-list.js#L239) - -- - -#### *reactivelist*.forEach(f, [noneReactive], [reverse])  Anywhere #### -- -*This method __forEach__ is defined in `prototype` of `ReactiveList`* - -__Arguments__ - -* __f__ *{function}* -Callback `funciton(value, key)` -* __noneReactive__ *{boolean}* (Optional = false) -Set true if want to disable reactivity -* __reverse__ *{boolean}* (Optional = false) -Set true to reverse iteration `forEachReverse` - -- - -> ```ReactiveList.prototype.forEach = function(f, noneReactive, reverse) { ...``` [reactive-list.js:249](reactive-list.js#L249) - -- - -#### *reactivelist*.forEachReverse(f, [noneReactive])  Anywhere #### -- -*This method __forEachReverse__ is defined in `prototype` of `ReactiveList`* - -__Arguments__ - -* __f__ *{function}* -Callback `funciton(value, key)` -* __noneReactive__ *{boolean}* (Optional = false) -Set true if want to disable reactivity - -- - -> ```ReactiveList.prototype.forEachReverse = function(f, noneReactive) { ...``` [reactive-list.js:272](reactive-list.js#L272) - -- - -#### *reactivelist*.fetch([noneReactive])  Anywhere #### -- -*This method __fetch__ is defined in `prototype` of `ReactiveList`* - -__Arguments__ - -* __noneReactive__ *{boolean}* (Optional = false) -Set true if want to disable reactivity - -- - -__Returns__ *{array}* __(is reactive)__ -List of items - -> ```ReactiveList.prototype.fetch = function(noneReactive) { ...``` [reactive-list.js:282](reactive-list.js#L282) - -- diff --git a/packages/wekan-cfs-reactive-list/package.js b/packages/wekan-cfs-reactive-list/package.js deleted file mode 100644 index a96928f78..000000000 --- a/packages/wekan-cfs-reactive-list/package.js +++ /dev/null @@ -1,23 +0,0 @@ -Package.describe({ - name: 'wekan-cfs-reactive-list', - version: '0.0.9', - summary: 'ReactiveList provides a small, fast queue/list built for Power-Queue', - git: 'https://github.com/zcfs/Meteor-reactive-list.git' -}); - -Package.onUse(function (api) { - api.versionsFrom('1.0'); - - api.use('deps', ['client', 'server']); - - api.export('ReactiveList'); - api.addFiles(['reactive-list.js'], ['client', 'server']); -}); - -Package.onTest(function (api) { - api.use('wekan-cfs-reactive-list'); - api.use('test-helpers', 'server'); - api.use('tinytest'); - - api.addFiles('tests.js'); -}); diff --git a/packages/wekan-cfs-reactive-list/reactive-list.js b/packages/wekan-cfs-reactive-list/reactive-list.js deleted file mode 100644 index c99434bc4..000000000 --- a/packages/wekan-cfs-reactive-list/reactive-list.js +++ /dev/null @@ -1,313 +0,0 @@ -// #ReactiveList -// Provides a simple reactive list interface -var _noopCallback = function() {}; - -var _nonReactive = { - changed: _noopCallback, - depend: _noopCallback -}; - -/** @method ReactiveList Keeps a reactive list of key+value items - * @constructor - * @namespace ReactiveList - * @param {object} [options] - * @param {function} sort The sort algorithm to use - * @param {boolean} [reactive=true] If set false this list is not reactive - * Example: - * ```js - * var list = new ReactiveList(); - * list.insert(1, { text: 'Hello id: 1' }); - * list.insert(2, { text: 'Hello id: 2' }); - * list.insert(3, { text: 'Hello id: 3' }); - * list.update(2, { text: 'Updated 2'}); - * list.remove(1); - * - * list.forEach(function(value, key) { - * console.log('GOT: ' + value.text); - * }, true); // Set noneReactive = true, default behaviour is reactive - * - * // Return from Template: - * Template.hello.list = function() { - * return list.fetch(); - * }; - * ``` - * - * ####Example of a sort algorithm - * Sort can be used to define the order of the list - * ```js - * var list = new ReactiveList({ - * sort: function(a, b) { - * // a and b are type of { key, value } - * // here we sort by the key: - * return a.key < b.key; - * } - * }); - * ``` - * ###Object chain - * ``` - * first last - * undefined - obj - obj - obj - undefined - * (prev value next) (prev value next) (prev value next) - * ``` - */ -ReactiveList = function(options) { - var self = this; - // Object container - self.lookup = {}; - // Length - self._length = 0; - // First object in list - self.first; - // Last object in list - self.last; - // Set sort to options.sort or default to true (asc) - self.sort = (options && options.sort || function(a, b) { - return a.key < b.key; - }); - - // Allow user to disable reactivity, default true - self.isReactive = (options)? options.reactive !== false : true; - - // If lifo queue - if (options === true || options && options.sort === true) { - self.sort = function(a, b) { return a.key > b.key; }; - } - - // Rig the dependencies - self._listDeps = (self.isReactive)? new Deps.Dependency() : _nonReactive; - - self._lengthDeps = (self.isReactive)? new Deps.Dependency() : _nonReactive; -}; - -/** @method ReactiveList.prototype.length Returns the length of the list - * @reactive - * @returns {number} Length of the reactive list - */ -ReactiveList.prototype.length = function() { - var self = this; - // Make this reactive - self._lengthDeps.depend(); - return self._length; -}; - -/** @method ReactiveList.prototype.reset Reset and empty the list - * @todo Check for memory leaks, if so we have to iterate over lookup and delete the items - */ -ReactiveList.prototype.reset = function() { - var self = this; - // Clear the reference to the first object - self.first = undefined; - // Clear the reference to the last object - self.last = undefined; - // Clear the lookup object - self.lookup = {}; - // Set the length to 0 - self._length = 0; - self._lengthDeps.changed(); - // Invalidate the list - self._listDeps.changed(); -}; - -/** @method ReactiveList.prototype.update - * @param {string|number} key Key to update - * @param {any} value Update with this value - */ -ReactiveList.prototype.update = function(key, value) { - var self = this; - // Make sure the key is found in the list - if (typeof self.lookup[key] === 'undefined') { - throw new Error('Reactive list cannot update, key "' + key + '" not found'); - } - // Set the new value - self.lookup[key].value = value; - // Invalidate the list - self._listDeps.changed(); -}; - -/** @method ReactiveList.prototype.insert - * @param {string|number} key Key to insert - * @param {any} value Insert item with this value - */ -ReactiveList.prototype.insert = function(key, value) { - var self = this; - if (typeof self.lookup[key] !== 'undefined') { - throw new Error('Reactive list could not insert: key "' + key + - '" allready found'); - } - // Create the new item to insert into the list - var newItem = { key: key, value: value }; - // Init current by pointing it at the first object in the list - var current = self.first; - // Init the isInserted flag - var isInserted = false; - - - // Iterate through list while not empty and item is not inserted - while (typeof current !== 'undefined' && !isInserted) { - - // Sort the list by using the sort function - if (self.sort(newItem, current)) { - - // Insert self.lookup[key] before - if (typeof current.prev === 'undefined') { self.first = newItem; } - - // Set the references in the inserted object - newItem.prev = current.prev; - newItem.next = current; - - // Update the two existing objects - if (current.prev) { current.prev.next = newItem; } - current.prev = newItem; - - // Mark the item as inserted - job's done - isInserted = true; - } - // Goto next object - current = current.next; - } - - - if (!isInserted) { - // We append it to the list - newItem.prev = self.last; - if (self.last) { self.last.next = newItem; } - - // Update the last pointing to newItem - self.last = newItem; - // Update first if we are appending to an empty list - if (self._length === 0) { self.first = newItem; } - } - - - // Reference the object for a quick lookup option - self.lookup[key] = newItem; - // Increase length - self._length++; - self._lengthDeps.changed(); - // And invalidate the list - self._listDeps.changed(); -}; - -/** @method ReactiveList.prototype.remove - * @param {string|number} key Key to remove - */ -ReactiveList.prototype.remove = function(key) { - var self = this; - // Get the item object - var item = self.lookup[key]; - - // Check that it exists - if (typeof item === 'undefined') { - return; - // throw new Error('ReactiveList cannot remove item, unknow key "' + key + - // '"'); - } - - // Rig the references - var prevItem = item.prev; - var nextItem = item.next; - - // Update chain prev object next reference - if (typeof prevItem !== 'undefined') { - prevItem.next = nextItem; - } else { - self.first = nextItem; - } - - // Update chain next object prev reference - if (typeof nextItem !== 'undefined') { - nextItem.prev = prevItem; - } else { - self.last = prevItem; - } - - // Clean up - self.lookup[key].last = null; - self.lookup[key].prev = null; - self.lookup[key] = null; - prevItem = null; - - delete self.lookup[key]; - // Decrease the length - self._length--; - self._lengthDeps.changed(); - // Invalidate the list - self._listDeps.changed(); -}; - -/** @method ReactiveList.prototype.getLastItem - * @returns {any} Pops last item from the list - removes the item from the list - */ -ReactiveList.prototype.getLastItem = function(first) { - var self = this; - - // Get the relevant item first or last - var item = (first)?self.first: self.last; - - if (typeof item === 'undefined') { - return; // Empty list - } - // Remove the item from the list - self.remove(item.key); - // Return the value - return item.value; -}; - -/** @method ReactiveList.prototype.getFirstItem - * @returns {any} Pops first item from the list - removes the item from the list - */ -ReactiveList.prototype.getFirstItem = function() { - // This gets the first item... - return this.getLastItem(true); -}; - -/** @method ReactiveList.prototype.forEach - * @param {function} f Callback `funciton(value, key)` - * @param {boolean} [noneReactive=false] Set true if want to disable reactivity - * @param {boolean} [reverse=false] Set true to reverse iteration `forEachReverse` - */ -ReactiveList.prototype.forEach = function(f, noneReactive, reverse) { - var self = this; - // Check if f is a function - if (typeof f !== 'function') { - throw new Error('ReactiveList forEach requires a function'); - } - // We allow this not to be reactive - if (!noneReactive) { self._listDeps.depend(); } - // Set current to the first object - var current = (reverse)?self.last: self.first; - // Iterate over the list while its not empty - while (current) { - // Call the callback function - f(current.value, current.key); - // Jump to the next item in the list - current = (reverse)?current.prev: current.next; - } -}; - -/** @method ReactiveList.prototype.forEachReverse - * @param {function} f Callback `funciton(value, key)` - * @param {boolean} [noneReactive=false] Set true if want to disable reactivity - */ -ReactiveList.prototype.forEachReverse = function(f, noneReactive) { - // Call forEach with the reverse flag - this.forEach(f, noneReactive, true); -}; - -/** @method ReactiveList.prototype.fetch Returns list as array - * @param {boolean} [noneReactive=false] Set true if want to disable reactivity - * @reactive This can be disabled - * @returns {array} List of items - */ -ReactiveList.prototype.fetch = function(noneReactive) { - var self = this; - // Init the result buffer - var result = []; - // Iterate over the list items - self.forEach(function fetchCallback(value) { - // Add the item value to the result - result.push(value); - }, noneReactive); - // Return the result - return result; -}; diff --git a/packages/wekan-cfs-reactive-list/tests.js b/packages/wekan-cfs-reactive-list/tests.js deleted file mode 100644 index e13e90318..000000000 --- a/packages/wekan-cfs-reactive-list/tests.js +++ /dev/null @@ -1,104 +0,0 @@ -"use strict"; - -function equals(a, b) { - return !!(JSON.stringify(a) === JSON.stringify(b)); -} - -Tinytest.add('ReactiveList - definition', function(test) { - test.isTrue(typeof ReactiveList !== 'undefined', 'ReactiveList is undefined, make sure to add the reactive-list package'); -}); - - -// We do a small test of insert and remove -Tinytest.addAsync('ReactiveList - basic insert and remove - test 1', function test1 (test, onComplete) { - Meteor.setTimeout(function() { - var list = new ReactiveList({ - reactive: true - }); - - var testLength = 500; - - for (var i = 0; i < testLength; i++) - list.insert(i, 'value' + i); - - test.equal(list._length, testLength, 'List length is not as expected'); - - var order = 0; - list.forEach(function(value, key) { - test.equal(key, order, 'order is not as expected'); - test.equal(value, 'value'+order, 'order is not as expected'); - order++; - }); - - test.equal(order, testLength, 'forEach length is not as expected'); - - list.forEachReverse(function(value, key) { - order--; - test.equal(key, order, 'order is not as expected'); - test.equal(value, 'value'+order, 'order is not as expected'); - }); - - test.equal(order, 0, 'forEachReverse length is not as expected'); - - // Remove all items - for (var i = 0; i < testLength; i++) - list.remove(i); - - test.equal(list._length, 0, 'List length is not as expected'); - - test.isUndefined(list.first, 'First should now be undefined'); - - test.isUndefined(list.last, 'Last should now be undefined'); - onComplete(); - }, 1000); -}); - - -// We test insert and remove on larger scale -Tinytest.addAsync('ReactiveList - basic insert and reset - test 2', function test2 (test, onComplete) { - Meteor.setTimeout(function() { - var list = new ReactiveList({ - reactive: true - }); - - - var testLength = 500; - - for (var i = 0; i < testLength; i++) - list.insert(i, 'value' + i); - - test.equal(list._length, testLength, 'List length is not as expected'); - - - // Remove all items - list.reset(); - - test.equal(list._length, 0, 'List length is not as expected'); - - test.isUndefined(list.first, 'First should now be undefined'); - - test.isUndefined(list.last, 'Last should now be undefined'); - - onComplete(); - }, 5000); -}); - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-reactive-property/.editorconfig b/packages/wekan-cfs-reactive-property/.editorconfig deleted file mode 100644 index 37a7d486e..000000000 --- a/packages/wekan-cfs-reactive-property/.editorconfig +++ /dev/null @@ -1,18 +0,0 @@ -# .editorconfig -# Meteor adapted EditorConfig, http://EditorConfig.org -# By RaiX 2013 - -root = true - -[*.js] -end_of_line = lf -insert_final_newline = true -indent_style = space -indent_size = 2 -trim_trailing_whitespace = true -charset = utf-8 -max_line_length = 80 -indent_brace_style = 1TBS -spaces_around_operators = true -quote_type = auto -# curly_bracket_next_line = true diff --git a/packages/wekan-cfs-reactive-property/.gitignore b/packages/wekan-cfs-reactive-property/.gitignore deleted file mode 100644 index 45353da68..000000000 --- a/packages/wekan-cfs-reactive-property/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/versions.json -.build* diff --git a/packages/wekan-cfs-reactive-property/.jshintrc b/packages/wekan-cfs-reactive-property/.jshintrc deleted file mode 100644 index 52d24acf2..000000000 --- a/packages/wekan-cfs-reactive-property/.jshintrc +++ /dev/null @@ -1,97 +0,0 @@ -{ - // JSHint Meteor Configuration File - // Match the Meteor Style Guide - // - // By @raix with contributions from @aldeed and @awatson1978 - // Source https://github.com/raix/Meteor-jshintrc - // - // See http://jshint.com/docs/ for more details - - "maxerr": 50, - "bitwise": true, - "camelcase": true, - "curly": true, - "eqeqeq": true, - "forin": true, - "immed": false, - "indent": 2, - "latedef": false, - "newcap": false, - "noarg": true, - "noempty": true, - "nonew": false, - "plusplus": false, - "quotmark": false, - "undef": true, - "unused": true, - "strict": true, - "trailing": true, - "maxparams": false, - "maxdepth": false, - "maxstatements": false, - "maxcomplexity": false, - "maxlen": 80, - "asi": false, - "boss": false, - "debug": false, - "eqnull": false, - "es5": false, - "esnext": false, - "moz": false, - "evil": false, - "expr": false, - "funcscope": false, - "globalstrict": true, - "iterator": false, - "lastsemic": false, - "laxbreak": false, - "laxcomma": false, - "loopfunc": false, - "multistr": false, - "proto": false, - "scripturl": false, - "smarttabs": false, - "shadow": false, - "sub": false, - "supernew": false, - "validthis": false, - "browser": true, - "couch": false, - "devel": true, - "dojo": false, - "jquery": false, - "mootools": false, - "node": false, - "nonstandard": false, - "prototypejs": false, - "rhino": false, - "worker": false, - "wsh": false, - "yui": false, - "nomen": false, - "onevar": false, - "passfail": false, - "white": false, - "predef": [ - "Meteor", - "Accounts", - "Session", - "Template", - "check", - "Match", - "Deps", - "EJSON", - "Email", - "Package", - "Tinytest", - "Npm", - "Assets", - "Packages", - "process", - "LocalCollection", - "_", - "Random", - "HTTP", - "_methodHTTP" - ] -} \ No newline at end of file diff --git a/packages/wekan-cfs-reactive-property/LICENSE.md b/packages/wekan-cfs-reactive-property/LICENSE.md deleted file mode 100644 index 2a5c5339e..000000000 --- a/packages/wekan-cfs-reactive-property/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 [@raix](https://github.com/raix), aka Morten N.O. Nørgaard Henriksen, mh@gi-software.com - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/wekan-cfs-reactive-property/README.md b/packages/wekan-cfs-reactive-property/README.md deleted file mode 100644 index 14d5c4a7f..000000000 --- a/packages/wekan-cfs-reactive-property/README.md +++ /dev/null @@ -1,32 +0,0 @@ -wekan-cfs-reactive-property [![Build Status](https://travis-ci.org/CollectionFS/Meteor-reactive-property.png?branch=master)](https://travis-ci.org/CollectionFS/Meteor-reactive-property) -========= - -~~Looking for maintainers - please reach out!~~ -This package is to be archived due to inability to find contributors, thanks to everyone who helped make it possible. - -**If you're looking for an alternative, we highly recommend [Meteor-Files](https://github.com/VeliovGroup/Meteor-Files) by [VeliovGroup](https://github.com/VeliovGroup)** - ---- - -ReactiveProperty: -* `get` Get value -* `set` Set value -* `getset` A combined getter and setter -* `inc` Increase numeric values -* `dec` Decrease numeric values - -And... It's powered by Meteor's reactive sugar :) - -Kind regards Eric(@aldeed) and Morten(@raix) - -Happy coding!! - -#API -[API Documentation](api.md) - -#Contribute -[API Complete Documentation](internal.api.md) -Update docs, `npm install docmeteor` -```bash -$ docmeteor -``` diff --git a/packages/wekan-cfs-reactive-property/api.md b/packages/wekan-cfs-reactive-property/api.md deleted file mode 100644 index ce1886f88..000000000 --- a/packages/wekan-cfs-reactive-property/api.md +++ /dev/null @@ -1,152 +0,0 @@ -#ReactiveProperty -A simple class that provides an reactive property interface - -#### new ReactiveProperty(defaultValue, [reactive])  Anywhere #### -- - -__Arguments__ - -* __defaultValue__ *{any}* -Set the default value for the reactive property -* __reactive__ *{boolean}* (Optional = true) -Allow the user to disable reactivity - -- - - -This api should only be in the internal.api.md - -> ```ReactiveProperty = function(defaultValue, reactive) { ...``` [reactive-property.js:18](reactive-property.js#L18) - -- - -#### ReactiveProperty.get()  Anywhere #### -- -*This method __get__ is defined in `ReactiveProperty`* - -Usage: -```js - var foo = new ReactiveProperty('bar'); - foo.get(); // equals "bar" -``` - -> ```self.get = function() { ...``` [reactive-property.js:44](reactive-property.js#L44) - -- - -#### ReactiveProperty.set(value)  Anywhere #### -- -*This method __set__ is defined in `ReactiveProperty`* - -__Arguments__ - -* __value__ *{any}* - -- - -Usage: -```js - var foo = new ReactiveProperty('bar'); - foo.set('bar'); -``` - -> ```self.set = function(value) { ...``` [reactive-property.js:58](reactive-property.js#L58) - -- - -#### ReactiveProperty.dec([by])  Anywhere #### -- -*This method __dec__ is defined in `ReactiveProperty`* - -__Arguments__ - -* __by__ *{number}* (Optional = 1) -Value to decrease by - -- - -Usage: -```js - var foo = new ReactiveProperty('bar'); - foo.set(0); - foo.dec(5); // -5 -``` - -> ```self.dec = function(by) { ...``` [reactive-property.js:75](reactive-property.js#L75) - -- - -#### ReactiveProperty.inc([by])  Anywhere #### -- -*This method __inc__ is defined in `ReactiveProperty`* - -__Arguments__ - -* __by__ *{number}* (Optional = 1) -Value to increase by - -- - -Usage: -```js - var foo = new ReactiveProperty('bar'); - foo.set(0); - foo.inc(5); // 5 -``` - -> ```self.inc = function(by) { ...``` [reactive-property.js:90](reactive-property.js#L90) - -- - -#### ReactiveProperty.getset([value])  Anywhere #### -- -*This method __getset__ is defined in `ReactiveProperty`* - -__Arguments__ - -* __value__ *{any}* (Optional) -Value to set property - if undefined the act like `get` - -- - -__Returns__ *{any}* -Returns value if no arguments are passed to the function - -Usage: -```js - var foo = new ReactiveProperty('bar'); - foo.getset(5); - foo.getset(); // returns 5 -``` - -> ```self.getset = function(value) { ...``` [reactive-property.js:106](reactive-property.js#L106) - -- - -#### ReactiveProperty.toString()  Anywhere #### -- -*This method __toString__ is defined in `ReactiveProperty`* - -Usage: -```js - var foo = new ReactiveProperty('bar'); - foo.toString(); // returns 'bar' -``` - -> ```self.toString = function() { ...``` [reactive-property.js:122](reactive-property.js#L122) - -- - -#### ReactiveProperty.toText()  Anywhere #### -- -*This method __toText__ is defined in `ReactiveProperty`* - -Usage: -```js - var foo = new ReactiveProperty('bar'); - foo.toText(); // returns 'bar' -``` - -> ```self.toText = self.toString;``` [reactive-property.js:135](reactive-property.js#L135) - -- diff --git a/packages/wekan-cfs-reactive-property/internal.api.md b/packages/wekan-cfs-reactive-property/internal.api.md deleted file mode 100644 index 74b4b6607..000000000 --- a/packages/wekan-cfs-reactive-property/internal.api.md +++ /dev/null @@ -1,167 +0,0 @@ -> File: ["reactive-property.js"](reactive-property.js) -> Where: {client|server} - -- -#ReactiveProperty -A simple class that provides an reactive property interface - -#### new ReactiveProperty(defaultValue, [reactive])  Anywhere #### -- - -__Arguments__ - -* __defaultValue__ *{any}* -Set the default value for the reactive property -* __reactive__ *{boolean}* (Optional = true) -Allow the user to disable reactivity - -- - - -This api should only be in the internal.api.md - -> ```ReactiveProperty = function(defaultValue, reactive) { ...``` [reactive-property.js:18](reactive-property.js#L18) - -- - -#### ReactiveProperty.value {any}  Anywhere #### -- -*This property is private* -*This property __value__ is defined in `ReactiveProperty`* -This contains the non reactive value, should only be used as a getter for -internal use - -> ```self.value = defaultValue;``` [reactive-property.js:27](reactive-property.js#L27) - -- - -#### ReactiveProperty.get()  Anywhere #### -- -*This method __get__ is defined in `ReactiveProperty`* - -Usage: -```js - var foo = new ReactiveProperty('bar'); - foo.get(); // equals "bar" -``` - -> ```self.get = function() { ...``` [reactive-property.js:44](reactive-property.js#L44) - -- - -#### ReactiveProperty.set(value)  Anywhere #### -- -*This method __set__ is defined in `ReactiveProperty`* - -__Arguments__ - -* __value__ *{any}* - -- - -Usage: -```js - var foo = new ReactiveProperty('bar'); - foo.set('bar'); -``` - -> ```self.set = function(value) { ...``` [reactive-property.js:58](reactive-property.js#L58) - -- - -#### ReactiveProperty.dec([by])  Anywhere #### -- -*This method __dec__ is defined in `ReactiveProperty`* - -__Arguments__ - -* __by__ *{number}* (Optional = 1) -Value to decrease by - -- - -Usage: -```js - var foo = new ReactiveProperty('bar'); - foo.set(0); - foo.dec(5); // -5 -``` - -> ```self.dec = function(by) { ...``` [reactive-property.js:75](reactive-property.js#L75) - -- - -#### ReactiveProperty.inc([by])  Anywhere #### -- -*This method __inc__ is defined in `ReactiveProperty`* - -__Arguments__ - -* __by__ *{number}* (Optional = 1) -Value to increase by - -- - -Usage: -```js - var foo = new ReactiveProperty('bar'); - foo.set(0); - foo.inc(5); // 5 -``` - -> ```self.inc = function(by) { ...``` [reactive-property.js:90](reactive-property.js#L90) - -- - -#### ReactiveProperty.getset([value])  Anywhere #### -- -*This method __getset__ is defined in `ReactiveProperty`* - -__Arguments__ - -* __value__ *{any}* (Optional) -Value to set property - if undefined the act like `get` - -- - -__Returns__ *{any}* -Returns value if no arguments are passed to the function - -Usage: -```js - var foo = new ReactiveProperty('bar'); - foo.getset(5); - foo.getset(); // returns 5 -``` - -> ```self.getset = function(value) { ...``` [reactive-property.js:106](reactive-property.js#L106) - -- - -#### ReactiveProperty.toString()  Anywhere #### -- -*This method __toString__ is defined in `ReactiveProperty`* - -Usage: -```js - var foo = new ReactiveProperty('bar'); - foo.toString(); // returns 'bar' -``` - -> ```self.toString = function() { ...``` [reactive-property.js:122](reactive-property.js#L122) - -- - -#### ReactiveProperty.toText()  Anywhere #### -- -*This method __toText__ is defined in `ReactiveProperty`* - -Usage: -```js - var foo = new ReactiveProperty('bar'); - foo.toText(); // returns 'bar' -``` - -> ```self.toText = self.toString;``` [reactive-property.js:135](reactive-property.js#L135) - -- diff --git a/packages/wekan-cfs-reactive-property/package.js b/packages/wekan-cfs-reactive-property/package.js deleted file mode 100644 index cc8797e96..000000000 --- a/packages/wekan-cfs-reactive-property/package.js +++ /dev/null @@ -1,23 +0,0 @@ -Package.describe({ - name: 'wekan-cfs-reactive-property', - version: '0.0.4', - summary: 'Reactive Property is a small, fast reative property class', - git: 'https://github.com/zcfs/Meteor-reactive-property.git' -}); - -Package.onUse(function (api) { - api.versionsFrom('1.0'); - - api.use('deps', ['client', 'server']); - - api.export('ReactiveProperty'); - api.addFiles(['reactive-property.js'], ['client', 'server']); -}); - -// Package.onTest(function (api) { -// api.use('power-queue'); -// api.use('test-helpers', 'server'); -// api.use('tinytest'); - -// api.add_files('tests.js'); -// }); diff --git a/packages/wekan-cfs-reactive-property/reactive-property.js b/packages/wekan-cfs-reactive-property/reactive-property.js deleted file mode 100644 index 183f3aea9..000000000 --- a/packages/wekan-cfs-reactive-property/reactive-property.js +++ /dev/null @@ -1,137 +0,0 @@ -// #ReactiveProperty -// A simple class that provides an reactive property interface - -_noopCallback = function() {}; - -_nonReactive = { - changed: _noopCallback, - depend: _noopCallback -}; - -/** - * @constructor - * @param {any} defaultValue Set the default value for the reactive property - * @param {boolean} [reactive = true] Allow the user to disable reactivity - * - * This api should only be in the internal.api.md - */ -ReactiveProperty = function(defaultValue, reactive) { - var self = this; - var _deps = (reactive === false)? _nonReactive : new Deps.Dependency(); - - /** @property ReactiveProperty.value - * @private - * This contains the non reactive value, should only be used as a getter for - * internal use - */ - self.value = defaultValue; - - self.onChange = function() {}; - - self.changed = function() { - _deps.changed(); - self.onChange(self.value); - }; - - /** - * @method ReactiveProperty.get - * Usage: - * ```js - * var foo = new ReactiveProperty('bar'); - * foo.get(); // equals "bar" - * ``` - */ - self.get = function() { - _deps.depend(); - return self.value; - }; - - /** - * @method ReactiveProperty.set Set property to value - * @param {any} value - * Usage: - * ```js - * var foo = new ReactiveProperty('bar'); - * foo.set('bar'); - * ``` - */ - self.set = function(value) { - if (self.value !== value) { - self.value = value; - self.changed(); - } - }; - - /** - * @method ReactiveProperty.dec Decrease numeric property - * @param {number} [by=1] Value to decrease by - * Usage: - * ```js - * var foo = new ReactiveProperty('bar'); - * foo.set(0); - * foo.dec(5); // -5 - * ``` - */ - self.dec = function(by) { - self.value -= by || 1; - self.changed(); - }; - - /** - * @method ReactiveProperty.inc increase numeric property - * @param {number} [by=1] Value to increase by - * Usage: - * ```js - * var foo = new ReactiveProperty('bar'); - * foo.set(0); - * foo.inc(5); // 5 - * ``` - */ - self.inc = function(by) { - self.value += by || 1; - self.changed(); - }; - - /** - * @method ReactiveProperty.getset increase numeric property - * @param {any} [value] Value to set property - if undefined the act like `get` - * @returns {any} Returns value if no arguments are passed to the function - * Usage: - * ```js - * var foo = new ReactiveProperty('bar'); - * foo.getset(5); - * foo.getset(); // returns 5 - * ``` - */ - self.getset = function(value) { - if (typeof value !== 'undefined') { - self.set(value); - } else { - return self.get(); - } - }; - - /** - * @method ReactiveProperty.toString - * Usage: - * ```js - * var foo = new ReactiveProperty('bar'); - * foo.toString(); // returns 'bar' - * ``` - */ - self.toString = function() { - var val = self.get(); - return val ? val.toString() : ''; - }; - - /** - * @method ReactiveProperty.toText - * Usage: - * ```js - * var foo = new ReactiveProperty('bar'); - * foo.toText(); // returns 'bar' - * ``` - */ - self.toText = self.toString; - -}; diff --git a/packages/wekan-cfs-reactive-property/tests.js b/packages/wekan-cfs-reactive-property/tests.js deleted file mode 100644 index 863e96821..000000000 --- a/packages/wekan-cfs-reactive-property/tests.js +++ /dev/null @@ -1,30 +0,0 @@ -"use strict"; - -function equals(a, b) { - return !!(JSON.stringify(a) === JSON.stringify(b)); -} - -Tinytest.add('ReactiveProperty - test', function(test) { - //TODO -}); - - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-standard-packages/.travis.yml b/packages/wekan-cfs-standard-packages/.travis.yml deleted file mode 100644 index 6a4640033..000000000 --- a/packages/wekan-cfs-standard-packages/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - "0.10" -before_install: - - "curl -L http://git.io/s0Zu-w | /bin/sh" \ No newline at end of file diff --git a/packages/wekan-cfs-standard-packages/ADVANCED.md b/packages/wekan-cfs-standard-packages/ADVANCED.md deleted file mode 100644 index 8e8b64012..000000000 --- a/packages/wekan-cfs-standard-packages/ADVANCED.md +++ /dev/null @@ -1,265 +0,0 @@ -This is advanced information useful for anyone who contributes to CollectionFS -or wants to make their own storage adapter. - -## Goals - -* Scale horizontally and vertically -* Secure file operations and file serving -* Limit memory consumption and stream where possible -* Use queues to provide synchronous execution of tasks -* Reactivity -* Uploads and downloads are cancelable and resumable - -## All Packages - -* wekan-cfs-standard-packages (implies some component packages) - * wekan-cfs-base-package - * wekan-cfs-file - * wekan-cfs-collection - * wekan-cfs-collection-filters - * wekan-cfs-access-point - * wekan-cfs-worker - * wekan-cfs-upload-http -* wekan-cfs-graphicsmagick -* wekan-cfs-ui -* wekan-cfs-filesystem -* wekan-cfs-gridfs -* wekan-cfs-s3 -* wekan-cfs-dropbox - -## Collections - -Various MongoDB collections are created by CollectionFS and related packages. -Here's an explanation of what they are named and what their documents look like. - -### cfs.collectionName.filerecord (FS.Collection) - -```js -{ - _id: "", - copies: { - storeName: { - key: String, // a string that the store generates, understands, and uses to uniquely identify the file in the backing store - name: String, // as saved in this store, potentially changed by beforeWrite - type: String, // as saved in this store, potentially changed by beforeWrite - size: Number, // as saved in this store, in bytes, potentially changed by beforeWrite - createdAt: Date, // when first saved in this store - updatedAt: Date // when last saved in this store - } - }, - original: { - name: String, // of the originally uploaded file - type: String, // of the originally uploaded file - size: Number, // of the originally uploaded file, in bytes - updatedAt: Date // of the originally uploaded file - }, - failures: { - copies: { - storeName: { - count: Number, - firstAttempt: Date, - lastAttempt: Date, - doneTrying: Boolean - } - } - } -} -``` - -The `original` object represents the file that was uploaded. Each object under `copies`, represents the file that was stored, keyed by store name. - -The original file isn’t technically stored anywhere permanently, so the `original` object can be generally ignored. It’s there for reference in case you want to see any of that info. - -The objects under the `copies` object represent the copies of the original that were actually saved in the backing stores. The info here might be the same as the original file, or it might be different if your store has a `beforeWrite` or `transformWrite` function that changes the stored file's properties. - -You can change any of the info in the `copies` object using the setter methods on FS.File instances, like fileObj.name('NewName.gif', {store: 'blobs'}), which would change the name of the file stored in the blobs store. Of course you wouldn't want to change `type` or `size` unless you were also transforming the binary file data itself. The important thing is not to touch the `key` property since that's used by the store to retrieve the file data. The rest is metadata that you're free to change. - -### cfs_gridfs... - -Created by the GridFS storage adapter. The `cfs_gridfs..files` and `cfs_gridfs..chunks` collections match the MongoDB GridFS spec. - -### _tempstore - -When files are first uploaded or inserted on the server, we save the original to a temporary store. This is a place where data can be stored until we have all the chunks we need and we are able to successfully save the file to all of the defined permanant stores. The temporary store may create one or more collections with `_tempstore` in the name. In general, it is relatively safe to clear these collections at any time. The worst you will do is cause a currently uploading or currently storing file to fail. - -## Creating a Storage Adapter - -To create a storage adapter, define an object constructor function that takes -a name as a first argument and any additional necessary settings as additional -arguments. Make it return an instance of FS.StorageAdapter, passing your API to -the FS.StorageAdapter constructor function. Here's an example: - -```js -FS.MyStore = function(name, options) { - // Prep some variables here - - return new FS.StorageAdapter(name, {}, { - typeName: 'storage.myadapter', - get: function(identifier, callback) { - // Use identifier to retrieve a Buffer and pass it to callback - }, - getBytes: function(identifier, start, end, callback) { - // Use identifier to retrieve a Buffer containing only - // the bytes from start to end, and pass it to callback. - // If this is impossible, don't include a getBytes property. - }, - put: function(id, fileKey, buffer, options, callback) { - // Store the buffer and then call the callback, passing it - // an identifier that will later be the first argument of the - // other API functions. The identifier will likely be the - // fileKey, the id, or some altered version of those. - }, - remove: function(identifier, callback) { - // Delete the data for the file identified by identifier - }, - watch: function(callback) { - // If you can watch file data, initialize a watcher and then call - // callback whenever a file changes. Refer to the filesystem - // storage adapter for an example. If you can't watch files, then - // throw an error stating that the "sync" option is not supported. - }, - init: function() { - // Perform any initialization - } - }); -}; -``` - -`getBytes` and `init` are optional. The others are required, but you should throw -an error from `watch` if you can't watch files. Your `put` function should check -for an `overwrite` option. If it's true, save the data even if you've already -saved for the given `id` or `fileKey`. If not, you may alter the `fileKey` as -necessary to prevent overwriting and then pass the altered `fileKey` to the -callback. - -By convention, any official stores should be in the `FS` namespace -and end with the word "Store". - -## Architecture - -``` -Client <---- (ddp/http) --- | CFS access point | - | Security layer | - | Storage adapters | - | | | | - Mongo–––––––––O | | | - Local––––––––––––––O | | - Fileserver––––––––––––––O | - External server––––––––––––––O -``` - -## The Upload Process (DDP) - -Here's a closer look at what happens when a file is uploaded. - -### Step 1: Insert - -All uploads initiate on a client. If a file is inserted on the server, the -data is already on the server, so no upload process is necessary. - -An upload begins when you call `insert()` on an `FS.Collection` instance. The -`insert` method inserts the file's metadata into the underlying collection on -the client. If that is successful, it immediately calls `put()` on the `FS.File` -instance. This in turn calls `FS.uploadQueue.uploadFile()`, which kicks off -the data upload. - -### Step 2: Transfer - -The upload transfer queue's `uploadFile` method uses the file size and a -pre-defined chunk size to determine how many chunks the file will be broken into. -It then adds one task to its PowerQueue instance per chunk. Each chunk task does -the following: - -1. Extracts the necessary subset (chunk) of data from the file. -2. Passes the data chunk to a server method over DDP. -3. Marks the chunk uploaded in a client-only tracking collection if the server -method reports no errors. - -PowerQueue's reactive methods are used to report total progress for all current -uploads, but the custom client-only tracking collection is used to report progress -per file. (TODO: update this after PQ sub-queues are done and the transfer -queues are updated to use them) - -### Step 3: Receive - -Each data chunk is received by a DDP access point (a server method defined in -accessPoint.js). This method does the following: - -1. Checks that incoming arguments are of the correct type. -2. If the `insecure` package is not used, checks the `insert` allow and deny -functions. If insertion is denied, the method throws an access denied error. -3. Passes the data chunk to the temporary store. -4. If the temporary store reports that it now has all chunks for the file, -retrieves the complete file from the temporary store and calls `fsFile.put()` -to begin the process of saving it to each of the defined stores. - -### Step 4: Temporarily Store - -The temporary store is managed by the `FS.TempStore` object. When the server method -calls `FS.TempStore.saveChunk()`, the chunk data is saved to a randomly named -temporary file in the server operating system's default temporary directory. -The path to this file is saved in the `chunks` array on the corresponding FS.File. -(The `chunks` property is available on an FS.File instance only on the server -because it is used strictly for server-side tracking.) - -`saveChunk` calls a callback after saving the chunk. The second argument of -this callback is `true` if all chunks for the given file are now saved in the -temporary store (i.e., all chunks were uploaded so all file data is now present -on the server). - -Using a temporary filesystem store like this ensures that chunks remain available -after an app or server restart, allowing the client to resume uploads. Chunks -are saved to the app server filesystem rather than GridFS in your MongoDB because it -is theoretically faster, especially when the mongo database is on a separate server. - -NOTE: The first version of temp storage appended/wrote to a single temp file -per uploaded file, but there are issues with file locking and writing to -specific start-points in an existing file. By switching to 1 chunk = 1 temp -file, we have the freedom to have parallel chunk uploads in any order without -fear of file lock contention, and it's still really fast. - -### Step 5: Store - -After the server method calls `put()` on the complete uploaded file, this in -turn calls `saveCopies()` on its associated `FS.Collection` instance. `saveCopies` -loops through each copy/store you defined in the options and saves the file -to that store. If you defined a `beforeSave` function for the store, the file -passes through that function first. If a `beforeSave` returns `false`, this is -recorded in the `FS.File` instance and the file will never be saved to that store. - -* If the store reports that it successfully saved the file, a reference string, -returned by the store, is stored in `fsFile.copies[storeName]`. This string will -be anything that the store wants to return, so long as it can be used later to -retrieve that same file. -* If the store reports that it was not able to save the file, the error is logged -in the `FS.File` instance. If the total number of failures exceeds the `maxTries` -setting for the store, a `doneTrying` flag is set to `true`. When `doneTrying` -is `false`, the FileWorker may attempt to save again later. (See the next step.) - -### Step 6: Retry - -The `FileWorker` (in fileWorker.js), searches all `FS.Collection` every 5 -seconds (not configurable right now but could be) to see if there are any -storage failures that meet the criteria to be -retried (namely, if failure count > 0 and doneTrying is false). The file worker -then calls `saveCopies` for each file that is identified. (See the previous step.) - -The `FileWorker` also does one more thing. If it identifies any files that have -been successfully saved to all defined stores, or that have failed to save the -maximum number of times for a store, or that won't be saved to a store because -`beforeSave` returned `false`, then it tells `FS.TempStore` to delete all the -temporary chunks for that file. They are no longer needed. - -Note: One the temporary chunks are deleted, the "original" file will be no longer -available if all stores are modifying the original using a `beforeSave` function. - -## The Download Process (DDP) - -Here's a closer look at what happens when a file is downloaded. - -TODO Explain with similar layout to "The Upload Process" section - -## Wish List - -* Dynamic file manipulation -* Paste box upload component diff --git a/packages/wekan-cfs-standard-packages/CHANGELOG.md b/packages/wekan-cfs-standard-packages/CHANGELOG.md deleted file mode 100644 index 342de524c..000000000 --- a/packages/wekan-cfs-standard-packages/CHANGELOG.md +++ /dev/null @@ -1,721 +0,0 @@ -# Changelog - -## vCurrent -## [v0.5.2] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.5.2) -#### 17/12/14 by Morten Henriksen -- Bump to version 0.5.2 - -## [v0.5.1] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.5.1) -#### 17/12/14 by Morten Henriksen -- mbr update, remove versions.json - -- Bump to version 0.5.1 - -## [v0.5.0] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.5.0) -#### 17/12/14 by Morten Henriksen -- Merge branch 'devel' of https://github.com/zcfs/Meteor-CollectionFS into devel - -- mbr update versions and fix warnings - -- update pkg, dependencies, etc. - -- Fix #483 - -- *Merged pull-request:* "mrt graphicsmagick instructions to meteor 0.9+" [#442](https://github.com/zcfs/Meteor-CollectionFS/issues/442) ([yogiben](https://github.com/yogiben)) - -- mrt graphicsmagick instructions to meteor 0.9+ - -- mention underlying collection - -- *Merged pull-request:* "Added server-side Buffer example to README.md" [#405](https://github.com/zcfs/Meteor-CollectionFS/issues/405) ([abuddenb](https://github.com/abuddenb)) - -- change prop names - -- Merge branch 'devel' of https://github.com/zcfs/Meteor-CollectionFS into devel - -- add "Display an Uploaded Image" example - -- addition to steps - -- correct 0.9.0 steps - -- Merge branch 'devel' of github.com:abuddenb/Meteor-CollectionFS into devel - -- Added server-side Buffer example to README.md - -Patches by GitHub users [@yogiben](https://github.com/yogiben), [@abuddenb](https://github.com/abuddenb). - -## [v0.4.9] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.9) -#### 27/08/14 by Eric Dobbertin -- add 0.9.0 instructions - -- change package name to lowercase - -- Added server-side Buffer example to README.md - -- *Merged pull-request:* "Updated README.md to reflect that FS.File - Objects can't be stored in t..." [#395](https://github.com/zcfs/Meteor-CollectionFS/issues/395) ([DanielDornhardt](https://github.com/DanielDornhardt)) - -- Updated README.md to reflect that FS.File - Objects can't be stored in the Server MongoDB at the moment. - -- document key - -- update the descriptions of collections - -- document beforeWrite - -- add download button example - -- *Merged pull-request:* "Update README.md" [#354](https://github.com/zcfs/Meteor-CollectionFS/issues/354) ([karabijavad](https://github.com/karabijavad)) - -- should say to use cfs-graphicsmagick pkg - -- fix typo - -- *Merged pull-request:* "Added "Storing FS.File references in your objects" chapter to README" [#311](https://github.com/zcfs/Meteor-CollectionFS/issues/311) ([Sanjo](https://github.com/Sanjo)) - -- Added "Storing FS.File references in your objects" chapter to README - -- a few more API updates - -- updates for changed FS.File API - -- additions and clarifications - -- *Merged pull-request:* "Custom Metadata misleading example" [#282](https://github.com/zcfs/Meteor-CollectionFS/issues/282) ([czeslaaw](https://github.com/czeslaaw)) - -- Custom Metadata misleading example - -Patches by GitHub users [@DanielDornhardt](https://github.com/DanielDornhardt), [@karabijavad](https://github.com/karabijavad), [@Sanjo](https://github.com/Sanjo), [@czeslaaw](https://github.com/czeslaaw). - -## [v0.4.8] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.8) -#### 09/04/14 by Eric Dobbertin -- Add cfs-collection-filters pkg by default - -- Use FS.Utility.setFileExtension in example - -## [v0.4.7] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.7) -#### 05/04/14 by Morten Henriksen -- corrections, and move image examples here so we can deprecate cfs-imagemagick - -## [v0.4.6] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.6) -#### 02/04/14 by Morten Henriksen -- *Fixed bug:* "Documentation Issues" [#241](https://github.com/zcfs/Meteor-CollectionFS/issues/241) - -- point to cfs-graphicsmagick readme for transform examples - -## [v0.4.5] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.5) -#### 31/03/14 by Eric Dobbertin -- use latest releases - -- Add yet a note about mrt and collectionFS in the readme - -## [v0.4.4] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.4) -#### 25/03/14 by Morten Henriksen -- attempt to get everything up to date - -- Add notice about mrt having troubles figuring out deps - -- *Merged pull-request:* "Removed redundant installation instructions." [#212](https://github.com/zcfs/Meteor-CollectionFS/issues/212) ([lleonard188](https://github.com/lleonard188)) - -- up to date - -- read me update - -- add test note - -Patches by GitHub user [@lleonard188](https://github.com/lleonard188). - -## [v0.4.3] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.3) -#### 23/03/14 by Morten Henriksen -- use collectionFS travis version force update - -## [v0.4.2] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.2) -#### 22/03/14 by Morten Henriksen -- change deps - -- Add read me about transformWrite - -## [v0.4.1] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.1) -#### 21/03/14 by Morten Henriksen -- update reference to devel branch - -- Merge branch 'devel' of https://github.com/zcfs/Meteor-CollectionFS into devel - -- don't need to install transfer - -- mark deprecated api docs - -- test strikeout md - -- no need to imply cfs-transfer since it doesn't do anything at the moment - -- Remove ejson-file imply - -## [v0.4.0] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.4.0) -#### 06/03/14 by Eric Dobbertin -- add section for documenting example code for common tasks, and add some of the examples; @raix feel free to add more - -- add http upload package to smart.json - -- Merge origin/devel into devel - -- need to imply the http upload package because it's the default now - -- update HTTP access point override docs - -- update docs to use `devel` branch - -- list component packages in smart.json - -- Merge origin/devel into devel-merge - -- add the ejson-file and correct doc - -- refactor everything into packages - -## [(origin/devel-merge-old] (https://github.com/zcfs/Meteor-CollectionFS/tree/(origin/devel-merge-old) -#### 12/02/14 by Eric Dobbertin -- update to latest FileSaver.js - -- one of many refactores - -- add optimization section - -- add section explaining client vs server insert - -- prevent autopublish for the SA collections - -- remove arg that isn't used or passed - -- changes to support client SA, plus clean/reorg SA code to have less duplication - -- merge the concepts of "store" and "copy", update docs, switch to FS.Store namespace - -- use wait:true to avoid Meteor issue - -- extend allow when insecure package is installed - -- document and improve code flow a bit - -- faster to use onResultReceived callback - -- use onload instead of onloadend because we want only successful loads - -- remove some console logging - -- fix issue where stuff wasn't uploading because we weren't calling getFileRecord() in the access point methods - -- make allowed file extension checks not be case sensitive - -- remove DDP "/del" access point since it's not used or necessary - -- Remove collection-hooks dependency; use deny instead. Also some cleanup and code docs - -- replace `mmmagic` dependency with a `mime` dependency; hopefully fixes issues we've seen with meteor deploy - -- refactor to expose saveCopy to API; then change fileworker observes to be per-copy, calling saveCopy and allowing better control of which copies to create at which times - -- use observes for all store saving and temp store deleting; add/adjust some api doc comments (didn't regenerate yet) - -- improve fileIsAllowed check order and messages - -- Add check for the Accounts package - -- *Fixed bug:* "no userId passed to download allow validator" [#120](https://github.com/zcfs/Meteor-CollectionFS/issues/120) - -- always append access token to url when a user is logged in; makes usage simpler to do opt-out rather than opt-in - -- Don't queue ddp method calls - -- Merge changes - -- Optimize buffer handling - -- Switch to MicroQueue - -- improve memory management, attempt client side resume implementation, other minor fixes - -- fix several issues, make downloading work, improve a few bits of code - -- do the isImage test correctly; add some API docs - -- isEmpty will be true for null or undefined - -- rewrite getExtension so it works for unmounted files, too - -- add strong reactive-list dependency for powerqueue - -- minor fixes and code improvements; track uploading files by both collection and ID since one queue handles all collections - -- Base the upload queue on PowerQueue sub queues - -- Add sa note - -- limit use of db - -- Refactor and documentation - -- use mmmagic 0.3.5 - -- *Fixed bug:* "Option to set Cache-Control and Max-Age" [#117](https://github.com/zcfs/Meteor-CollectionFS/issues/117) - -- fix stuff that's broken - -## [v0.3.7] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.3.7) -#### 08/01/14 by Morten Henriksen -- *Fixed bug:* "How to store files on the server side?" [#29](https://github.com/zcfs/Meteor-CollectionFS/issues/29) - -- rework ejson and remove fsFile.reload - -- explain complete upload process in ADVANCED docs - -- Adds join to smart.json (its a weak dependency #119) - -- link to api docs for acceptDropsOn - -- typo/formatting fixes - -- docs + insert callback returns `FS.File` instead of `id` - -- Add docs and `FS.File.fetch` - -- Add support for `Join` - -- end with line - -- smaller headlines in docs - -- init api docs - -- Refactor and documentation - -- FS.Collection.insert should return the `FS.File` object - -- remove some comments and such - -- document custom connections - -- add livedata ref to access DDP obj - -- use separate ddp connection with option to pass in custom - -- public folder and gm/im - -- fix null options - -- *Fixed bug:* "no userId passed to download allow validator" [#120](https://github.com/zcfs/Meteor-CollectionFS/issues/120) - -- make useHTTP true by default - -- skip auth checks if Package.insecure - -- remove `callback` arg from fsFile.get since it's not used or necessary; fix partial gets such that they actually use getBytes, greatly speeding up downloads of large files - -- reorg code and speed up downloads - -- split TransferQueue into DownloadTransferQueue and UploadTransferQueue - -- improvements to make use of new PowerQueue features - -- fix issue with previous commit - -- add accessPoints option - -- Pull out temporary chunk code into a separate tempStore.js file, within a TempStore object. This makes it easier to maintain. Also updated the file worker code to correctly find temporary chunks that can be removed and delete those files. - -- add security section - -- Internally, change all "master" stuff to be the same as "copies". External API is still the same, but master options are copied to a special copy named "_master" so that all the other code can be cleaner. This may be a step toward being able to blur or eliminate the master/copy distinction, although there are still some benefits to having a master. - -- Add instructions for installing for testing - -- refactor code to be a bit cleaner - -- add functions for getting an FS.File or setting FS.File data from a URL on the server - -- clean up and improve some transfer code - -- update console log message to be more correct - -- ensure that fsFile.bytesUploaded is always set correctly - -- fix some issues with recent commits - -- *Merged pull-request:* "Updates the filter example area so that it works" [#109](https://github.com/zcfs/Meteor-CollectionFS/issues/109) ([cramhead](https://github.com/cramhead)) - -- add .npm to gitignore - -- Remove .npm folder - -- Clean clone just a bit - -- Refactor fsCollection and argParser - -- Comment on filter options - -- Add download url - -- refactor access point - -- add put/get/del security based on allow/deny functions - -- Updates the filter example area so that it works - -- update for API change - -- more client-side speed improvements and allow passing File/Blob to FS.File constructor again - -- fix data mixup - -- fix upload slowness and blocking - -- change API to adjust issue with data loading callbacks - -- revise FS.File API where data handling is concerned; fix some issues with callback handling in client-side methods; upshot should be faster, smoother uploads and downloads - -- change names and put everything in exported FS namespace - -- fix get/download of copies - -- *Fixed bug:* "Files after certain size aren't saved properly. " [#104](https://github.com/zcfs/Meteor-CollectionFS/issues/104) - -- add fileobject metadata and acceptDropsOn - -- add some methods to load FO data from URL - -- Correct allow/deny examples - -- call put callback correctly - -- add correct temporary installation instructions - -- use correct filename when saving download - -- filtering fixes - -- removed some unused stuff - -- adjust some comments - -- switch api.remove to api.del for consistency with the other methods - -- add hasCopy method - -- new api; tons of changes - -- use generic queue for server file handling - -- update progress in the correct place - -- minor changes to comments - -- fix gridfs get method - -- incorporate #82 - -- make filtering work (added collection-hooks dependency for core package) - -- change UploadsCollection to CollectionFS; change former CollectionFS to GridFS and don't export it (used only by the gridfs storage adaptor); clean up some other areas and update readmes - -- *Fixed bug:* "retrieveBlob failure" [#93](https://github.com/zcfs/Meteor-CollectionFS/issues/93) - -- implement http methods URLs - -- Merge branch 'devel' of https://github.com/zcfs/Meteor-CollectionFS.git into devel - -- significant revisions to move downloading support to the UploadsCollection and make collectionFS/gridFS a pure storage adaptor - -- Merge branch 'pr/94' into devel - -- split and revise readmes - -- rename packages and organize package.js - -- error handling improvements - -- better failure handling for removeCopy - -- handlebars helper to display blob image in CFS package - -- remove all encoding info - -- refactor to fix multiple-file simultaneous uploads - -- don't use _id in filesystem destination since it's not set anyway - -- remove FileObject.file and instead save file as Blob (.blob) when FileObject.fromFile is called - -- revise API a bit - -- stop using strings and encoding and pass everything as Uint8Array (fixes downloading corruption) - -- only attempt to delete file if it exists - -- remove unused file - -- complete refactoring; temporary for testing/tweaking and then will split into multiple packages - -- *Merged pull-request:* "Implemented max parallel transfers" [#62](https://github.com/zcfs/Meteor-CollectionFS/issues/62) ([floo51](https://github.com/floo51)) - -Patches by GitHub users [@cramhead](https://github.com/cramhead), [@floo51](https://github.com/floo51). - -## [v0.3.6] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.3.6) -#### 10/10/13 by Morten Henriksen -- Edit ideas about storage adapters and filehandlers - -- Add MIT License - -- Add paypal and weak deps - -- Added the org. filemanager demo/example - -## [v0.3.5] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.3.5) -#### 20/09/13 by Morten Henriksen -## [v0.3.4] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.3.4) -#### 20/09/13 by Morten Henriksen -- Extract the examples from collectionFS - -- Added examples from @mxab - -## [v0.3.3] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.3.3) -#### 18/09/13 by Morten Henriksen -- added travis badge - -- Added travis badge - -- Added basic environment - -- Added metadata getter to docs - -## [v0.3.2] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.3.2) -#### 17/09/13 by Morten Henriksen -## [v0.3.1] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.3.1) -#### 16/09/13 by Morten Henriksen -- Added some details about http.publishing of collections - -- added check in filehandlers - -- Updated som docs - -- js hint added scope - -- jshint clean up - -- *Fixed bug:* "Exception from setTimeout callback: { stack: [Getter] }" [#64](https://github.com/zcfs/Meteor-CollectionFS/issues/64) - -- Merge branch 'devel' - -- Bump version to preview of 0.3.0 - -- Implemented max parallel transfers - -- Revert "began refractoring" - -- Revert "Run jshint through files" - -- Revert "Preparing file object methods for better api" - -- Revert "added fileobject files to package" - -- added fileobject files to package - -- Preparing file object methods for better api - -- Run jshint through files - -- *Merged pull-request:* "Improvements and Fixes to built-in helpers, storeFiles, and acceptDropsOn" [#51](https://github.com/zcfs/Meteor-CollectionFS/issues/51) ([aldeed](https://github.com/aldeed)) - -- Add generic events system, switch to "enums" for invalid event types, and change "fileFilter" to "filter" throughout. Update README to reflect these changes. - -- Update readme to reflect storeFiles and acceptDropsOn changes, plus add documentation for all of the new built-in handlebars helpers - -- commit some files that should be committed - -- -Improve and fix built-in handlebars helpers -Prefix all built-in helpers with "cfs" -Update new example app to reflect helper changes, and improve and fix it a bit, too - -- Merge remote-tracking branch 'upstream/master' - -- update documentation of storeFiles and acceptDropsOn - -- Added credit to @eprochasson - -- *Merged pull-request:* "Should fix issue #45" [#50](https://github.com/zcfs/Meteor-CollectionFS/issues/50) ([eprochasson](https://github.com/eprochasson)) - -- *Fixed bug:* "file handlers not showing up in local demo" [#45](https://github.com/zcfs/Meteor-CollectionFS/issues/45) - -- *Merged pull-request:* "Update README.md" [#49](https://github.com/zcfs/Meteor-CollectionFS/issues/49) ([eprochasson](https://github.com/eprochasson)) - -- Added meteor style guide for jshint - -- fix package file - -- fixes and improvements to storeFiles() and acceptDropsOn() - -- Use a different saveAs shim - -- Merge branch 'master' of https://github.com/aldeed/Meteor-CollectionFS - -- Fixes and changes to support cfs changes - -- -"cfs" prefix, new helpers, improvements and fixes -include saveAs shim in the package so that download button helper can reliably call it - -- Add dependencies and files - -- Document storeFiles() and acceptDropsOn() - -- *Merged pull-request:* "Built-ins, fixes, etc." [#48](https://github.com/zcfs/Meteor-CollectionFS/issues/48) ([aldeed](https://github.com/aldeed)) - -- Add the new files to the package manifest - -- Add underscore as dependency. It seems that Meteor may soon remove underscore from the core. - -- Minor changes to support fileHanders() and fileFilter() function changes - -- Copy in numeral.js for use by the built-in handlebar helper that displays file size in human readable format. This means the helper supports any of the format strings supported by numeral.js for file sizes. - -- -Add fileFilter() function to specify allowed and disallowed files per collectionFS, based on extensions and/or content types -Add fileIsAllowed() function to easily check whether a particular file is allowed based on the rules set up by fileFilter() -Change all of the passthrough functions (find, findOne, update, remove, allow, deny) to pass through all function arguments more simply and more safely. This allows, for example, using find() instead of find({}). -Change fileHandlers() to extend the object whenever called, which means you can safely call it more than once -Add several utility functions for use in either client or server code - -- -Add storeFiles API -Check that files are allowed by fileFilter before saving -Add acceptDropsOn API -Use .depend() instead of Deps throughout -Pull out _getProgress calc to use in two places -Add isUploading API -Improve isDownloading code - -- New file to hold built-in handlebars helpers, including several initial helpers - -- New file manager example app showing how to use new features, built-in handlebars helpers, etc. - -- *Merged pull-request:* "Minor doc correction" [#47](https://github.com/zcfs/Meteor-CollectionFS/issues/47) ([aldeed](https://github.com/aldeed)) - -- *Merged pull-request:* "Documentation Improvement" [#46](https://github.com/zcfs/Meteor-CollectionFS/issues/46) ([aldeed](https://github.com/aldeed)) - -- Extensively revised README - -Patches by GitHub users [@aldeed](https://github.com/aldeed), [@eprochasson](https://github.com/eprochasson). - -## [v0.2.3] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.2.3) -#### 04/05/13 by Morten Henriksen -- *Fixed bug:* "Binary File Transfers Corrupted? Truncated?" [#41](https://github.com/zcfs/Meteor-CollectionFS/issues/41) - -## [v0.2.2] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.2.2) -#### 03/05/13 by Morten Henriksen -- updated scope for serverConsole - -- *Fixed bug:* "Error when using fresh meteor install" [#40](https://github.com/zcfs/Meteor-CollectionFS/issues/40) - -- more text edits - -- Minor text edits - -- Add credit to README - -- *Merged pull-request:* "Option for file encoding" [#36](https://github.com/zcfs/Meteor-CollectionFS/issues/36) ([nhibner](https://github.com/nhibner)) - -- Typo fix. - -- Updated documentation (added encoding to the fileRecord structure). - -- File encoding is stored in the fileRecord. - -- Allow the user to specify an encoding for the buffer when storing on the server. - -- *Merged pull-request:* "Fix backwards incompatibility" [#33](https://github.com/zcfs/Meteor-CollectionFS/issues/33) ([mitar](https://github.com/mitar)) - -- Fix backwards incompatibility. - -Patches by GitHub users [@nhibner](https://github.com/nhibner), [@mitar](https://github.com/mitar). - -## [v0.2.1] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.2.1) -#### 08/04/13 by Morten Henriksen -- Minor fixes, added dragndrop, minor refractoring - -- Only work on completed files - -## [v0.2.0] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.2.0) -#### 06/04/13 by Morten Henriksen -- Bump to 0.2.0 - Nice - -- Big speed and refractoring - -## [v0.1.9] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.9) -#### 31/03/13 by Morten Henriksen -- Added some more doc, deprecated autosubscribe to autopublish instead - -## [v0.1.8] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.8) -#### 31/03/13 by Morten Henriksen -- Added maxFilehandlers to the doc - -## [(origin/devel-old, origin/devel-#27-fixed] (https://github.com/zcfs/Meteor-CollectionFS/tree/(origin/devel-old, origin/devel-#27-fixed) -#### 31/03/13 by Morten Henriksen -- Added documentation by @petrocket - -- Got filehandlers up and running in bundles - -- Make a seperate thread + connection foreach collectionFS - -## [v0.1.7] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.7) -#### 14/03/13 by Morten Henriksen -## [v0.1.6] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.6) -#### 13/01/13 by Morten Henriksen -- Converted .length to string to cope with Meteor use of underscore - -## [(origin/devel-server-cache] (https://github.com/zcfs/Meteor-CollectionFS/tree/(origin/devel-server-cache) -#### 11/01/13 by Morten Henriksen -## [v0.1.5] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.5) -#### 11/01/13 by Morten Henriksen -- On going tests - db updates gone, requires refresh to commit changes to db - guess some que not working - -- removed setTimeout when spawn == 1 - -## [v0.1.4] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.4) -#### 08/01/13 by Morten Henriksen -## [v0.1.3] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.3) -#### 08/01/13 by Morten Henriksen -## [v0.1.2] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.2) -#### 08/01/13 by Morten Henriksen -## [v0.1.1] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.1) -#### 08/01/13 by Morten Henriksen -- Big one, added fileHandler to create cashed versions of the file - -- added made with Meteor in fileHandler example - -- corrected param bug in find and findOne - -- minor fix and update - -- Corrected install guide to use Meteorite - -## [v0.1.0] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1.0) -#### 07/01/13 by Morten Henriksen -## [v0.1] (https://github.com/zcfs/Meteor-CollectionFS/tree/v0.1) -#### 07/01/13 by Morten Henriksen -- updated file strukture and example - -- Restructure to package system - -- Refractoring filenames and edit package.js - -- Package.js added - -- Added smart.json for Atmosphere packages - Not tested! - -- Readme styling corrected - -- Added comments to the upload, storeFile - -- StoreFile should return fileId or null - -- Added notes about security - -- Added only owner can resume, makes sense for now - -- Added how to make a download... - -- Changed project title git - -- And some more corrections - -- More readme text - -- Added some short reference - -- some more md - -- Initial commit - diff --git a/packages/wekan-cfs-standard-packages/LICENSE.md b/packages/wekan-cfs-standard-packages/LICENSE.md deleted file mode 100644 index e49ce11bc..000000000 --- a/packages/wekan-cfs-standard-packages/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013-2015 [@raix](https://github.com/raix), aka Morten N.O. Nørgaard Henriksen, mh@gi-software.com - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/wekan-cfs-standard-packages/README.md b/packages/wekan-cfs-standard-packages/README.md deleted file mode 100644 index ce2fa69d7..000000000 --- a/packages/wekan-cfs-standard-packages/README.md +++ /dev/null @@ -1,16 +0,0 @@ -wekan-cfs-standard-packages -========================= - -This packege serves as a wrapper for several other packages and has no functionality in itself: - -* wekan-cfs-standard-packages (implies some component packages) - * wekan-cfs-base-package - * wekan-cfs-file - * wekan-cfs-collection - * wekan-cfs-collection-filters - * wekan-cfs-access-point - * wekan-cfs-worker - * wekan-cfs-upload-http - -Refer to the [CollectionFS](https://github.com/zcfs/Meteor-CollectionFS) -documentation for more information. diff --git a/packages/wekan-cfs-standard-packages/package.js b/packages/wekan-cfs-standard-packages/package.js deleted file mode 100644 index cf1a8da05..000000000 --- a/packages/wekan-cfs-standard-packages/package.js +++ /dev/null @@ -1,42 +0,0 @@ -Package.describe({ - git: 'https://github.com/zcfs/Meteor-CollectionFS.git', - name: 'wekan-cfs-standard-packages', - version: '0.5.10', - summary: 'Filesystem for Meteor, collectionFS' -}); - -Package.onUse(function(api) { - // Rig the collectionFS package v2 - api.imply([ - // Base util rigs the basis for the FS scope and some general helper mehtods - 'wekan-cfs-base-package@0.0.30', - // Want to make use of the file object and its api, yes! - 'wekan-cfs-file@0.1.17', - // Add the FS.Collection to keep track of everything - 'wekan-cfs-collection@0.5.5', - // Support filters for easy rules about what may be inserted - 'wekan-cfs-collection-filters@0.2.4', - // Add the option to have ddp and http access point - 'wekan-cfs-access-point@0.1.49', - // We might also want to have the server create copies of our files? - 'wekan-cfs-worker@0.1.5', - // By default we want to support uploads over HTTP - 'wekan-cfs-upload-http@0.0.20', - ]); -}); - -Package.onTest(function (api) { - api.use('wekan-cfs-standard-packages'); - api.use('test-helpers@1.0.0', 'server'); - api.use([ - 'tinytest@1.0.0', - 'underscore@1.0.0', - 'ejson@1.0.0', - 'ordered-dict@1.0.0', - 'random@1.0.0', - 'tracker@1.0.3' - ]); - - api.addFiles('tests/server-tests.js', 'server'); - api.addFiles('tests/client-tests.js', 'client'); -}); diff --git a/packages/wekan-cfs-standard-packages/tests/client-tests.js b/packages/wekan-cfs-standard-packages/tests/client-tests.js deleted file mode 100644 index 08b9671ac..000000000 --- a/packages/wekan-cfs-standard-packages/tests/client-tests.js +++ /dev/null @@ -1,25 +0,0 @@ -Tinytest.add('FS.Collection - client - test environment', function(test) { - test.isTrue(typeof FS.Utility !== 'undefined', 'test environment not initialized FS.Utility'); - test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection'); - test.isTrue(typeof FS.File !== 'undefined', 'test environment not initialized FS.File'); -}); - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-standard-packages/tests/server-tests.js b/packages/wekan-cfs-standard-packages/tests/server-tests.js deleted file mode 100644 index edf4c1624..000000000 --- a/packages/wekan-cfs-standard-packages/tests/server-tests.js +++ /dev/null @@ -1,25 +0,0 @@ -Tinytest.add('FS.Collection - server - test environment', function(test) { - test.isTrue(typeof FS.Utility !== 'undefined', 'test environment not initialized FS.Utility'); - test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection'); - test.isTrue(typeof FS.File !== 'undefined', 'test environment not initialized FS.File'); -}); - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-storage-adapter/.travis.yml b/packages/wekan-cfs-storage-adapter/.travis.yml deleted file mode 100644 index 6a4640033..000000000 --- a/packages/wekan-cfs-storage-adapter/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - "0.10" -before_install: - - "curl -L http://git.io/s0Zu-w | /bin/sh" \ No newline at end of file diff --git a/packages/wekan-cfs-storage-adapter/LICENSE.md b/packages/wekan-cfs-storage-adapter/LICENSE.md deleted file mode 100644 index 51e60c3d0..000000000 --- a/packages/wekan-cfs-storage-adapter/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013-2015 [@raix](https://github.com/raix) and [@aldeed](https://github.com/aldeed), aka Morten N.O. Nørgaard Henriksen, mh@gi-software.com - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/wekan-cfs-storage-adapter/README.md b/packages/wekan-cfs-storage-adapter/README.md deleted file mode 100644 index bc8e464a1..000000000 --- a/packages/wekan-cfs-storage-adapter/README.md +++ /dev/null @@ -1,7 +0,0 @@ -wekan-cfs-storage-adapter -========================= - -This is a Meteor package used by -[CollectionFS](https://github.com/zcfs/Meteor-CollectionFS). - -You don't need to manually add this package to your app. It is used by other packages to create various storage adapters. diff --git a/packages/wekan-cfs-storage-adapter/api.md b/packages/wekan-cfs-storage-adapter/api.md deleted file mode 100644 index e69de29bb..000000000 diff --git a/packages/wekan-cfs-storage-adapter/internal.api.md b/packages/wekan-cfs-storage-adapter/internal.api.md deleted file mode 100644 index ae9f64ad3..000000000 --- a/packages/wekan-cfs-storage-adapter/internal.api.md +++ /dev/null @@ -1,101 +0,0 @@ -> File: ["storageAdapter.server.js"](storageAdapter.server.js) -> Where: {server} - -- -############################################################################# - -STORAGE ADAPTER - -############################################################################# - -#### *self*.insert(fsFile, [options], [callback])  Server #### -``` -Attempts to insert a file into the store, first running the beforeSave -function for the store if there is one. If there is a temporary failure, -returns (or passes to the second argument of the callback) `null`. If there -is a permanant failure or the beforeSave function returns `false`, returns -`false`. If the file is successfully stored, returns an object with file -info that the FS.Collection can save. -Also updates the `files` collection for this store to save info about this -file. -``` -- -*This method __insert__ is defined in `self`* - -__Arguments__ - -* __fsFile__ *{[FS.File](#FS.File)}* -The FS.File instance to be stored. -* __options__ *{Object}* (Optional) -Options (currently unused) -* __callback__ *{Function}* (Optional) -If not provided, will block and return file info. - -- - - - - -> ```self.insert = function(fsFile, options, callback) { ...``` [storageAdapter.server.js:169](storageAdapter.server.js#L169) - -- - -#### *self*.update(fsFile, [options], [callback])  Server #### -``` -Attempts to update a file in the store, first running the beforeSave -function for the store if there is one. If there is a temporary failure, -returns (or passes to the second argument of the callback) `null`. If there -is a permanant failure or the beforeSave function returns `false`, returns -`false`. If the file is successfully stored, returns an object with file -info that the FS.Collection can save. -Also updates the `files` collection for this store to save info about this -file. -``` -- -*This method __update__ is defined in `self`* - -__Arguments__ - -* __fsFile__ *{[FS.File](#FS.File)}* -The FS.File instance to be stored. -* __options__ *{Object}* (Optional) -Options (currently unused) -* __callback__ *{Function}* (Optional) -If not provided, will block and return file info. - -- - - - - -> ```self.update = function(fsFile, options, callback) { ...``` [storageAdapter.server.js:264](storageAdapter.server.js#L264) - -- - -#### *self*.remove(fsFile, [options], [callback])  Server #### -``` -Attempts to remove a file from the store. Returns true if removed, or false. -Also removes file info from the `files` collection for this store. -``` -- -*This method __remove__ is defined in `self`* - -__Arguments__ - -* __fsFile__ *{[FS.File](#FS.File)}* -The FS.File instance to be stored. -* __options__ *{Object}* (Optional) -Options - - __ignoreMissing__ *{Boolean}* (Optional) -Set true to treat missing files as a successful deletion. Otherwise throws an error. -* __callback__ *{Function}* (Optional) -If not provided, will block and return true or false - -- - - - - -> ```self.remove = function(fsFile, options, callback) { ...``` [storageAdapter.server.js:321](storageAdapter.server.js#L321) - -- diff --git a/packages/wekan-cfs-storage-adapter/package.js b/packages/wekan-cfs-storage-adapter/package.js deleted file mode 100644 index 92838d44a..000000000 --- a/packages/wekan-cfs-storage-adapter/package.js +++ /dev/null @@ -1,50 +0,0 @@ -Package.describe({ - git: 'https://github.com/zcfs/Meteor-cfs-storage-adapter.git', - name: 'wekan-cfs-storage-adapter', - version: '0.2.4', - summary: 'CollectionFS, Class for creating Storage adapters' -}); - -Npm.depends({ - 'length-stream': '0.1.1' -}); - -Package.onUse(function(api) { - api.versionsFrom('1.0'); - - api.use([ - // CFS - 'wekan-cfs-base-package@0.0.30', - // Core - 'deps', - 'check', - 'livedata', - 'mongo-livedata', - 'ejson', - // Other - 'raix:eventemitter@0.1.1' - ]); - - // We want to make sure that its added to scope for now if installed. - // We have set a deprecation warning on the transform scope - api.use('wekan-cfs-graphicsmagick@0.0.17', 'server', { weak: true }); - - api.addFiles([ - 'storageAdapter.client.js' - ], 'client'); - - api.addFiles([ - 'storageAdapter.server.js', - 'transform.server.js' - ], 'server'); -}); - -Package.onTest(function (api) { - api.use('wekan-cfs-storage-adapter'); - api.use('test-helpers', 'server'); - api.use(['tinytest', 'underscore', 'ejson', 'ordered-dict', - 'random', 'deps']); - - api.addFiles('tests/server-tests.js', 'server'); - api.addFiles('tests/client-tests.js', 'client'); -}); diff --git a/packages/wekan-cfs-storage-adapter/storageAdapter.client.js b/packages/wekan-cfs-storage-adapter/storageAdapter.client.js deleted file mode 100644 index 90c87d00e..000000000 --- a/packages/wekan-cfs-storage-adapter/storageAdapter.client.js +++ /dev/null @@ -1,37 +0,0 @@ -/* global FS, _storageAdapters:true, EventEmitter */ - -// ############################################################################# -// -// STORAGE ADAPTER -// -// ############################################################################# - -_storageAdapters = {}; - -FS.StorageAdapter = function(name, options, api) { - var self = this; - - // Check the api - if (typeof api === 'undefined') { - throw new Error('FS.StorageAdapter please define an api'); - } - - // store reference for easy lookup by name - if (typeof _storageAdapters[name] !== 'undefined') { - throw new Error('Storage name already exists: "' + name + '"'); - } else { - _storageAdapters[name] = self; - } - - // extend self with options and other info - FS.Utility.extend(this, options || {}, { - name: name - }); - - // XXX: TODO, add upload feature here... - // we default to ddp upload but really let the SA like S3Cloud overwrite to - // implement direct client to s3 upload - -}; - -FS.StorageAdapter.prototype = new EventEmitter(); diff --git a/packages/wekan-cfs-storage-adapter/storageAdapter.server.js b/packages/wekan-cfs-storage-adapter/storageAdapter.server.js deleted file mode 100644 index 5af1bcbf5..000000000 --- a/packages/wekan-cfs-storage-adapter/storageAdapter.server.js +++ /dev/null @@ -1,269 +0,0 @@ -/* global FS, _storageAdapters:true, EventEmitter */ - -// ############################################################################# -// -// STORAGE ADAPTER -// -// ############################################################################# -_storageAdapters = {}; - -FS.StorageAdapter = function(storeName, options, api) { - var self = this, fileKeyMaker; - options = options || {}; - - // If storeName is the only argument, a string and the SA already found - // we will just return that SA - if (arguments.length === 1 && storeName === '' + storeName && - typeof _storageAdapters[storeName] !== 'undefined') - return _storageAdapters[storeName]; - - // Verify that the storage adapter defines all the necessary API methods - if (typeof api === 'undefined') { - throw new Error('FS.StorageAdapter please define an api'); - } - - FS.Utility.each('fileKey,remove,typeName,createReadStream,createWriteStream'.split(','), function(name) { - if (typeof api[name] === 'undefined') { - throw new Error('FS.StorageAdapter please define an api. "' + name + '" ' + (api.typeName || '')); - } - }); - - // Create an internal namespace, starting a name with underscore is only - // allowed for stores marked with options.internal === true - if (options.internal !== true && storeName[0] === '_') { - throw new Error('A storage adapter name may not begin with "_"'); - } - - if (storeName.indexOf('.') !== -1) { - throw new Error('A storage adapter name may not contain a "."'); - } - - // store reference for easy lookup by storeName - if (typeof _storageAdapters[storeName] !== 'undefined') { - throw new Error('Storage name already exists: "' + storeName + '"'); - } else { - _storageAdapters[storeName] = self; - } - - // User can customize the file key generation function - if (typeof options.fileKeyMaker === "function") { - fileKeyMaker = options.fileKeyMaker; - } else { - fileKeyMaker = api.fileKey; - } - - // User can provide a function to adjust the fileObj - // before it is written to the store. - var beforeWrite = options.beforeWrite; - - // extend self with options and other info - FS.Utility.extend(this, options, { - name: storeName, - typeName: api.typeName - }); - - // Create a nicer abstracted adapter interface - self.adapter = {}; - - self.adapter.fileKey = function(fileObj) { - return fileKeyMaker(fileObj); - }; - - // Return readable stream for fileKey - self.adapter.createReadStreamForFileKey = function(fileKey, options) { - if (FS.debug) console.log('createReadStreamForFileKey ' + storeName); - return FS.Utility.safeStream( api.createReadStream(fileKey, options) ); - }; - - // Return readable stream for fileObj - self.adapter.createReadStream = function(fileObj, options) { - if (FS.debug) console.log('createReadStream ' + storeName); - if (self.internal) { - // Internal stores take a fileKey - return self.adapter.createReadStreamForFileKey(fileObj, options); - } - return FS.Utility.safeStream( self._transform.createReadStream(fileObj, options) ); - }; - - function logEventsForStream(stream) { - if (FS.debug) { - stream.on('stored', function() { - console.log('-----------STORED STREAM', storeName); - }); - - stream.on('close', function() { - console.log('-----------CLOSE STREAM', storeName); - }); - - stream.on('end', function() { - console.log('-----------END STREAM', storeName); - }); - - stream.on('finish', function() { - console.log('-----------FINISH STREAM', storeName); - }); - - stream.on('error', function(error) { - console.log('-----------ERROR STREAM', storeName, error && (error.message || error.code)); - }); - } - } - - // Return writeable stream for fileKey - self.adapter.createWriteStreamForFileKey = function(fileKey, options) { - if (FS.debug) console.log('createWriteStreamForFileKey ' + storeName); - var writeStream = FS.Utility.safeStream( api.createWriteStream(fileKey, options) ); - - logEventsForStream(writeStream); - - return writeStream; - }; - - // Return writeable stream for fileObj - self.adapter.createWriteStream = function(fileObj, options) { - if (FS.debug) console.log('createWriteStream ' + storeName + ', internal: ' + !!self.internal); - - if (self.internal) { - // Internal stores take a fileKey - return self.adapter.createWriteStreamForFileKey(fileObj, options); - } - - // If we haven't set name, type, or size for this version yet, - // set it to same values as original version. We don't save - // these to the DB right away because they might be changed - // in a transformWrite function. - if (!fileObj.name({store: storeName})) { - fileObj.name(fileObj.name(), {store: storeName, save: false}); - } - if (!fileObj.type({store: storeName})) { - fileObj.type(fileObj.type(), {store: storeName, save: false}); - } - if (!fileObj.size({store: storeName})) { - fileObj.size(fileObj.size(), {store: storeName, save: false}); - } - - // Call user function to adjust file metadata for this store. - // We support updating name, extension, and/or type based on - // info returned in an object. Or `fileObj` could be - // altered directly within the beforeWrite function. - if (beforeWrite) { - var fileChanges = beforeWrite(fileObj); - if (typeof fileChanges === "object") { - if (fileChanges.extension) { - fileObj.extension(fileChanges.extension, {store: storeName, save: false}); - } else if (fileChanges.name) { - fileObj.name(fileChanges.name, {store: storeName, save: false}); - } - if (fileChanges.type) { - fileObj.type(fileChanges.type, {store: storeName, save: false}); - } - } - } - - var writeStream = FS.Utility.safeStream( self._transform.createWriteStream(fileObj, options) ); - - logEventsForStream(writeStream); - - // Its really only the storage adapter who knows if the file is uploaded - // - // We have to use our own event making sure the storage process is completed - // this is mainly - writeStream.safeOn('stored', function(result) { - if (typeof result.fileKey === 'undefined') { - throw new Error('SA ' + storeName + ' type ' + api.typeName + ' did not return a fileKey'); - } - if (FS.debug) console.log('SA', storeName, 'stored', result.fileKey); - // Set the fileKey - fileObj.copies[storeName].key = result.fileKey; - - // Update the size, as provided by the SA, in case it was changed by stream transformation - if (typeof result.size === "number") { - fileObj.copies[storeName].size = result.size; - } - - // Set last updated time, either provided by SA or now - fileObj.copies[storeName].updatedAt = result.storedAt || new Date(); - - // If the file object copy havent got a createdAt then set this - if (typeof fileObj.copies[storeName].createdAt === 'undefined') { - fileObj.copies[storeName].createdAt = fileObj.copies[storeName].updatedAt; - } - - fileObj._saveChanges(storeName); - - // There is code in transform that may have set the original file size, too. - fileObj._saveChanges('_original'); - }); - - // Emit events from SA - writeStream.once('stored', function(/*result*/) { - // XXX Because of the way stores inherit from SA, this will emit on every store. - // Maybe need to rewrite the way we inherit from SA? - var emitted = self.emit('stored', storeName, fileObj); - if (FS.debug && !emitted) { - console.log(fileObj.name() + ' was successfully stored in the ' + storeName + ' store. You are seeing this informational message because you enabled debugging and you have not defined any listeners for the "stored" event on this store.'); - } - }); - - writeStream.on('error', function(error) { - // XXX We could wrap and clarify error - // XXX Because of the way stores inherit from SA, this will emit on every store. - // Maybe need to rewrite the way we inherit from SA? - var emitted = self.emit('error', storeName, error, fileObj); - if (FS.debug && !emitted) { - console.log(error); - } - }); - - return writeStream; - }; - - //internal - self._removeAsync = function(fileKey, callback) { - // Remove the file from the store - api.remove.call(self, fileKey, callback); - }; - - /** - * @method FS.StorageAdapter.prototype.remove - * @public - * @param {FS.File} fsFile The FS.File instance to be stored. - * @param {Function} [callback] If not provided, will block and return true or false - * - * Attempts to remove a file from the store. Returns true if removed or not - * found, or false if the file couldn't be removed. - */ - self.adapter.remove = function(fileObj, callback) { - if (FS.debug) console.log("---SA REMOVE"); - - // Get the fileKey - var fileKey = (fileObj instanceof FS.File) ? self.adapter.fileKey(fileObj) : fileObj; - - if (callback) { - return self._removeAsync(fileKey, FS.Utility.safeCallback(callback)); - } else { - return Meteor.wrapAsync(self._removeAsync)(fileKey); - } - }; - - self.remove = function(fileObj, callback) { - // Add deprecation note - console.warn('Storage.remove is deprecating, use "Storage.adapter.remove"'); - return self.adapter.remove(fileObj, callback); - }; - - if (typeof api.init === 'function') { - Meteor.wrapAsync(api.init.bind(self))(); - } - - // This supports optional transformWrite and transformRead - self._transform = new FS.Transform({ - adapter: self.adapter, - // Optional transformation functions: - transformWrite: options.transformWrite, - transformRead: options.transformRead - }); - -}; - -Npm.require('util').inherits(FS.StorageAdapter, EventEmitter); diff --git a/packages/wekan-cfs-storage-adapter/tests/client-tests.js b/packages/wekan-cfs-storage-adapter/tests/client-tests.js deleted file mode 100644 index efe5a3abb..000000000 --- a/packages/wekan-cfs-storage-adapter/tests/client-tests.js +++ /dev/null @@ -1,44 +0,0 @@ -function equals(a, b) { - return !!(EJSON.stringify(a) === EJSON.stringify(b)); -} - -Tinytest.add('cfs-storage-adapter - client - test environment', function(test) { - test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection'); - test.isTrue(typeof CFSErrorType !== 'undefined', 'test environment not initialized CFSErrorType'); -}); - -/* - * FS.File Client Tests - * - * construct FS.File with no arguments - * construct FS.File passing in File - * construct FS.File passing in Blob - * load blob into FS.File and then call FS.File.toDataUrl - * call FS.File.setDataFromBinary, then FS.File.getBlob(); make sure correct data is returned - * load blob into FS.File and then call FS.File.getBinary() with and without start/end; make sure correct data is returned - * construct FS.File, set FS.File.collectionName to a CFS name, and then test FS.File.update/remove/get/put/del/url - * set FS.File.name to a filename and test that FS.File.getExtension() returns the extension - * load blob into FS.File and make sure FS.File.saveLocal initiates a download (possibly can't do automatically) - * - */ - - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-storage-adapter/tests/server-tests.js b/packages/wekan-cfs-storage-adapter/tests/server-tests.js deleted file mode 100644 index b25036569..000000000 --- a/packages/wekan-cfs-storage-adapter/tests/server-tests.js +++ /dev/null @@ -1,49 +0,0 @@ -function equals(a, b) { - return !!(EJSON.stringify(a) === EJSON.stringify(b)); -} - -Tinytest.add('cfs-storage-adapter - server - test environment', function(test) { - test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection'); - test.isTrue(typeof CFSErrorType !== 'undefined', 'test environment not initialized CFSErrorType'); -}); - -/* - * FS.File Server Tests - * - * construct FS.File with no arguments - * load data with FS.File.setDataFromBuffer - * load data with FS.File.setDataFromBinary - * load data and then call FS.File.toDataUrl with and without callback - * load buffer into FS.File and then call FS.File.getBinary with and without start/end; make sure correct data is returned - * construct FS.File, set FS.File.collectionName to a CFS name, and then test FS.File.update/remove/get/put/del/url - * (call these with and without callback to test sync vs. async) - * set FS.File.name to a filename and test that FS.File.getExtension() returns the extension - * - * - * FS.Collection Server Tests - * - * Make sure options.filter is respected - * - * - */ - - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-storage-adapter/transform.server.js b/packages/wekan-cfs-storage-adapter/transform.server.js deleted file mode 100644 index 8936ddc3f..000000000 --- a/packages/wekan-cfs-storage-adapter/transform.server.js +++ /dev/null @@ -1,119 +0,0 @@ -/* global FS */ - -var PassThrough = Npm.require('stream').PassThrough; -var lengthStream = Npm.require('length-stream'); - -FS.Transform = function(options) { - var self = this; - - options = options || {}; - - if (!(self instanceof FS.Transform)) - throw new Error('FS.Transform must be called with the "new" keyword'); - - if (!options.adapter) - throw new Error('Transform expects option.adapter to be a storage adapter'); - - self.storage = options.adapter; - - // Fetch the transformation functions if any - self.transformWrite = options.transformWrite; - self.transformRead = options.transformRead; -}; - -// Allow packages to add scope -FS.Transform.scope = {}; - -// The transformation stream triggers an "stored" event when data is stored into -// the storage adapter -FS.Transform.prototype.createWriteStream = function(fileObj) { - var self = this; - - // Get the file key - var fileKey = self.storage.fileKey(fileObj); - - // Rig write stream - var destinationStream = self.storage.createWriteStreamForFileKey(fileKey, { - // Not all SA's can set these options and cfs dont depend on setting these - // but its nice if other systems are accessing the SA that some of the data - // is also available to those - aliases: [fileObj.name()], - contentType: fileObj.type(), - metadata: fileObj.metadata - }); - - // Pass through transformWrite function if provided - if (typeof self.transformWrite === 'function') { - - destinationStream = addPassThrough(destinationStream, function (ptStream, originalStream) { - // Rig transform - try { - self.transformWrite.call(FS.Transform.scope, fileObj, ptStream, originalStream); - // XXX: If the transform function returns a buffer should we stream that? - } catch(err) { - // We emit an error - should we throw an error? - console.warn('FS.Transform.createWriteStream transform function failed, Error: '); - throw err; - } - }); - - } - - // If original doesn't have size, add another PassThrough to get and set the size. - // This will run on size=0, too, which is OK. - // NOTE: This must come AFTER the transformWrite code block above. This might seem - // confusing, but by coming after it, this will actually be executed BEFORE the user's - // transform, which is what we need in order to be sure we get the original file - // size and not the transformed file size. - if (!fileObj.size()) { - destinationStream = addPassThrough(destinationStream, function (ptStream, originalStream) { - var lstream = lengthStream(function (fileSize) { - fileObj.size(fileSize, {save: false}); - }); - - ptStream.pipe(lstream).pipe(originalStream); - }); - } - - return destinationStream; -}; - -FS.Transform.prototype.createReadStream = function(fileObj, options) { - var self = this; - - // Get the file key - var fileKey = self.storage.fileKey(fileObj); - - // Rig read stream - var sourceStream = self.storage.createReadStreamForFileKey(fileKey, options); - - // Pass through transformRead function if provided - if (typeof self.transformRead === 'function') { - - sourceStream = addPassThrough(sourceStream, function (ptStream, originalStream) { - // Rig transform - try { - self.transformRead.call(FS.Transform.scope, fileObj, originalStream, ptStream); - } catch(err) { - //throw new Error(err); - // We emit an error - should we throw an error? - sourceStream.emit('error', 'FS.Transform.createReadStream transform function failed'); - } - }); - - } - - // We dont transform just normal SA interface - return sourceStream; -}; - -// Utility function to simplify adding layers of passthrough -function addPassThrough(stream, func) { - var pts = new PassThrough(); - // We pass on the special "stored" event for those listening - stream.on('stored', function(result) { - pts.emit('stored', result); - }); - func(pts, stream); - return pts; -} diff --git a/packages/wekan-cfs-temp-store/.travis.yml b/packages/wekan-cfs-temp-store/.travis.yml deleted file mode 100644 index 6a4640033..000000000 --- a/packages/wekan-cfs-temp-store/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - "0.10" -before_install: - - "curl -L http://git.io/s0Zu-w | /bin/sh" \ No newline at end of file diff --git a/packages/wekan-cfs-temp-store/CHANGELOG.md b/packages/wekan-cfs-temp-store/CHANGELOG.md deleted file mode 100644 index 3113b8e61..000000000 --- a/packages/wekan-cfs-temp-store/CHANGELOG.md +++ /dev/null @@ -1,169 +0,0 @@ -# Changelog - -## vCurrent -## [v0.1.2] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.1.2) -#### 17/12/14 by Morten Henriksen -## [v0.1.1] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.1.1) -#### 17/12/14 by Morten Henriksen -- mbr update, remove versions.json - -- Bump to version 0.1.1 - -## [v0.1.0] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.1.0) -#### 17/12/14 by Morten Henriksen -- mbr update versions and fix warnings - -- fix 0.9.1 package scope - -- don't rely on package names; fix for 0.9.1 - -- 0.9.1 support - -## [v0.0.29] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.29) -#### 28/08/14 by Morten Henriksen -- Meteor Package System Update - -## [v0.0.28] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.28) -#### 27/08/14 by Eric Dobbertin -- change package name to lowercase - -## [v0.0.27] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.27) -#### 17/06/14 by Eric Dobbertin -- add `FS.TempStore.removeAll` method - -## [v0.0.26] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.26) -#### 30/04/14 by Eric Dobbertin -## [v0.0.25] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.25) -#### 30/04/14 by Eric Dobbertin -- use third-party combined-stream node pkg as attempt to resolve pesky streaming issues - -## [v0.0.24] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.24) -#### 29/04/14 by Eric Dobbertin -- generate api docs - -- fileKey methods now expect an FS.File always, so we give them one - -- small FS.File API change - -## [v0.0.23] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.23) -#### 12/04/14 by Eric Dobbertin -- test for packages since we're assigning default error functions for stores - -## [v0.0.22] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.22) -#### 12/04/14 by Eric Dobbertin -- avoid errors if file already removed from temp store - -## [v0.0.21] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.21) -#### 12/04/14 by Eric Dobbertin -## [v0.0.20] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.20) -#### 08/04/14 by Eric Dobbertin -- cleanup stored/uploaded events and further improve chunk tracking - -## [v0.0.19] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.19) -#### 08/04/14 by Eric Dobbertin -- use internal tracking collection - -- Have TempStore set the size - -- Add the SA on stored result - -- allow unset chunkSum - -## [v0.0.18] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.18) -#### 06/04/14 by Eric Dobbertin -- delete chunkCount and chunkSize props from fileObj after upload is complete - -## [v0.0.17] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.17) -#### 06/04/14 by Eric Dobbertin -- We now wait to mount storage until it's needed (first upload begins); this ensures that we are able to accurately check for the cfs-worker package, which loads after this one. It also makes the code a bit cleaner. - -## [v0.0.16] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.16) -#### 04/04/14 by Morten Henriksen -- Temporary workaround: We currently we generate a mongoId if gridFS is used for TempStore - -- Note: At the moment tempStore will only use gridfs if no filesystem is installed - -## [v0.0.15] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.15) -#### 02/04/14 by Morten Henriksen -- Use the stored event and object instead (result object is not used at the moment - but we could store an id at some point) - -## [v0.0.14] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.14) -#### 31/03/14 by Eric Dobbertin -- use latest releases - -- use latest releases - -## [v0.0.13] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.13) -#### 31/03/14 by Morten Henriksen -- Try to use latest when using weak deps - -## [v0.0.12] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.12) -#### 30/03/14 by Morten Henriksen -## [v0.0.11] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.11) -#### 30/03/14 by Morten Henriksen -- Set noon callback - we just want the file gone - -## [v0.0.10] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.10) -#### 29/03/14 by Morten Henriksen -- add filesystem and gridfs as weak deps - -## [v0.0.9] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.9) -#### 29/03/14 by Morten Henriksen -- Add check to see if FS.TempStore.Storage is set - -## [v0.0.8] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.8) -#### 29/03/14 by Morten Henriksen -- Converting TempStore to use SA api - -## [v0.0.7] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.7) -#### 25/03/14 by Morten Henriksen -- use `new Date` - -- Have TempStore emit relevant events - -## [v0.0.6] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.6) -#### 23/03/14 by Morten Henriksen -- Rollback to specific git dependency - -- use collectionFS travis version force update - -## [v0.0.5] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.5) -#### 22/03/14 by Morten Henriksen -- try to fix travis test by using general package references - -## [v0.0.4] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.4) -#### 21/03/14 by Morten Henriksen -- fix chunk files not actually being deleted - -## [v0.0.3] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.3) -#### 18/03/14 by Morten Henriksen -- * TempStore is now an EventEmitter * progress event * uploaded * (start) should perhaps be created * remove * Added FS.TempStore.listParts - will return lookup object listing the parts already uploaded - -- Allow chunk to be undefined an thereby have the createWriteStream follow normal streaming api - -- Allow undefined in chunkPath - -- added comments - -- bug hunting - -- Add streaming WIP - -- rename temp store collection to 'cfs.tempstore' - -- fix ensureForFile - -- track tempstore chunks in our own collection rather than in the file object - -- change to accept buffer; less converting - -- prevent bytesUploaded from getting bigger than size - -## [v0.0.2] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.2) -#### 15/02/14 by Morten Henriksen -- fix typo - -## [v0.0.1] (https://github.com/zcfs/Meteor-cfs-tempstore/tree/v0.0.1) -#### 13/02/14 by Morten Henriksen -- init commit - diff --git a/packages/wekan-cfs-temp-store/LICENSE.md b/packages/wekan-cfs-temp-store/LICENSE.md deleted file mode 100644 index 1a3820821..000000000 --- a/packages/wekan-cfs-temp-store/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 [@raix](https://github.com/raix) and [@aldeed](https://github.com/aldeed), aka Morten N.O. Nørgaard Henriksen, mh@gi-software.com - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/wekan-cfs-temp-store/README.md b/packages/wekan-cfs-temp-store/README.md deleted file mode 100644 index e0d8f0c48..000000000 --- a/packages/wekan-cfs-temp-store/README.md +++ /dev/null @@ -1,24 +0,0 @@ -wekan-cfs-tempstore -========================= - -This is a Meteor package used by -[CollectionFS](https://github.com/zcfs/Meteor-CollectionFS). It provides -an API for quickly storing chunks of file data in temporary files. If also supports deleting those chunks, and combining them into one -binary object and attaching it to an FS.File instance. - -You don't need to manually add this package to your app, but you could replace -this package with your own if you want to handle temporary storage in another -way. - -> `FS.TempStore` uses the `wekan-cfs-storage-adapter` compatible Storage Adapters, both `FS.Store.FileSystem` and `FS.Store.GridFS` will be defaulted. *for more information read the [internal.api.md](internal.api.md)* - -##Documentation -[API Documentation](api.md) - -##Contribute -Here's the [complete API documentation](internal.api.md), including private methods. - -Update docs, `npm install docmeteor` -```bash -$ docmeteor -``` \ No newline at end of file diff --git a/packages/wekan-cfs-temp-store/api.md b/packages/wekan-cfs-temp-store/api.md deleted file mode 100644 index cbb34632e..000000000 --- a/packages/wekan-cfs-temp-store/api.md +++ /dev/null @@ -1,112 +0,0 @@ -## cfs-tempstore Public API ## - -CollectionFS, temporary storage - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -##Temporary Storage - -Temporary storage is used for chunked uploads until all chunks are received -and all copies have been made or given up. In some cases, the original file -is stored only in temporary storage (for example, if all copies do some -manipulation in beforeSave). This is why we use the temporary file as the -basis for each saved copy, and then remove it after all copies are saved. - -Every chunk is saved as an individual temporary file. This is safer than -attempting to write multiple incoming chunks to different positions in a -single temporary file, which can lead to write conflicts. - -Using temp files also allows us to easily resume uploads, even if the server -restarts, and to keep the working memory clear. -The FS.TempStore emits events that others are able to listen to -- - -### *fs*.TempStore {object}  Server ### - -*This property __TempStore__ is defined in `FS`* -it's an event emitter* - -> ```FS.TempStore = new EventEmitter();``` [tempStore.js:28](tempStore.js#L28) - - - -- -We will not mount a storage adapter until needed. This allows us to check for the -existance of FS.FileWorker, which is loaded after this package because it -depends on this package. - -- -XXX: TODO -FS.TempStore.on('stored', function(fileObj, chunkCount, result) { -This should work if we pass on result from the SA on stored event... -fileObj.update({ $set: { chunkSum: 1, chunkCount: chunkCount, size: result.size } }); -}); -Stream implementation -- - -### *fsTempstore*.removeFile(fileObj)  Server ### - -*This method __removeFile__ is defined in `FS.TempStore`* - -__Arguments__ - -* __fileObj__ *{[FS.File](#FS.File)}* - -This function removes the file from tempstorage - it cares not if file is -already removed or not found, goal is reached anyway. - -> ```FS.TempStore.removeFile = function(fileObj) { ...``` [tempStore.js:169](tempStore.js#L169) - - -- - -### *fsTempstore*.createWriteStream(fileObj, [options])  Server ### - -*This method __createWriteStream__ is defined in `FS.TempStore`* - -__Arguments__ - -* __fileObj__ *{[FS.File](#FS.File)}* - - File to store in temporary storage - -* __options__ *{[Number ](#Number )|[ String](# String)}* (Optional) - -__Returns__ *{Stream}* -Writeable stream - - -`options` of different types mean differnt things: -`undefined` We store the file in one part -(Normal server-side api usage)* -`Number` the number is the part number total -(multipart uploads will use this api)* -`String` the string is the name of the `store` that wants to store file data -(stores that want to sync their data to the rest of the files stores will use this)* - -> Note: fileObj must be mounted on a `FS.Collection`, it makes no sense to store otherwise - -> ```FS.TempStore.createWriteStream = function(fileObj, options) { ...``` [tempStore.js:217](tempStore.js#L217) - - -- - -### *fsTempstore*.createReadStream(fileObj)  Server ### - -*This method __createReadStream__ is defined in `FS.TempStore`* - -__Arguments__ - -* __fileObj__ *{[FS.File](#FS.File)}* - - The file to read - - -__Returns__ *{Stream}* -Returns readable stream - - - -> ```FS.TempStore.createReadStream = function(fileObj) { ...``` [tempStore.js:313](tempStore.js#L313) - - diff --git a/packages/wekan-cfs-temp-store/internal.api.md b/packages/wekan-cfs-temp-store/internal.api.md deleted file mode 100644 index 4b6e1f6d5..000000000 --- a/packages/wekan-cfs-temp-store/internal.api.md +++ /dev/null @@ -1,225 +0,0 @@ -## Public and Private API ## - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -*** - -__File: ["tempStore.js"](tempStore.js) Where: {server}__ - -*** - -##Temporary Storage - -Temporary storage is used for chunked uploads until all chunks are received -and all copies have been made or given up. In some cases, the original file -is stored only in temporary storage (for example, if all copies do some -manipulation in beforeSave). This is why we use the temporary file as the -basis for each saved copy, and then remove it after all copies are saved. - -Every chunk is saved as an individual temporary file. This is safer than -attempting to write multiple incoming chunks to different positions in a -single temporary file, which can lead to write conflicts. - -Using temp files also allows us to easily resume uploads, even if the server -restarts, and to keep the working memory clear. -The FS.TempStore emits events that others are able to listen to -- - -### *fs*.TempStore {object}  Server ### - -*This property __TempStore__ is defined in `FS`* -it's an event emitter* - -> ```FS.TempStore = new EventEmitter();``` [tempStore.js:28](tempStore.js#L28) - - -- - -### *fsTempstore*.Storage {StorageAdapter}  Server ### - -*This property is private* -*This property __Storage__ is defined in `FS.TempStore`* - -This property is set to either `FS.Store.FileSystem` or `FS.Store.GridFS` - -__When and why:__ -We normally default to `cfs-filesystem` unless its not installed. *(we default to gridfs if installed)* -But if `cfs-gridfs` and `cfs-worker` is installed we default to `cfs-gridfs` - -If `cfs-gridfs` and `cfs-filesystem` is not installed we log a warning. -the user can set `FS.TempStore.Storage` them selfs eg.: -```js -// Its important to set `internal: true` this lets the SA know that we -// are using this internally and it will give us direct SA api -FS.TempStore.Storage = new FS.Store.GridFS('_tempstore', { internal: true }); -``` - -> Note: This is considered as `advanced` use, its not a common pattern. - -> ```FS.TempStore.Storage = null;``` [tempStore.js:54](tempStore.js#L54) - - - -- -We will not mount a storage adapter until needed. This allows us to check for the -existance of FS.FileWorker, which is loaded after this package because it -depends on this package. - -- -XXX: TODO -FS.TempStore.on('stored', function(fileObj, chunkCount, result) { -This should work if we pass on result from the SA on stored event... -fileObj.update({ $set: { chunkSum: 1, chunkCount: chunkCount, size: result.size } }); -}); -Stream implementation -- - -### _chunkPath([n])  Server ### - -*This method is private* - -__Arguments__ - -* __n__ *{Number}* (Optional) - - Chunk number - - -__Returns__ *{String}* -Chunk naming convention - - -> ```_chunkPath = function(n) { ...``` [tempStore.js:104](tempStore.js#L104) - - -- - -### _fileReference(fileObj, chunk)  Server ### - -*This method is private* - -__Arguments__ - -* __fileObj__ *{[FS.File](#FS.File)}* -* __chunk__ *{Number}* - -__Returns__ *{String}* -Generated SA specific fileKey for the chunk - - -Note: Calling function should call mountStorage() first, and -make sure that fileObj is mounted. - -> ```_fileReference = function(fileObj, chunk, existing) { ...``` [tempStore.js:118](tempStore.js#L118) - - -- - -### *fsTempstore*.exists(File)  Server ### - -*This method __exists__ is defined in `FS.TempStore`* - -__Arguments__ - -* __File__ *{[FS.File](#FS.File)}* - - object - - -__Returns__ *{Boolean}* -Is this file, or parts of it, currently stored in the TempStore - - -> ```FS.TempStore.exists = function(fileObj) { ...``` [tempStore.js:145](tempStore.js#L145) - - -- - -### *fsTempstore*.listParts(fileObj)  Server ### - -*This method __listParts__ is defined in `FS.TempStore`* - -__Arguments__ - -* __fileObj__ *{[FS.File](#FS.File)}* - -__Returns__ *{Object}* -of parts already stored - -__TODO__ -``` -* This is not yet implemented, milestone 1.1.0 -``` - - -> ```FS.TempStore.listParts = function(fileObj) { ...``` [tempStore.js:156](tempStore.js#L156) - - -- - -### *fsTempstore*.removeFile(fileObj)  Server ### - -*This method __removeFile__ is defined in `FS.TempStore`* - -__Arguments__ - -* __fileObj__ *{[FS.File](#FS.File)}* - -This function removes the file from tempstorage - it cares not if file is -already removed or not found, goal is reached anyway. - -> ```FS.TempStore.removeFile = function(fileObj) { ...``` [tempStore.js:169](tempStore.js#L169) - - -- - -### *fsTempstore*.createWriteStream(fileObj, [options])  Server ### - -*This method __createWriteStream__ is defined in `FS.TempStore`* - -__Arguments__ - -* __fileObj__ *{[FS.File](#FS.File)}* - - File to store in temporary storage - -* __options__ *{[Number ](#Number )|[ String](# String)}* (Optional) - -__Returns__ *{Stream}* -Writeable stream - - -`options` of different types mean differnt things: -`undefined` We store the file in one part -(Normal server-side api usage)* -`Number` the number is the part number total -(multipart uploads will use this api)* -`String` the string is the name of the `store` that wants to store file data -(stores that want to sync their data to the rest of the files stores will use this)* - -> Note: fileObj must be mounted on a `FS.Collection`, it makes no sense to store otherwise - -> ```FS.TempStore.createWriteStream = function(fileObj, options) { ...``` [tempStore.js:217](tempStore.js#L217) - - -- - -### *fsTempstore*.createReadStream(fileObj)  Server ### - -*This method __createReadStream__ is defined in `FS.TempStore`* - -__Arguments__ - -* __fileObj__ *{[FS.File](#FS.File)}* - - The file to read - - -__Returns__ *{Stream}* -Returns readable stream - - - -> ```FS.TempStore.createReadStream = function(fileObj) { ...``` [tempStore.js:313](tempStore.js#L313) - - diff --git a/packages/wekan-cfs-temp-store/package.js b/packages/wekan-cfs-temp-store/package.js deleted file mode 100644 index 61487fed9..000000000 --- a/packages/wekan-cfs-temp-store/package.js +++ /dev/null @@ -1,32 +0,0 @@ - Package.describe({ - git: 'https://github.com/zcfs/Meteor-cfs-tempstore.git', - name: 'wekan-cfs-tempstore', - version: '0.1.6', - summary: 'CollectionFS, temporary storage' -}); - -Npm.depends({ - 'combined-stream': '0.0.4' -}); - -Package.onUse(function(api) { - api.use(['wekan-cfs-base-package@0.0.30', 'wekan-cfs-file@0.1.16', 'ecmascript@0.1.0']); - - api.use('wekan-cfs-filesystem@0.1.2', { weak: true }); - api.use('wekan-cfs-gridfs@0.0.30', { weak: true }); - - api.use('mongo@1.0.0'); - - api.addFiles([ - 'tempStore.js' - ], 'server'); -}); - -// Package.on_test(function (api) { -// api.use('collectionfs'); -// api.use('test-helpers', 'server'); -// api.use(['tinytest', 'underscore', 'ejson', 'ordered-dict', -// 'random', 'deps']); - -// api.addFiles('tests/server-tests.js', 'server'); -// }); diff --git a/packages/wekan-cfs-temp-store/tempStore.js b/packages/wekan-cfs-temp-store/tempStore.js deleted file mode 100644 index 3823737f4..000000000 --- a/packages/wekan-cfs-temp-store/tempStore.js +++ /dev/null @@ -1,395 +0,0 @@ -// ##Temporary Storage -// -// Temporary storage is used for chunked uploads until all chunks are received -// and all copies have been made or given up. In some cases, the original file -// is stored only in temporary storage (for example, if all copies do some -// manipulation in beforeSave). This is why we use the temporary file as the -// basis for each saved copy, and then remove it after all copies are saved. -// -// Every chunk is saved as an individual temporary file. This is safer than -// attempting to write multiple incoming chunks to different positions in a -// single temporary file, which can lead to write conflicts. -// -// Using temp files also allows us to easily resume uploads, even if the server -// restarts, and to keep the working memory clear. - -// The FS.TempStore emits events that others are able to listen to -var EventEmitter = Npm.require('events').EventEmitter; - -// We have a special stream concating all chunk files into one readable stream -var CombinedStream = Npm.require('combined-stream'); - -/** @namespace FS.TempStore - * @property FS.TempStore - * @type {object} - * @public - * @summary An event emitter - */ -FS.TempStore = new EventEmitter(); - -// Create a tracker collection for keeping track of all chunks for any files that are currently in the temp store -var tracker = FS.TempStore.Tracker = new Mongo.Collection('cfs._tempstore.chunks'); - -/** - * @property FS.TempStore.Storage - * @type {StorageAdapter} - * @namespace FS.TempStore - * @private - * @summary This property is set to either `FS.Store.FileSystem` or `FS.Store.GridFS` - * - * __When and why:__ - * We normally default to `cfs-filesystem` unless its not installed. *(we default to gridfs if installed)* - * But if `cfs-gridfs` and `cfs-worker` is installed we default to `cfs-gridfs` - * - * If `cfs-gridfs` and `cfs-filesystem` is not installed we log a warning. - * the user can set `FS.TempStore.Storage` them selfs eg.: - * ```js - * // Its important to set `internal: true` this lets the SA know that we - * // are using this internally and it will give us direct SA api - * FS.TempStore.Storage = new FS.Store.GridFS('_tempstore', { internal: true }); - * ``` - * - * > Note: This is considered as `advanced` use, its not a common pattern. - */ -FS.TempStore.Storage = null; - -// We will not mount a storage adapter until needed. This allows us to check for the -// existance of FS.FileWorker, which is loaded after this package because it -// depends on this package. -function mountStorage() { - - if (FS.TempStore.Storage) return; - - // XXX: We could replace this test, testing the FS scope for grifFS etc. - // This is on the todo later when we get "stable" - if (Package["wekan-cfs-gridfs"] && (Package["wekan-cfs-worker"] || !Package["wekan-cfs-filesystem"])) { - // If the file worker is installed we would prefer to use the gridfs sa - // for scalability. We also default to gridfs if filesystem is not found - - // Use the gridfs - FS.TempStore.Storage = new FS.Store.GridFS('_tempstore', { internal: true }); - } else if (Package["wekan-cfs-filesystem"]) { - - // use the Filesystem - FS.TempStore.Storage = new FS.Store.FileSystem('_tempstore', { internal: true }); - } else { - throw new Error('FS.TempStore.Storage is not set: Install wekan-cfs-filesystem or wekan-cfs-gridfs or set it manually'); - } - - FS.debug && console.log('TempStore is mounted on', FS.TempStore.Storage.typeName); -} - -function mountFile(fileObj, name) { - if (!fileObj.isMounted()) { - throw new Error(name + ' cannot work with unmounted file'); - } -} - -// We update the fileObj on progress -FS.TempStore.on('progress', function(fileObj, chunkNum, count, total, result) { - FS.debug && console.log('TempStore progress: Received ' + count + ' of ' + total + ' chunks for ' + fileObj.name()); -}); - -// XXX: TODO -// FS.TempStore.on('stored', function(fileObj, chunkCount, result) { -// // This should work if we pass on result from the SA on stored event... -// fileObj.update({ $set: { chunkSum: 1, chunkCount: chunkCount, size: result.size } }); -// }); - -// Stream implementation - -/** - * @method _chunkPath - * @private - * @param {Number} [n] Chunk number - * @returns {String} Chunk naming convention - */ -_chunkPath = function(n) { - return (n || 0) + '.chunk'; -}; - -/** - * @method _fileReference - * @param {FS.File} fileObj - * @param {Number} chunk - * @private - * @returns {String} Generated SA specific fileKey for the chunk - * - * Note: Calling function should call mountStorage() first, and - * make sure that fileObj is mounted. - */ -_fileReference = function(fileObj, chunk, existing) { - // Maybe it's a chunk we've already saved - existing = existing || tracker.findOne({fileId: fileObj._id, collectionName: fileObj.collectionName}); - - // Make a temporary fileObj just for fileKey generation - var tempFileObj = new FS.File({ - collectionName: fileObj.collectionName, - _id: fileObj._id, - original: { - name: _chunkPath(chunk) - }, - copies: { - _tempstore: { - key: existing && existing.keys[chunk] - } - } - }); - - // Return a fitting fileKey SA specific - return FS.TempStore.Storage.adapter.fileKey(tempFileObj); -}; - -/** - * @method FS.TempStore.exists - * @param {FS.File} File object - * @returns {Boolean} Is this file, or parts of it, currently stored in the TempStore - */ -FS.TempStore.exists = function(fileObj) { - var existing = tracker.findOne({fileId: fileObj._id, collectionName: fileObj.collectionName}); - return !!existing; -}; - -/** - * @method FS.TempStore.listParts - * @param {FS.File} fileObj - * @returns {Object} of parts already stored - * @todo This is not yet implemented, milestone 1.1.0 - */ -FS.TempStore.listParts = function fsTempStoreListParts(fileObj) { - var self = this; - console.warn('This function is not correctly implemented using SA in TempStore'); - //XXX This function might be necessary for resume. Not currently supported. -}; - -/** - * @method FS.TempStore.removeFile - * @public - * @param {FS.File} fileObj - * This function removes the file from tempstorage - it cares not if file is - * already removed or not found, goal is reached anyway. - */ -FS.TempStore.removeFile = function fsTempStoreRemoveFile(fileObj) { - var self = this; - - // Ensure that we have a storage adapter mounted; if not, throw an error. - mountStorage(); - - // If fileObj is not mounted or can't be, throw an error - mountFile(fileObj, 'FS.TempStore.removeFile'); - - // Emit event - self.emit('remove', fileObj); - - var chunkInfo = tracker.findOne({ - fileId: fileObj._id, - collectionName: fileObj.collectionName - }); - - if (chunkInfo) { - - // Unlink each file - FS.Utility.each(chunkInfo.keys || {}, function (key, chunk) { - var fileKey = _fileReference(fileObj, chunk, chunkInfo); - FS.TempStore.Storage.adapter.remove(fileKey, FS.Utility.noop); - }); - - // Remove fileObj from tracker collection, too - tracker.remove({_id: chunkInfo._id}); - - } -}; - -/** - * @method FS.TempStore.removeAll - * @public - * @summary This function removes all files from tempstorage - it cares not if file is - * already removed or not found, goal is reached anyway. - */ -FS.TempStore.removeAll = function fsTempStoreRemoveAll() { - var self = this; - - // Ensure that we have a storage adapter mounted; if not, throw an error. - mountStorage(); - - tracker.find().forEach(function (chunkInfo) { - // Unlink each file - FS.Utility.each(chunkInfo.keys || {}, function (key, chunk) { - var fileKey = _fileReference({_id: chunkInfo.fileId, collectionName: chunkInfo.collectionName}, chunk, chunkInfo); - FS.TempStore.Storage.adapter.remove(fileKey, FS.Utility.noop); - }); - - // Remove from tracker collection, too - tracker.remove({_id: chunkInfo._id}); - }); -}; - -/** - * @method FS.TempStore.createWriteStream - * @public - * @param {FS.File} fileObj File to store in temporary storage - * @param {Number | String} [options] - * @returns {Stream} Writeable stream - * - * `options` of different types mean differnt things: - * * `undefined` We store the file in one part - * *(Normal server-side api usage)* - * * `Number` the number is the part number total - * *(multipart uploads will use this api)* - * * `String` the string is the name of the `store` that wants to store file data - * *(stores that want to sync their data to the rest of the files stores will use this)* - * - * > Note: fileObj must be mounted on a `FS.Collection`, it makes no sense to store otherwise - */ -FS.TempStore.createWriteStream = function(fileObj, options) { - var self = this; - - // Ensure that we have a storage adapter mounted; if not, throw an error. - mountStorage(); - - // If fileObj is not mounted or can't be, throw an error - mountFile(fileObj, 'FS.TempStore.createWriteStream'); - - // Cache the selector for use multiple times below - var selector = {fileId: fileObj._id, collectionName: fileObj.collectionName}; - - // TODO, should pass in chunkSum so we don't need to use FS.File for it - var chunkSum = fileObj.chunkSum || 1; - - // Add fileObj to tracker collection - tracker.upsert(selector, {$setOnInsert: {keys: {}}}); - - // Determine how we're using the writeStream - var isOnePart = false, isMultiPart = false, isStoreSync = false, chunkNum = 0; - if (options === +options) { - isMultiPart = true; - chunkNum = options; - } else if (options === ''+options) { - isStoreSync = true; - } else { - isOnePart = true; - } - - // XXX: it should be possible for a store to sync by storing data into the - // tempstore - this could be done nicely by setting the store name as string - // in the chunk variable? - // This store name could be passed on the the fileworker via the uploaded - // event - // So the uploaded event can return: - // undefined - if data is stored into and should sync out to all storage adapters - // number - if a chunk has been uploaded - // string - if a storage adapter wants to sync its data to the other SA's - - // Find a nice location for the chunk data - var fileKey = _fileReference(fileObj, chunkNum); - - // Create the stream as Meteor safe stream - var writeStream = FS.TempStore.Storage.adapter.createWriteStream(fileKey); - - // When the stream closes we update the chunkCount - writeStream.safeOn('stored', function(result) { - // Save key in tracker document - var setObj = {}; - setObj['keys.' + chunkNum] = result.fileKey; - tracker.update(selector, {$set: setObj}); - - var temp = tracker.findOne(selector); - - if (!temp) { - FS.debug && console.log('NOT FOUND FROM TEMPSTORE => EXIT (REMOVED)'); - return; - } - - // Get updated chunkCount - var chunkCount = FS.Utility.size(temp.keys); - - // Progress - self.emit('progress', fileObj, chunkNum, chunkCount, chunkSum, result); - - var modifier = { $set: {} }; - if (!fileObj.instance_id) { - modifier.$set.instance_id = process.env.COLLECTIONFS_ENV_NAME_UNIQUE_ID ? process.env[process.env.COLLECTIONFS_ENV_NAME_UNIQUE_ID] : process.env.METEOR_PARENT_PID; - } - - // If upload is completed - if (chunkCount === chunkSum) { - // We no longer need the chunk info - modifier.$unset = {chunkCount: 1, chunkSum: 1, chunkSize: 1}; - - // Check if the file has been uploaded before - if (typeof fileObj.uploadedAt === 'undefined') { - // We set the uploadedAt date - modifier.$set.uploadedAt = new Date(); - } else { - // We have been uploaded so an event were file data is updated is - // called synchronizing - so this must be a synchronizedAt? - modifier.$set.synchronizedAt = new Date(); - } - - // Update the fileObject - fileObj.update(modifier); - - // Fire ending events - var eventName = isStoreSync ? 'synchronized' : 'stored'; - self.emit(eventName, fileObj, result); - - // XXX is emitting "ready" necessary? - self.emit('ready', fileObj, chunkCount, result); - } else { - // Update the chunkCount on the fileObject - modifier.$set.chunkCount = chunkCount; - fileObj.update(modifier); - } - }); - - // Emit errors - writeStream.on('error', function (error) { - FS.debug && console.log('TempStore writeStream error:', error); - self.emit('error', error, fileObj); - }); - - return writeStream; -}; - -/** - * @method FS.TempStore.createReadStream - * @public - * @param {FS.File} fileObj The file to read - * @return {Stream} Returns readable stream - * - */ -FS.TempStore.createReadStream = function(fileObj) { - // Ensure that we have a storage adapter mounted; if not, throw an error. - mountStorage(); - - // If fileObj is not mounted or can't be, throw an error - mountFile(fileObj, 'FS.TempStore.createReadStream'); - - FS.debug && console.log('FS.TempStore creating read stream for ' + fileObj._id); - - // Determine how many total chunks there are from the tracker collection - var chunkInfo = tracker.findOne({fileId: fileObj._id, collectionName: fileObj.collectionName}) || {}; - var totalChunks = FS.Utility.size(chunkInfo.keys); - - function getNextStreamFunc(chunk) { - return Meteor.bindEnvironment(function(next) { - var fileKey = _fileReference(fileObj, chunk); - var chunkReadStream = FS.TempStore.Storage.adapter.createReadStream(fileKey); - next(chunkReadStream); - }, function (error) { - throw error; - }); - } - - // Make a combined stream - var combinedStream = CombinedStream.create(); - - // Add each chunk stream to the combined stream when the previous chunk stream ends - var currentChunk = 0; - for (var chunk = 0; chunk < totalChunks; chunk++) { - combinedStream.append(getNextStreamFunc(chunk)); - } - - // Return the combined stream - return combinedStream; -}; diff --git a/packages/wekan-cfs-temp-store/tests/server-tests.js b/packages/wekan-cfs-temp-store/tests/server-tests.js deleted file mode 100644 index 242aa89ca..000000000 --- a/packages/wekan-cfs-temp-store/tests/server-tests.js +++ /dev/null @@ -1,39 +0,0 @@ -function equals(a, b) { - return !!(EJSON.stringify(a) === EJSON.stringify(b)); -} - -Tinytest.add('cfs-tempstore - server - test environment', function(test) { - test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection'); -}); - -/* - * This is a server-only package so only server tests are needed. - * Need to test each API method: - * FS.TempStore.saveChunk - * FS.TempStore.getDataForFile - * FS.TempStore.getDataForFileSync - * FS.TempStore.deleteChunks - * FS.TempStore.ensureForFile - * - */ - - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-upload-http/.travis.yml b/packages/wekan-cfs-upload-http/.travis.yml deleted file mode 100644 index 6a4640033..000000000 --- a/packages/wekan-cfs-upload-http/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - "0.10" -before_install: - - "curl -L http://git.io/s0Zu-w | /bin/sh" \ No newline at end of file diff --git a/packages/wekan-cfs-upload-http/LICENSE.md b/packages/wekan-cfs-upload-http/LICENSE.md deleted file mode 100644 index b8d7fab60..000000000 --- a/packages/wekan-cfs-upload-http/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013-2014 [@raix](https://github.com/raix) and [@aldeed](https://github.com/aldeed), aka Morten N.O. Nørgaard Henriksen, mh@gi-software.com - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/wekan-cfs-upload-http/README.md b/packages/wekan-cfs-upload-http/README.md deleted file mode 100644 index 855f50585..000000000 --- a/packages/wekan-cfs-upload-http/README.md +++ /dev/null @@ -1,8 +0,0 @@ -wekan-cfs-upload-http -========================= - -This is a Meteor package that provides HTTP uploads for -[CollectionFS](https://github.com/zcfs/Meteor-CollectionFS). - -You don't need to manually add this package to your app. It is added when you -add the `wekan-cfs-standard-packages` package. \ No newline at end of file diff --git a/packages/wekan-cfs-upload-http/api.md b/packages/wekan-cfs-upload-http/api.md deleted file mode 100644 index 674502a6f..000000000 --- a/packages/wekan-cfs-upload-http/api.md +++ /dev/null @@ -1,24 +0,0 @@ -## wekan-cfs-upload-http Public API ## - -CollectionFS, HTTP File Upload - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -2MB default upload chunk size -Can be overridden by user with FS.config.uploadChunkSize or per FS.Collection in collection options -- - -### *fsFile*.resume(ref)  Client ### - -*This method __resume__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __ref__ *{[File](#File)|[Blob](#Blob)|Buffer}* - - -> This function is not yet implemented for server - -> ```FS.File.prototype.resume = function(ref) { ...``` [upload-http-client.js:257](upload-http-client.js#L257) - - diff --git a/packages/wekan-cfs-upload-http/internal.api.md b/packages/wekan-cfs-upload-http/internal.api.md deleted file mode 100644 index dd5a57f66..000000000 --- a/packages/wekan-cfs-upload-http/internal.api.md +++ /dev/null @@ -1,160 +0,0 @@ -## Public and Private API ## - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -*** - -__File: ["upload-http-client.js"](upload-http-client.js) Where: {client}__ - -*** - -2MB default upload chunk size -Can be overridden by user with FS.config.uploadChunkSize or per FS.Collection in collection options -- - -### _taskHandler(task, next)  Client ### - -*This method is private* - -__Arguments__ - -* __task__ *{Object}* -* __next__ *{Function}* - -__Returns__ *{undefined}* - - -> ```var _taskHandler = function(task, next) { ...``` [upload-http-client.js:15](upload-http-client.js#L15) - - -- - -### _errorHandler(data, addTask)  Client ### - -*This method is private* - -__Arguments__ - -* __data__ *{Object}* -* __addTask__ *{Function}* - -__Returns__ *{undefined}* - - -> ```var _errorHandler = function(data, addTask, failures) { ...``` [upload-http-client.js:49](upload-http-client.js#L49) - - -- - -### new UploadTransferQueue([options])  Client ### - - -__Arguments__ - -* __options__ *{Object}* (Optional) - -> ```UploadTransferQueue = function(options) { ...``` [upload-http-client.js:60](upload-http-client.js#L60) - - -- - -### *uploadtransferqueue*.isUploadingFile(fileObj)  Client ### - -*This method __isUploadingFile__ is defined in `UploadTransferQueue`* - -__Arguments__ - -* __fileObj__ *{[FS.File](#FS.File)}* - - File to check if uploading - - -__Returns__ *{Boolean}* -True if the file is uploading - -__TODO__ -``` -* Maybe have a similar function for accessing the file upload queue? -``` - - - -> ```self.isUploadingFile = function(fileObj) { ...``` [upload-http-client.js:90](upload-http-client.js#L90) - - -- - -### *uploadtransferqueue*.resumeUploadingFile(File)  Client ### - -*This method __resumeUploadingFile__ is defined in `UploadTransferQueue`* - -__Arguments__ - -* __File__ *{[FS.File](#FS.File)}* - - to resume uploading - - -__TODO__ -``` -* Not sure if this is the best way to handle resumes -``` - -> ```self.resumeUploadingFile = function(fileObj) { ...``` [upload-http-client.js:99](upload-http-client.js#L99) - - -- - -### *uploadtransferqueue*.uploadFile(File)  Client ### - -*This method __uploadFile__ is defined in `UploadTransferQueue`* - -__Arguments__ - -* __File__ *{[FS.File](#FS.File)}* - - to upload - - -__TODO__ -``` -* Check that a file can only be added once - maybe a visual helper on the FS.File? -* Have an initial request to the server getting uploaded chunks for resume -``` - -> ```self.uploadFile = function(fileObj) { ...``` [upload-http-client.js:120](upload-http-client.js#L120) - - -- - -### *fsHttp*.uploadQueue UploadTransferQueue  Client ### - -*This property __uploadQueue__ is defined in `FS.HTTP`* - - -There is a single uploads transfer queue per client (not per CFS) - -> ```FS.HTTP.uploadQueue = new UploadTransferQueue();``` [upload-http-client.js:243](upload-http-client.js#L243) - - -- - -### *fsFile*.resume(ref)  Client ### - -*This method __resume__ is defined in `prototype` of `FS.File`* - -__Arguments__ - -* __ref__ *{[File](#File)|[Blob](#Blob)|Buffer}* - -__TODO__ -``` -* WIP, Not yet implemented for server -``` - - -> This function is not yet implemented for server - -> ```FS.File.prototype.resume = function(ref) { ...``` [upload-http-client.js:257](upload-http-client.js#L257) - - diff --git a/packages/wekan-cfs-upload-http/package.js b/packages/wekan-cfs-upload-http/package.js deleted file mode 100644 index ef76ba94c..000000000 --- a/packages/wekan-cfs-upload-http/package.js +++ /dev/null @@ -1,37 +0,0 @@ -Package.describe({ - name: 'wekan-cfs-upload-http', - version: '0.0.21', - summary: 'CollectionFS, HTTP File Upload', -}); - -Package.onUse(function(api) { - api.versionsFrom('1.0'); - - api.use([ - 'wekan-cfs-base-package@0.0.30', - 'wekan-cfs-tempstore@0.1.4', - 'wekan-cfs-file@0.1.16', - 'wekan-cfs-access-point@0.1.49', - 'wekan-cfs-power-queue@0.9.11', - 'wekan-cfs-reactive-list@0.0.9' - ]); - - api.addFiles([ - 'upload-http-common.js', - 'upload-http-client.js' - ], 'client'); - - api.addFiles([ - 'upload-http-common.js' - ], 'server'); -}); - -// Package.onTest(function (api) { -// api.use('collectionfs'); -// api.use('test-helpers', 'server'); -// api.use(['tinytest', 'underscore', 'ejson', 'ordered-dict', -// 'random', 'deps']); - -// api.addFiles('tests/server-tests.js', 'server'); -// api.addFiles('tests/client-tests.js', 'client'); -// }); diff --git a/packages/wekan-cfs-upload-http/tests/client-tests.js b/packages/wekan-cfs-upload-http/tests/client-tests.js deleted file mode 100644 index 53ccc6239..000000000 --- a/packages/wekan-cfs-upload-http/tests/client-tests.js +++ /dev/null @@ -1,27 +0,0 @@ -function equals(a, b) { - return !!(EJSON.stringify(a) === EJSON.stringify(b)); -} - -Tinytest.add('cfs-upload-http - client - test environment', function(test) { - test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection'); -}); - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-upload-http/tests/server-tests.js b/packages/wekan-cfs-upload-http/tests/server-tests.js deleted file mode 100644 index 7fb4a7f5d..000000000 --- a/packages/wekan-cfs-upload-http/tests/server-tests.js +++ /dev/null @@ -1,27 +0,0 @@ -function equals(a, b) { - return !!(EJSON.stringify(a) === EJSON.stringify(b)); -} - -Tinytest.add('cfs-upload-http - server - test environment', function(test) { - test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection'); -}); - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-upload-http/upload-http-client.js b/packages/wekan-cfs-upload-http/upload-http-client.js deleted file mode 100644 index 6ac2ff645..000000000 --- a/packages/wekan-cfs-upload-http/upload-http-client.js +++ /dev/null @@ -1,260 +0,0 @@ -/* - * HTTP Upload Transfer Queue - */ - -// 2MB default upload chunk size -// Can be overridden by user with FS.config.uploadChunkSize or per FS.Collection in collection options -var defaultChunkSize = 2 * 1024 * 1024; - -/** - * @private - * @param {Object} task - * @param {Function} next - * @return {undefined} - */ -var _taskHandler = function(task, next) { - FS.debug && console.log("uploading chunk " + task.chunk + ", bytes " + task.start + " to " + Math.min(task.end, task.fileObj.size()) + " of " + task.fileObj.size()); - task.fileObj.data.getBinary(task.start, task.end, function gotBinaryCallback(err, data) { - if (err) { - next(new Meteor.Error(err.error, err.message)); - } else { - - FS.debug && console.log('PUT to URL', task.url, task.urlParams); - - HTTP.call("PUT", task.url, { - params: FS.Utility.extend({chunk: task.chunk}, task.urlParams), - content: data, - headers: { - 'Content-Type': task.fileObj.type() - } - }, function(error, result) { - task = null; - if (error) { - next(new Meteor.Error(error.error, error.message)); - } else { - next(); - } - }); - - } - }); -}; - -/** - * @private - * @param {Object} data - * @param {Function} addTask - * @return {undefined} - */ -var _errorHandler = function(data, addTask, failures) { - // If file upload fails - // TODO We should retry a few times and then emit error? - // data.fileObj.emit("error", error); -}; - -/** @method UploadTransferQueue - * @namespace UploadTransferQueue - * @constructor - * @param {Object} [options] - */ -UploadTransferQueue = function(options) { - // Rig options - options = options || {}; - - // Init the power queue - var self = new PowerQueue({ - name: 'HTTPUploadTransferQueue', - // spinalQueue: ReactiveList, - maxProcessing: 1, - maxFailures: 5, - jumpOnFailure: true, - autostart: true, - isPaused: false, - filo: false, - debug: FS.debug - }); - - // Keep track of uploaded files via this queue - self.files = {}; - - // cancel maps onto queue reset - self.cancel = self.reset; - - /** - * @method UploadTransferQueue.isUploadingFile - * @param {FS.File} fileObj File to check if uploading - * @returns {Boolean} True if the file is uploading - * - * @todo Maybe have a similar function for accessing the file upload queue? - */ - self.isUploadingFile = function(fileObj) { - // Check if file is already in queue - return !!(fileObj && fileObj._id && fileObj.collectionName && (self.files[fileObj.collectionName] || {})[fileObj._id]); - }; - - /** @method UploadTransferQueue.resumeUploadingFile - * @param {FS.File} File to resume uploading - * @todo Not sure if this is the best way to handle resumes - */ - self.resumeUploadingFile = function(fileObj) { - // Make sure we are handed a FS.File - if (!(fileObj instanceof FS.File)) { - throw new Error('Transfer queue expects a FS.File'); - } - - if (fileObj.isMounted()) { - // This might still be true, preventing upload, if - // there was a server restart without client restart. - self.files[fileObj.collectionName] = self.files[fileObj.collectionName] || {}; - self.files[fileObj.collectionName][fileObj._id] = false; - // Kick off normal upload - self.uploadFile(fileObj); - } - }; - - /** @method UploadTransferQueue.uploadFile - * @param {FS.File} File to upload - * @todo Check that a file can only be added once - maybe a visual helper on the FS.File? - * @todo Have an initial request to the server getting uploaded chunks for resume - */ - self.uploadFile = function(fileObj) { - FS.debug && console.log("HTTP uploadFile"); - - // Make sure we are handed a FS.File - if (!(fileObj instanceof FS.File)) { - throw new Error('Transfer queue expects a FS.File'); - } - - // Make sure that we have size as number - if (typeof fileObj.size() !== 'number') { - throw new Error('TransferQueue upload failed: fileObj size not set'); - } - - // We don't add the file if it's already in transfer or if already uploaded - if (self.isUploadingFile(fileObj) || fileObj.isUploaded()) { - return; - } - - // Make sure the file object is mounted on a collection - if (fileObj.isMounted()) { - - var collectionName = fileObj.collectionName; - var id = fileObj._id; - - // Set the chunkSize to match the collection options, or global config, or default - fileObj.chunkSize = fileObj.collection.options.chunkSize || FS.config.uploadChunkSize || defaultChunkSize; - // Set counter for uploaded chunks - fileObj.chunkCount = 0; - // Calc the number of chunks - fileObj.chunkSum = Math.ceil(fileObj.size() / fileObj.chunkSize); - - if (fileObj.chunkSum === 0) - return; - - // Update the filerecord - // TODO eventually we should be able to do this without storing any chunk info in the filerecord - fileObj.update({$set: {chunkSize: fileObj.chunkSize, chunkCount: fileObj.chunkCount, chunkSum: fileObj.chunkSum}}); - - // Create a sub queue - var chunkQueue = new PowerQueue({ - onEnded: function oneChunkQueueEnded() { - // Remove from list of files being uploaded - self.files[collectionName][id] = false; - // XXX It might be possible for this to be called even though there were errors uploading? - fileObj.emit("uploaded"); - }, - spinalQueue: ReactiveList, - maxProcessing: 1, - maxFailures: 5, - jumpOnFailure: true, - autostart: false, - isPaused: false, - filo: false - }); - - // Rig the custom task handler - chunkQueue.taskHandler = _taskHandler; - - // Rig the error handler - chunkQueue.errorHandler = _errorHandler; - - // Set flag that this file is being transfered - self.files[collectionName] = self.files[collectionName] || {}; - self.files[collectionName][id] = true; - - // Construct URL - var url = FS.HTTP.uploadUrl + '/' + collectionName; - if (id) { - url += '/' + id; - } - - // TODO: Could we somehow figure out if the collection requires login? - var authToken = ''; - if (typeof Accounts !== "undefined") { - var authObject = { - authToken: Accounts._storedLoginToken() || '', - }; - - // Set the authToken - var authString = JSON.stringify(authObject); - authToken = FS.Utility.btoa(authString); - } - - // Construct query string - var urlParams = { - filename: fileObj.name() - }; - if (authToken !== '') { - urlParams.token = authToken; - } - - // Add chunk upload tasks - for (var chunk = 0, start; chunk < fileObj.chunkSum; chunk++) { - start = chunk * fileObj.chunkSize; - // Create and add the task - // XXX should we somehow make sure we haven't uploaded this chunk already, in - // case we are resuming? - chunkQueue.add({ - chunk: chunk, - name: fileObj.name(), - url: url, - urlParams: urlParams, - fileObj: fileObj, - start: start, - end: (chunk + 1) * fileObj.chunkSize - }); - } - - // Add the queue to the main upload queue - self.add(chunkQueue); - } - - }; - - return self; -}; - -/** - * @namespace FS - * @type UploadTransferQueue - * - * There is a single uploads transfer queue per client (not per CFS) - */ -FS.HTTP.uploadQueue = new UploadTransferQueue(); - -/* - * FS.File extensions - */ - -/** - * @method FS.File.prototype.resume - * @public - * @param {File|Blob|Buffer} ref - * @todo WIP, Not yet implemented for server - * - * > This function is not yet implemented for server - */ -FS.File.prototype.resume = function(ref) { - var self = this; - FS.uploadQueue.resumeUploadingFile(self); -}; diff --git a/packages/wekan-cfs-upload-http/upload-http-common.js b/packages/wekan-cfs-upload-http/upload-http-common.js deleted file mode 100644 index 4c630a385..000000000 --- a/packages/wekan-cfs-upload-http/upload-http-common.js +++ /dev/null @@ -1 +0,0 @@ -FS.HTTP = FS.HTTP || {}; diff --git a/packages/wekan-cfs-worker/.travis.yml b/packages/wekan-cfs-worker/.travis.yml deleted file mode 100644 index 6a4640033..000000000 --- a/packages/wekan-cfs-worker/.travis.yml +++ /dev/null @@ -1,5 +0,0 @@ -language: node_js -node_js: - - "0.10" -before_install: - - "curl -L http://git.io/s0Zu-w | /bin/sh" \ No newline at end of file diff --git a/packages/wekan-cfs-worker/CHANGELOG.md b/packages/wekan-cfs-worker/CHANGELOG.md deleted file mode 100644 index 84d63d329..000000000 --- a/packages/wekan-cfs-worker/CHANGELOG.md +++ /dev/null @@ -1,123 +0,0 @@ -# Changelog - -## vCurrent -## [v0.1.2] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.1.2) -#### 17/12/14 by Morten Henriksen -## [v0.1.1] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.1.1) -#### 17/12/14 by Morten Henriksen -- Bump to version 0.1.1 - -- mbr update, remove versions.json - -## [v0.1.0] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.1.0) -#### 17/12/14 by Morten Henriksen -- mbr update versions and fix warnings - -- *Merged pull-request:* "Remove the unused function makeSafeCallback()." [#4](https://github.com/zcfs/Meteor-cfs-worker/issues/4) ([DouglasUrner](https://github.com/DouglasUrner)) - -- Remove the unused function makeSafeCallback(). - -- *Merged pull-request:* "Minor formatting edit." [#2](https://github.com/zcfs/Meteor-cfs-worker/issues/2) ([DouglasUrner](https://github.com/DouglasUrner)) - -- Minor formatting edit. - -- 0.9.1 support - -Patches by GitHub user [@DouglasUrner](https://github.com/DouglasUrner). - -## [v0.0.20] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.20) -#### 28/08/14 by Morten Henriksen -- Meteor Package System Update - -## [v0.0.19] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.19) -#### 27/08/14 by Eric Dobbertin -## [v0.0.18] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.18) -#### 27/08/14 by Eric Dobbertin -- Merge branch 'master' of https://github.com/zcfs/Meteor-cfs-worker - -- change package name to lowercase - -## [v0.0.17] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.17) -#### 09/08/14 by Eric Dobbertin -- *Merged pull-request:* "Fixed bug preventing temp chunks deletion" [#1](https://github.com/zcfs/Meteor-cfs-worker/issues/1) ([GuillaumeZuff](https://github.com/GuillaumeZuff)) - -- Fixed bug preventing temp chunks deletion - -Patches by GitHub user [@GuillaumeZuff](https://github.com/GuillaumeZuff). - -## [v0.0.16] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.16) -#### 06/04/14 by Eric Dobbertin -- use uploadedAt so that we can remove chunk info when it's no longer needed - -## [v0.0.15] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.15) -#### 05/04/14 by Morten Henriksen -## [v0.0.14] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.14) -#### 31/03/14 by Eric Dobbertin -- use latest releases - -## [v0.0.13] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.13) -#### 29/03/14 by Morten Henriksen -- remove underscore deps - -## [v0.0.12] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.12) -#### 29/03/14 by Morten Henriksen -- Refactoring and clean ups - -## [v0.0.11] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.11) -#### 23/03/14 by Morten Henriksen -- Rollback to specific git dependency - -- use collectionFS travis version force update - -## [v0.0.10] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.10) -#### 22/03/14 by Morten Henriksen -- try to fix travis test by using general package references - -## [v0.0.9] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.9) -#### 22/03/14 by Morten Henriksen -- out factor fileobj update when file is stored - -- clean up and use the correct end event for streams - -- reference released collectionFS pkg - -## [v0.0.8] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.8) -#### 21/03/14 by Morten Henriksen -## [v0.0.7] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.7) -#### 18/03/14 by Eric Dobbertin -- Remove from temp store when removed from collection - -## [v0.0.6] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.6) -#### 18/03/14 by Morten Henriksen -- fix refactor name for removeFile - -- add back code for running beforeSave function, with stream support (just getting it working for now, can be switched to transform streams later) - -- changed method name - -- minor changes using chunks in file record - -- Add streaming WIP - -## [v0.0.5] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.5) -#### 07/03/14 by Eric Dobbertin -- should be installing devel - -- small change because tempstore no longer tracks chunks in the file object - -## [v0.0.4] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.4) -#### 03/03/14 by Eric Dobbertin -- moved beforeSave out of SA and into here - -- move saveCopy here, out of fs.collection - -- just package and doc tweaks - -## [v0.0.3] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.3) -#### 15/02/14 by Morten Henriksen -## [v0.0.2] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.2) -#### 13/02/14 by Morten Henriksen -## [v0.0.1] (https://github.com/zcfs/Meteor-cfs-worker/tree/v0.0.1) -#### 13/02/14 by Morten Henriksen -- init commit - diff --git a/packages/wekan-cfs-worker/LICENSE.md b/packages/wekan-cfs-worker/LICENSE.md deleted file mode 100644 index 1a3820821..000000000 --- a/packages/wekan-cfs-worker/LICENSE.md +++ /dev/null @@ -1,20 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2013 [@raix](https://github.com/raix) and [@aldeed](https://github.com/aldeed), aka Morten N.O. Nørgaard Henriksen, mh@gi-software.com - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/packages/wekan-cfs-worker/README.md b/packages/wekan-cfs-worker/README.md deleted file mode 100644 index f45ef8df6..000000000 --- a/packages/wekan-cfs-worker/README.md +++ /dev/null @@ -1,8 +0,0 @@ -wekan-cfs-worker -========================= - -This is a Meteor package used by -[CollectionFS](https://github.com/zcfs/Meteor-CollectionFS). - -You don't need to manually add this package to your app. It is added when you -add the `wekan-cfs-standard-packages` package. \ No newline at end of file diff --git a/packages/wekan-cfs-worker/api.md b/packages/wekan-cfs-worker/api.md deleted file mode 100644 index cab1605d5..000000000 --- a/packages/wekan-cfs-worker/api.md +++ /dev/null @@ -1,38 +0,0 @@ -## cfs-worker Public API ## - -CollectionFS, file worker - handles file copies/versions - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -TODO: Use power queue to handle throttling etc. -Use observe to monitor changes and have it create tasks for the power queue -to perform. -- - -### *fs*.FileWorker Object  Server ### - -*This property __FileWorker__ is defined in `FS`* - - -> ```FS.FileWorker = { ...``` [fileWorker.js:9](fileWorker.js#L9) - - -- - -### *fsFileworker*.observe(fsCollection)  Server ### - -*This method __observe__ is defined in `FS.FileWorker`* - -__Arguments__ - -* __fsCollection__ *{[FS.Collection](#FS.Collection)}* - -__Returns__ *{undefined}* - - -Sets up observes on the fsCollection to store file copies and delete -temp files at the appropriate times. - -> ```FS.FileWorker.observe = function(fsCollection) { ...``` [fileWorker.js:20](fileWorker.js#L20) - - diff --git a/packages/wekan-cfs-worker/fileWorker.js b/packages/wekan-cfs-worker/fileWorker.js deleted file mode 100644 index 8d40da3e8..000000000 --- a/packages/wekan-cfs-worker/fileWorker.js +++ /dev/null @@ -1,185 +0,0 @@ -//// TODO: Use power queue to handle throttling etc. -//// Use observe to monitor changes and have it create tasks for the power queue -//// to perform. - -/** - * @public - * @type Object - */ -FS.FileWorker = {}; - -/** - * @method FS.FileWorker.observe - * @public - * @param {FS.Collection} fsCollection - * @returns {undefined} - * - * Sets up observes on the fsCollection to store file copies and delete - * temp files at the appropriate times. - */ -FS.FileWorker.observe = function(fsCollection) { - - // Initiate observe for finding newly uploaded/added files that need to be stored - // per store. - FS.Utility.each(fsCollection.options.stores, function(store) { - var storeName = store.name; - fsCollection.files.find(getReadyQuery(storeName), { - fields: { - copies: 0 - } - }).observe({ - added: function(fsFile) { - // added will catch fresh files - FS.debug && console.log("FileWorker ADDED - calling saveCopy", storeName, "for", fsFile._id); - saveCopy(fsFile, storeName); - }, - changed: function(fsFile) { - // changed will catch failures and retry them - FS.debug && console.log("FileWorker CHANGED - calling saveCopy", storeName, "for", fsFile._id); - saveCopy(fsFile, storeName); - } - }); - }); - - // Initiate observe for finding files that have been stored so we can delete - // any temp files - fsCollection.files.find(getDoneQuery(fsCollection.options.stores)).observe({ - added: function(fsFile) { - FS.debug && console.log("FileWorker ADDED - calling deleteChunks for", fsFile._id); - try { - FS.TempStore.removeFile(fsFile); - } catch(err) { - console.error(err); - } - } - }); - - // Initiate observe for catching files that have been removed and - // removing the data from all stores as well - fsCollection.files.find().observe({ - removed: function(fsFile) { - FS.debug && console.log('FileWorker REMOVED - removing all stored data for', fsFile._id); - //remove from temp store - FS.TempStore.removeFile(fsFile); - //delete from all stores - FS.Utility.each(fsCollection.options.stores, function(storage) { - storage.adapter.remove(fsFile); - }); - } - }); -}; - -/** - * @method getReadyQuery - * @private - * @param {string} storeName - The name of the store to observe - * - * Returns a selector that will be used to identify files that - * have been uploaded but have not yet been stored to the - * specified store. - * - * { - * uploadedAt: {$exists: true}, - * 'copies.storeName`: null, - * 'failures.copies.storeName.doneTrying': {$ne: true} - * } - */ -function getReadyQuery(storeName) { - var selector = {uploadedAt: {$exists: true}}; - selector['copies.' + storeName] = null; - selector['failures.copies.' + storeName + '.doneTrying'] = {$ne: true}; - return selector; -} - -/** - * @method getDoneQuery - * @private - * @param {Array} stores - The stores array from the FS.Collection options - * - * Returns a selector that will be used to identify files where all - * stores have successfully save or have failed the - * max number of times but still have chunks. The resulting selector - * should be something like this: - * - * { - * $and: [ - * {chunks: {$exists: true}}, - * { - * $or: [ - * { - * $and: [ - * { - * 'copies.storeName': {$ne: null} - * }, - * { - * 'copies.storeName': {$ne: false} - * } - * ] - * }, - * { - * 'failures.copies.storeName.doneTrying': true - * } - * ] - * }, - * REPEATED FOR EACH STORE - * ] - * } - * - */ -function getDoneQuery(stores) { - var selector = { - $and: [{chunks: {$exists: true}}] - }; - - // Add conditions for all defined stores - FS.Utility.each(stores, function(store) { - var storeName = store.name; - var copyCond = {$or: [{$and: []}]}; - var tempCond = {}; - tempCond["copies." + storeName] = {$ne: null}; - copyCond.$or[0].$and.push(tempCond); - tempCond = {}; - tempCond["copies." + storeName] = {$ne: false}; - copyCond.$or[0].$and.push(tempCond); - tempCond = {}; - tempCond['failures.copies.' + storeName + '.doneTrying'] = true; - copyCond.$or.push(tempCond); - selector.$and.push(copyCond); - }) - - return selector; -} - -/** - * @method saveCopy - * @private - * @param {FS.File} fsFile - * @param {string} storeName - * @param {Object} options - * @param {Boolean} [options.overwrite=false] - Force save to the specified store? - * @returns {undefined} - * - * Saves to the specified store. If the - * `overwrite` option is `true`, will save to the store even if we already - * have, potentially overwriting any previously saved data. Synchronous. - */ -function saveCopy(fsFile, storeName, options) { - options = options || {}; - - var storage = FS.StorageAdapter(storeName); - if (!storage) { - throw new Error('No store named "' + storeName + '" exists'); - } - - FS.debug && console.log('saving to store ' + storeName); - - try { - var writeStream = storage.adapter.createWriteStream(fsFile); - var readStream = FS.TempStore.createReadStream(fsFile); - - // Pipe the temp data into the storage adapter - readStream.pipe(writeStream); - } catch(err) { - console.error(err); - } -} diff --git a/packages/wekan-cfs-worker/internal.api.md b/packages/wekan-cfs-worker/internal.api.md deleted file mode 100644 index 92cce610b..000000000 --- a/packages/wekan-cfs-worker/internal.api.md +++ /dev/null @@ -1,143 +0,0 @@ -## Public and Private API ## - -_API documentation automatically generated by [docmeteor](https://github.com/raix/docmeteor)._ - -*** - -__File: ["fileWorker.js"](fileWorker.js) Where: {server}__ - -*** - -TODO: Use power queue to handle throttling etc. -Use observe to monitor changes and have it create tasks for the power queue -to perform. - -- - -### *fs*.FileWorker Object  Server ### - -*This property __FileWorker__ is defined in `FS`* - - -> ```FS.FileWorker = { ...``` [fileWorker.js:9](fileWorker.js#L9) - - -- - -### *fsFileworker*.observe(fsCollection)  Server ### - -*This method __observe__ is defined in `FS.FileWorker`* - -__Arguments__ - -* __fsCollection__ *{[FS.Collection](#FS.Collection)}* - -__Returns__ *{undefined}* - - -Sets up observes on the fsCollection to store file copies and delete -temp files at the appropriate times. - -> ```FS.FileWorker.observe = function(fsCollection) { ...``` [fileWorker.js:20](fileWorker.js#L20) - - -- - -### getReadyQuery(storeName)  undefined ### - -*This method is private* - -__Arguments__ - -* __storeName__ *{string}* - - The name of the store to observe - - - -Returns a selector that will be used to identify files that -have been uploaded but have not yet been stored to the -specified store. - -{ -$where: "this.chunkSum === this.chunkCount", -'copies.storeName`: null, -'failures.copies.storeName.doneTrying': {$ne: true} -} - -> ```function getReadyQuery(storeName) { ...``` [fileWorker.js:83](fileWorker.js#L83) - - -- - -### getDoneQuery(stores)  undefined ### - -*This method is private* - -__Arguments__ - -* __stores__ *{Object}* - - The stores object from the FS.Collection options - - - -Returns a selector that will be used to identify files where all -stores have successfully save or have failed the -max number of times but still have chunks. The resulting selector -should be something like this: - -{ -$and: [ -{chunks: {$exists: true}}, -{ -$or: [ -{ -$and: [ -{ -'copies.storeName': {$ne: null} -}, -{ -'copies.storeName': {$ne: false} -} -] -}, -{ -'failures.copies.storeName.doneTrying': true -} -] -}, -REPEATED FOR EACH STORE -] -} - - -> ```function getDoneQuery(stores) { ...``` [fileWorker.js:129](fileWorker.js#L129) - - -- - -### saveCopy(fsFile, storeName, options)  Server ### - -*This method is private* - -__Arguments__ - -* __fsFile__ *{[FS.File](#FS.File)}* -* __storeName__ *{string}* -* __options__ *{Object}* - * __overwrite__ *{Boolean}* (Optional, Default = false) - - Force save to the specified store? - - -__Returns__ *{undefined}* - - -Saves to the specified store. If the -`overwrite` option is `true`, will save to the store even if we already -have, potentially overwriting any previously saved data. Synchronous. - -> ```var makeSafeCallback = function (callback) { ...``` [fileWorker.js:168](fileWorker.js#L168) - - diff --git a/packages/wekan-cfs-worker/package.js b/packages/wekan-cfs-worker/package.js deleted file mode 100644 index e8bc72058..000000000 --- a/packages/wekan-cfs-worker/package.js +++ /dev/null @@ -1,34 +0,0 @@ -Package.describe({ - git: 'https://github.com/zcfs/Meteor-cfs-worker.git', - name: 'wekan-cfs-worker', - version: '0.1.5', - summary: 'CollectionFS, file worker - handles file copies/versions' -}); - -Package.onUse(function(api) { - api.use([ - 'wekan-cfs-base-package@0.0.30', - 'wekan-cfs-tempstore@0.1.6', - 'wekan-cfs-storage-adapter@0.2.1' - ]); - - api.use([ - 'livedata@1.0.0', - 'mongo-livedata@1.0.0', - 'wekan-cfs-power-queue@0.9.11' - ]); - - api.addFiles([ - 'fileWorker.js' - ], 'server'); -}); - -// Package.on_test(function (api) { -// api.use('wekan-cfs-standard-packages@0.0.0'); - -// api.use('test-helpers', 'server'); -// api.use(['tinytest', 'underscore', 'ejson', 'ordered-dict', 'random']); - -// api.addFiles('tests/client-tests.js', 'client'); -// api.addFiles('tests/server-tests.js', 'server'); -// }); diff --git a/packages/wekan-cfs-worker/tests/client-tests.js b/packages/wekan-cfs-worker/tests/client-tests.js deleted file mode 100644 index 49a100846..000000000 --- a/packages/wekan-cfs-worker/tests/client-tests.js +++ /dev/null @@ -1,44 +0,0 @@ -function equals(a, b) { - return !!(EJSON.stringify(a) === EJSON.stringify(b)); -} - -Tinytest.add('cfs-worker - client - test environment', function(test) { - test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection'); - test.isTrue(typeof CFSErrorType !== 'undefined', 'test environment not initialized CFSErrorType'); -}); - -/* - * FS.File Client Tests - * - * construct FS.File with no arguments - * construct FS.File passing in File - * construct FS.File passing in Blob - * load blob into FS.File and then call FS.File.toDataUrl - * call FS.File.setDataFromBinary, then FS.File.getBlob(); make sure correct data is returned - * load blob into FS.File and then call FS.File.getBinary() with and without start/end; make sure correct data is returned - * construct FS.File, set FS.File.collectionName to a CFS name, and then test FS.File.update/remove/get/put/del/url - * set FS.File.name to a filename and test that FS.File.getExtension() returns the extension - * load blob into FS.File and make sure FS.File.saveLocal initiates a download (possibly can't do automatically) - * - */ - - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg) diff --git a/packages/wekan-cfs-worker/tests/server-tests.js b/packages/wekan-cfs-worker/tests/server-tests.js deleted file mode 100644 index 713ebc07c..000000000 --- a/packages/wekan-cfs-worker/tests/server-tests.js +++ /dev/null @@ -1,49 +0,0 @@ -function equals(a, b) { - return !!(EJSON.stringify(a) === EJSON.stringify(b)); -} - -Tinytest.add('cfs-worker - server - test environment', function(test) { - test.isTrue(typeof FS.Collection !== 'undefined', 'test environment not initialized FS.Collection'); - test.isTrue(typeof CFSErrorType !== 'undefined', 'test environment not initialized CFSErrorType'); -}); - -/* - * FS.File Server Tests - * - * construct FS.File with no arguments - * load data with FS.File.setDataFromBuffer - * load data with FS.File.setDataFromBinary - * load data and then call FS.File.toDataUrl with and without callback - * load buffer into FS.File and then call FS.File.getBinary with and without start/end; make sure correct data is returned - * construct FS.File, set FS.File.collectionName to a CFS name, and then test FS.File.update/remove/get/put/del/url - * (call these with and without callback to test sync vs. async) - * set FS.File.name to a filename and test that FS.File.getExtension() returns the extension - * - * - * FS.Collection Server Tests - * - * Make sure options.filter is respected - * - * - */ - - -//Test API: -//test.isFalse(v, msg) -//test.isTrue(v, msg) -//test.equalactual, expected, message, not -//test.length(obj, len) -//test.include(s, v) -//test.isNaN(v, msg) -//test.isUndefined(v, msg) -//test.isNotNull -//test.isNull -//test.throws(func) -//test.instanceOf(obj, klass) -//test.notEqual(actual, expected, message) -//test.runId() -//test.exception(exception) -//test.expect_fail() -//test.ok(doc) -//test.fail(doc) -//test.equal(a, b, msg)