├── .cirrus.yml ├── .editorconfig ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .huskyrc.js ├── .vscode └── launch.json ├── CHANGELOG.md ├── CONTRIBUTING.md ├── LICENSE.txt ├── README.md ├── commitlint.config.js ├── greenkeeper.json ├── lerna.json ├── logo-browserstack.png ├── logo-progresskinvey.png ├── package-lock.json ├── package.json ├── packages ├── angular-sdk │ ├── .editorconfig │ ├── .gitignore │ ├── CHANGELOG.md │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── README.md │ ├── code-of-conduct.md │ ├── package-lock.json │ ├── package.json │ ├── scripts │ │ └── postbuild.js │ ├── src │ │ ├── datastore.service.ts │ │ ├── endpoint.service.ts │ │ ├── files.service.ts │ │ ├── index.ts │ │ ├── kinvey.module.ts │ │ ├── mfa.service.ts │ │ ├── ping.service.ts │ │ ├── user.service.ts │ │ └── utils.ts │ ├── tsconfig.json │ └── tslint.json ├── eslint-config │ ├── .gitignore │ ├── CHANGELOG.md │ ├── index.js │ ├── package-lock.json │ └── package.json ├── html5-sdk │ ├── .editorconfig │ ├── .gitignore │ ├── CHANGELOG.md │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── README.md │ ├── code-of-conduct.md │ ├── package-lock.json │ ├── package.json │ ├── scripts │ │ └── postbuild.js │ ├── src │ │ ├── httpAdapter.ts │ │ ├── index.ts │ │ ├── init.ts │ │ ├── popup.ts │ │ ├── sessionStore.ts │ │ └── storage │ │ │ ├── index.ts │ │ │ ├── indexeddb.ts │ │ │ ├── localstorage.ts │ │ │ ├── memory.ts │ │ │ ├── sessionstorage.ts │ │ │ └── websql.ts │ ├── tsconfig.json │ ├── tslint.json │ └── webpack.config.js ├── js-sdk │ ├── .editorconfig │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .gitignore │ ├── .prettierrc.js │ ├── CHANGELOG.md │ ├── LICENSE │ ├── README.md │ ├── babel.config.js │ ├── jest.config.js │ ├── package-lock.json │ ├── package.json │ ├── src │ │ ├── acl.ts │ │ ├── aggregation.ts │ │ ├── config.ts │ │ ├── datastore │ │ │ ├── autostore.ts │ │ │ ├── cache.ts │ │ │ ├── cachestore.ts │ │ │ ├── index.ts │ │ │ ├── networkstore.ts │ │ │ └── sync.ts │ │ ├── device.ts │ │ ├── endpoint.ts │ │ ├── errors │ │ │ ├── activeUser.ts │ │ │ ├── apiVersionNotAvailable.ts │ │ │ ├── apiVersionNotImplemented.ts │ │ │ ├── appProblem.ts │ │ │ ├── badRequest.ts │ │ │ ├── base.ts │ │ │ ├── bl.ts │ │ │ ├── corsDisabled.ts │ │ │ ├── duplicateEndUsers.ts │ │ │ ├── featureUnavailable.ts │ │ │ ├── incompleteRequestBody.ts │ │ │ ├── index.ts │ │ │ ├── indirectCollectionAccessDisallowed.ts │ │ │ ├── insufficientCredentials.ts │ │ │ ├── invalidCredentials.ts │ │ │ ├── invalidIdentifier.ts │ │ │ ├── invalidQuerySyntax.ts │ │ │ ├── jsonParse.ts │ │ │ ├── kinvey.ts │ │ │ ├── kinveyInternalErrorRetry.ts │ │ │ ├── kinveyInternalErrorStop.ts │ │ │ ├── missingConfiguration.ts │ │ │ ├── missingQuery.ts │ │ │ ├── missingRequestHeader.ts │ │ │ ├── missingRequestParameter.ts │ │ │ ├── mobileIdentityConnect.ts │ │ │ ├── network.ts │ │ │ ├── noActiveUser.ts │ │ │ ├── noResponse.ts │ │ │ ├── notFound.ts │ │ │ ├── parameterValueOutOfRange.ts │ │ │ ├── popup.ts │ │ │ ├── query.ts │ │ │ ├── resultSetSizeExceeded.ts │ │ │ ├── server.ts │ │ │ ├── staleRequest.ts │ │ │ ├── sync.ts │ │ │ ├── timeout.ts │ │ │ ├── userAlreadyExists.ts │ │ │ └── writesToCollectionDisallowed.ts │ │ ├── files │ │ │ ├── create.ts │ │ │ ├── download.ts │ │ │ ├── downloadByUrl.ts │ │ │ ├── find.ts │ │ │ ├── findById.ts │ │ │ ├── index.ts │ │ │ ├── remove.ts │ │ │ ├── removeById.ts │ │ │ ├── stream.ts │ │ │ ├── update.ts │ │ │ └── upload.ts │ │ ├── http │ │ │ ├── headers.ts │ │ │ ├── http.ts │ │ │ ├── index.ts │ │ │ ├── request.ts │ │ │ ├── response.ts │ │ │ ├── session.ts │ │ │ └── utils.ts │ │ ├── index.ts │ │ ├── init.ts │ │ ├── kinvey.ts │ │ ├── kmd.ts │ │ ├── live.ts │ │ ├── log.ts │ │ ├── mfa │ │ │ └── index.ts │ │ ├── observable.ts │ │ ├── ping.ts │ │ ├── query.ts │ │ ├── storage.ts │ │ └── user │ │ │ ├── createMFAAuthenticator.ts │ │ │ ├── exists.ts │ │ │ ├── forgotUsername.ts │ │ │ ├── getActiveUser.ts │ │ │ ├── index.ts │ │ │ ├── invalidateTokens.ts │ │ │ ├── login.ts │ │ │ ├── loginWithMFA.ts │ │ │ ├── loginWithMIC.ts │ │ │ ├── loginWithMICUsingResourceOwnerCredentials.ts │ │ │ ├── loginWithRecoveryCode.ts │ │ │ ├── loginWithRedirectUri.ts │ │ │ ├── loginWithSocialIdentity.ts │ │ │ ├── logout.ts │ │ │ ├── lookup.ts │ │ │ ├── me.ts │ │ │ ├── mic │ │ │ ├── getTokenWithCode.ts │ │ │ ├── getTokenWithUsernamePassword.ts │ │ │ ├── index.ts │ │ │ ├── loginWithPopup.ts │ │ │ ├── popup.ts │ │ │ └── utils.ts │ │ │ ├── registerForLiveService.ts │ │ │ ├── remove.ts │ │ │ ├── resetPassword.ts │ │ │ ├── restore.ts │ │ │ ├── signup.ts │ │ │ ├── signupWithIdentity.ts │ │ │ ├── unregisterFromLiveService.ts │ │ │ ├── update.ts │ │ │ ├── user.ts │ │ │ ├── utils.ts │ │ │ └── verifyEmail.ts │ ├── test │ │ ├── datastore │ │ │ ├── autostore.spec.ts │ │ │ ├── networkstore.spec.ts │ │ │ └── syncstore.spec.ts │ │ ├── http.ts │ │ ├── kinvey.spec.ts │ │ ├── memory.ts │ │ ├── mic │ │ │ ├── mic.spec.ts │ │ │ └── session-management.test.ts │ │ ├── query.spec.ts │ │ ├── sessionStore.ts │ │ └── user │ │ │ ├── signup.spec.ts │ │ │ └── user.spec.ts │ ├── tests │ │ ├── sample.spec.ts │ │ └── tsconfig.json │ └── tsconfig.json ├── nativescript-sdk │ ├── .editorconfig │ ├── .gitignore │ ├── CHANGELOG.md │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── README.md │ ├── angular │ │ ├── index.d.ts │ │ ├── index.js │ │ ├── push.d.ts │ │ └── push.js │ ├── code-of-conduct.md │ ├── nativescript-hook-scripts │ │ ├── before-checkForChanges.js │ │ ├── before-preview-sync.js │ │ ├── postinstall.js │ │ └── preuninstall.js │ ├── package-lock.json │ ├── package.json │ ├── platforms │ │ ├── android │ │ │ ├── AndroidManifest.default.xml │ │ │ ├── AndroidManifest.mic.xml │ │ │ └── include.gradle │ │ └── ios │ │ │ ├── app.entitlements │ │ │ ├── info.default.plist │ │ │ └── info.mic.plist │ ├── push.js │ ├── reference.d.ts │ ├── scripts │ │ └── postbuild.js │ ├── src │ │ ├── angular │ │ │ ├── datastore.service.ts │ │ │ ├── endpoint.service.ts │ │ │ ├── files.service.ts │ │ │ ├── index.ts │ │ │ ├── kinvey.module.ts │ │ │ ├── ping.service.ts │ │ │ ├── push.module.ts │ │ │ ├── push.service.ts │ │ │ ├── push.ts │ │ │ ├── user.service.ts │ │ │ └── utils.ts │ │ └── nativescript │ │ │ ├── files │ │ │ ├── index.ts │ │ │ └── upload.ts │ │ │ ├── httpAdapter.ts │ │ │ ├── index.ts │ │ │ ├── init.ts │ │ │ ├── live.ts │ │ │ ├── popup │ │ │ ├── index.ts │ │ │ ├── popup.android.ts │ │ │ ├── popup.ios.ts │ │ │ └── popup.ts │ │ │ ├── push.ts │ │ │ ├── sessionStore.ts │ │ │ ├── storage │ │ │ ├── index.ts │ │ │ └── sqlite.ts │ │ │ ├── user │ │ │ ├── index.ts │ │ │ ├── loginWithMIC.ts │ │ │ └── loginWithRedirectUri.ts │ │ │ └── utils.ts │ ├── tsconfig.json │ └── tslint.json ├── node-sdk │ ├── .editorconfig │ ├── .gitignore │ ├── CHANGELOG.md │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── README.md │ ├── code-of-conduct.md │ ├── package-lock.json │ ├── package.json │ ├── scripts │ │ └── postbuild.js │ ├── src │ │ ├── httpAdapter.ts │ │ ├── index.ts │ │ ├── init.ts │ │ ├── popup.ts │ │ ├── sessionStore.ts │ │ └── storage │ │ │ ├── index.ts │ │ │ └── memory.ts │ ├── tsconfig.json │ └── tslint.json └── react-native-sdk │ ├── .editorconfig │ ├── .eslintrc │ ├── .gitignore │ ├── .prettierrc │ ├── CHANGELOG.md │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── README.md │ ├── code-of-conduct.md │ ├── jest.config.js │ ├── jest.setup.ts │ ├── package-lock.json │ ├── package.json │ ├── scripts │ └── postbuild.js │ ├── src │ ├── httpAdapter.ts │ ├── index.ts │ ├── init.ts │ ├── popup.ts │ ├── push.ts │ ├── sessionStore.ts │ └── storage │ │ ├── asyncStorage.ts │ │ ├── index.ts │ │ └── memory.ts │ ├── test │ ├── asyncStorage.spec.ts │ ├── popup.spec.ts │ └── push.spec.ts │ ├── tsconfig.jest.json │ └── tsconfig.json └── tests ├── integration ├── clean.js ├── copy-specs.js ├── html5 │ ├── .gitignore │ ├── babel.config.js │ ├── karma.conf.js │ ├── mocha.opts │ ├── package-lock.json │ ├── package.json │ └── webpack.config.js ├── nativescript │ ├── .gitignore │ ├── babel.config.js │ ├── karma.conf.js │ ├── mocha.opts │ ├── package-lock.json │ ├── package.json │ ├── scripts │ │ ├── AndroidManifest.xml │ │ ├── app.gradle │ │ ├── fix-nativescript-build-xcconfig.js │ │ ├── nativescript.config.ts │ │ └── test.js │ └── webpack.config.js ├── node │ ├── .gitignore │ ├── babel.config.js │ ├── mocha.opts │ ├── package-lock.json │ └── package.json ├── package-lock.json ├── package.json ├── react-native │ ├── .gitignore │ ├── babel.config.json │ ├── jest.config.js │ ├── jest.setup.ts │ ├── package-lock.json │ └── package.json ├── setup.js ├── shared.js └── specs │ ├── common │ ├── aggregation.spec.js │ ├── auth.spec.js │ ├── autostore.spec.js │ ├── common-crud.spec.js │ ├── delta-set.spec.js │ ├── endpoint.spec.js │ ├── files.spec_skip.js │ ├── live-services.spec.js │ ├── mfa.spec.js │ ├── offline-crud.spec.js │ ├── sync.spec.js │ └── users.spec.js │ ├── config.js │ ├── constants.js │ ├── fixtures │ ├── test1.png │ ├── test1.txt │ └── test2.txt │ ├── html5 │ ├── files.spec.js │ ├── init.spec.js │ └── mic.spec.js │ ├── nativescript │ └── files.spec.js │ └── utils.js ├── node_modules ├── kinvey-html5-sdk │ └── package.json ├── kinvey-nativescript-sdk │ └── package.json ├── kinvey-node-sdk │ └── package.json └── kinvey-react-native-sdk │ └── package.json └── unit ├── cache.spec.js ├── datastore ├── cache │ └── indexeddb.spec.js ├── cachestore.spec.js ├── datastore.spec.js ├── networkstore.spec.js └── syncstore.spec.js ├── files └── files.spec.js ├── http └── headers.spec.js └── user ├── user.spec.js └── utils.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig helps developers define and maintain consistent 2 | # coding styles between different editors and IDEs 3 | # editorconfig.org 4 | 5 | root = true 6 | 7 | [*] 8 | 9 | # Change these settings to your own preference 10 | indent_style = space 11 | indent_size = 2 12 | 13 | # We recommend you to keep these unchanged 14 | end_of_line = lf 15 | charset = utf-8 16 | trim_trailing_whitespace = true 17 | insert_final_newline = true 18 | 19 | [*.md] 20 | trim_trailing_whitespace = false 21 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ### Description 2 | 3 | 4 | ### Kinvey SDK Version 5 | 6 | 7 | #### NodeJS version 8 | 9 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | #### Description 2 | 3 | 4 | #### Changes 5 | 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Dependency directories 9 | node_modules 10 | 11 | # Typescript v1 declaration files 12 | typings 13 | 14 | # Optional npm cache directory 15 | .npm 16 | 17 | # Yarn Integrity file 18 | .yarn-integrity 19 | 20 | # Windows 21 | Thumbs.db 22 | Desktop.ini 23 | 24 | # Mac 25 | .DS_Store 26 | 27 | # WebStorm 28 | .idea 29 | 30 | !tests/node_modules 31 | tests/integration/.env 32 | -------------------------------------------------------------------------------- /.huskyrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | hooks: { 3 | 'commit-msg': 'commitlint -E HUSKY_GIT_PARAMS' 4 | } 5 | }; 6 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "node", 9 | "request": "launch", 10 | "name": "unit:js", 11 | "cwd": "${workspaceRoot}", 12 | "runtimeExecutable": "npm", 13 | "runtimeArgs": [ 14 | "run", "test-unit:js", "--" 15 | ], 16 | "skipFiles": [ 17 | "/**/*.js" 18 | ], 19 | "autoAttachChildProcesses": true 20 | }, 21 | { 22 | "type": "node", 23 | "request": "launch", 24 | "name": "integration:node", 25 | "cwd": "${workspaceRoot}", 26 | "runtimeExecutable": "npm", 27 | "runtimeArgs": [ 28 | "run", "test-integration:node-debug", "--", "--" 29 | ], 30 | "skipFiles": [ 31 | "/**/*.js" 32 | ], 33 | "autoAttachChildProcesses": true, 34 | "timeout": 20000 35 | }, 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes for the respective packages of this monorepo can be found here: 3 | 4 | [js-sdk](https://github.com/Kinvey/js-sdk/blob/master/packages/js-sdk/CHANGELOG.md)
5 | [html5-sdk](https://github.com/Kinvey/js-sdk/blob/master/packages/html5-sdk/CHANGELOG.md)
6 | [angular-sdk](https://github.com/Kinvey/js-sdk/blob/master/packages/angular-sdk/CHANGELOG.md)
7 | [nativescript-sdk](https://github.com/Kinvey/js-sdk/blob/master/packages/nativescript-sdk/CHANGELOG.md)
8 | [node-sdk](https://github.com/Kinvey/js-sdk/blob/master/packages/node-sdk/CHANGELOG.md)
9 | [react-native-sdk](https://github.com/Kinvey/js-sdk/blob/master/packages/react-native-sdk/CHANGELOG.md)
-------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@commitlint/config-conventional'] 3 | }; 4 | -------------------------------------------------------------------------------- /greenkeeper.json: -------------------------------------------------------------------------------- 1 | { 2 | "groups": { 3 | "default": { 4 | "packages": [ 5 | "package.json", 6 | "packages/angular-sdk/package.json", 7 | "packages/eslint-config/package.json", 8 | "packages/html5-sdk/package.json", 9 | "packages/js-sdk/package.json", 10 | "packages/nativescript-sdk/package.json", 11 | "packages/node-sdk/package.json", 12 | "packages/react-native-sdk/package.json" 13 | ] 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "packages": [ 3 | "packages/*" 4 | ], 5 | "version": "independent", 6 | "command": { 7 | "version": { 8 | "conventionalCommits": true, 9 | "createRelease": true, 10 | "message": "chore(release): publish" 11 | } 12 | }, 13 | "ignoreChanges": [ 14 | "**/__fixtures__/**", 15 | "**/__tests__/**", 16 | "**/*.md", 17 | "**/package.json", 18 | "**/package-lock.json", 19 | "**/tsconfig.json", 20 | "**/tslint.json", 21 | "**/webpack.config.js" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /logo-browserstack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kinvey/js-sdk/c41448007075d726519828d1a4f5208fe30c1d0b/logo-browserstack.png -------------------------------------------------------------------------------- /logo-progresskinvey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kinvey/js-sdk/c41448007075d726519828d1a4f5208fe30c1d0b/logo-progresskinvey.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "kinvey", 4 | "scripts": { 5 | "bootstrap": "lerna bootstrap", 6 | "test": "npm run test-unit && npm run test-integration", 7 | "test-unit": "npm run test-unit:js && npm run test-unit:react-native", 8 | "test-unit:js": "lerna run build --scope kinvey-js-sdk --stream && lerna run test --scope kinvey-js-sdk --stream", 9 | "test-unit:react-native": "lerna run build --scope kinvey-react-native-sdk --stream && lerna run test --scope kinvey-react-native-sdk --stream", 10 | "test-integration": "npm run test-integration:html5 && npm run test-integration:nativescript && npm run test-integration:node && npm run test-integration:react-native", 11 | "test-integration:html5": "cd tests/integration && npm i && cd html5 && npm i --no-audit && npm test", 12 | "test-integration:html5-debug": "cd tests/integration && npm i && cd html5 && npm i --no-audit && npm run test-debug", 13 | "test-integration:nativescript": "cd tests/integration && npm i && cd nativescript && npm i --no-audit && npm test", 14 | "test-integration:react-native": "cd tests/integration && npm i && cd react-native && npm i --no-audit && npm test", 15 | "test-integration:node": "cd tests/integration && npm i && cd node && npm i --no-audit && npm test", 16 | "test-integration:node-debug": "cd tests/integration && npm i && cd node && npm i --no-audit && npm run test-debug" 17 | }, 18 | "devDependencies": { 19 | "@commitlint/cli": "8.1.0", 20 | "@commitlint/config-conventional": "8.1.0", 21 | "commitizen": "4.0.3", 22 | "cz-conventional-changelog": "3.0.2", 23 | "husky": "3.0.4", 24 | "lerna": "3.16.4" 25 | }, 26 | "config": { 27 | "commitizen": { 28 | "path": "./node_modules/cz-conventional-changelog" 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/angular-sdk/.editorconfig: -------------------------------------------------------------------------------- 1 | #root = true 2 | 3 | [*] 4 | indent_style = space 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | max_line_length = 100 10 | indent_size = 2 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /packages/angular-sdk/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .idea 3 | .DS_Store 4 | *.log 5 | node_modules 6 | lib 7 | dist 8 | *.tgz 9 | -------------------------------------------------------------------------------- /packages/angular-sdk/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | We're really glad you're reading this, because we need volunteer developers to help this project come to fruition. 👏 2 | 3 | ## Instructions 4 | 5 | These steps will guide you through contributing to this project: 6 | 7 | - Fork the repo 8 | - Clone it and install dependencies 9 | 10 | git clone https://github.com/YOUR-USERNAME/typescript-library-starter 11 | npm install 12 | 13 | Keep in mind that after running `npm install` the git repo is reset. So a good way to cope with this is to have a copy of the folder to push the changes, and the other to try them. 14 | 15 | Make and commit your changes. Make sure the commands npm run build and npm run test:prod are working. 16 | 17 | Finally send a [GitHub Pull Request](https://github.com/alexjoverm/typescript-library-starter/compare?expand=1) with a clear list of what you've done (read more [about pull requests](https://help.github.com/articles/about-pull-requests/)). Make sure all of your commits are atomic (one feature per commit). 18 | -------------------------------------------------------------------------------- /packages/angular-sdk/README.md: -------------------------------------------------------------------------------- 1 | # Kinvey Angular SDK 2 | 3 | ## Installation 4 | 5 | From the command prompt go to your app's root folder and execute: 6 | 7 | ```bash 8 | npm i kinvey-angular-sdk@next 9 | ``` 10 | 11 | ## Usage 12 | Import the `KinveyModule` in your `app.module.ts` like this to initialize the SDK: 13 | 14 | ```js 15 | import { NgModule } from '@angular/core'; 16 | import { KinveyModule } from 'kinvey-angular-sdk'; 17 | 18 | @NgModule({ 19 | imports: [ 20 | KinveyModule.init({ 21 | appKey: '', 22 | appSecret: '' 23 | }) 24 | ] 25 | }) 26 | export class AppModule { } 27 | ``` 28 | 29 | Then you can use dependency injection to inject a Kinvey service in your module like this: 30 | 31 | ```js 32 | import { Component } from '@angular/core'; 33 | import { UserService } from 'kinvey-angular-sdk'; 34 | 35 | @Component() 36 | export class AppComponent { 37 | constructor(private userService: UserService) {} 38 | 39 | async login() { 40 | try { 41 | const user = await this.userService.login('', ''); 42 | console.log(user); 43 | } catch (error) { 44 | console.log(error); 45 | } 46 | } 47 | } 48 | ``` 49 | 50 | The following services are available to use with dependency injection: 51 | 52 | - `DataStoreService` 53 | - `EndpointService` 54 | - `FilesService` 55 | - `PingService` 56 | - `UserService` 57 | 58 | ## Build 59 | 60 | If you would like to build the SDK yourself, clone the monorepo, then: 61 | - `npm i` 62 | - `npm run build` 63 | 64 | You can then install the SDK build by running `npm i //packages/angular-sdk` 65 | -------------------------------------------------------------------------------- /packages/angular-sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kinvey-angular-sdk", 3 | "description": "Kinvey JavaScript SDK for Angular applications.", 4 | "version": "9.0.0", 5 | "license": "Apache-2.0", 6 | "homepage": "https://github.com/Kinvey/js-sdk/tree/master/packages/angular-sdk", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/Kinvey/js-sdk.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/Kinvey/js-sdk/issues" 13 | }, 14 | "author": { 15 | "name": "Thomas Conner", 16 | "email": "thomas.conner@progress.com" 17 | }, 18 | "keywords": [ 19 | "Kinvey", 20 | "JavaScript", 21 | "Angular" 22 | ], 23 | "main": "lib/index.js", 24 | "scripts": { 25 | "prebuild": "del lib", 26 | "build": "ngc -p tsconfig.json" 27 | }, 28 | "dependencies": { 29 | "kinvey-html5-sdk": "9.0.0", 30 | "tslib": "2.5.3" 31 | }, 32 | "peerDependencies": { 33 | "@angular/core": "~12.0.5" 34 | }, 35 | "devDependencies": { 36 | "@angular/compiler": "~12.0.5", 37 | "@angular/compiler-cli": "~12.0.5", 38 | "@angular/core": "~12.0.5", 39 | "del-cli": "2.0.0", 40 | "fs-extra": "~8.1.0", 41 | "typescript": "4.2.3" 42 | }, 43 | "files": [ 44 | "lib/**/*" 45 | ] 46 | } 47 | -------------------------------------------------------------------------------- /packages/angular-sdk/scripts/postbuild.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs-extra'); 2 | const path = require('path'); 3 | 4 | const rootPath = path.join(__dirname, '..'); 5 | const libPath = path.join(rootPath, 'lib'); 6 | const tmpPath = path.join(rootPath, 'tmp'); 7 | 8 | // Copy /lib to /tmp 9 | fs.copySync(libPath, tmpPath); 10 | 11 | // Remove /lib 12 | fs.removeSync(libPath); 13 | 14 | // Copy /tmp/src to /lib 15 | fs.copySync(path.join(tmpPath, 'src'), libPath); 16 | 17 | // Remove /tmp 18 | fs.removeSync(tmpPath); 19 | -------------------------------------------------------------------------------- /packages/angular-sdk/src/datastore.service.ts: -------------------------------------------------------------------------------- 1 | import { Inject, Injectable } from '@angular/core'; 2 | import { init, DataStore, DataStoreType } from 'kinvey-html5-sdk'; 3 | import { KinveyConfigToken } from './utils'; 4 | ; 5 | 6 | @Injectable({ 7 | providedIn: 'root' 8 | }) 9 | export class DataStoreService { 10 | constructor(@Inject(KinveyConfigToken) config: any) { 11 | init(config); 12 | } 13 | 14 | collection(collectionName: string, type?: DataStoreType, options?: any): any { 15 | return DataStore.collection(collectionName, type, options); 16 | } 17 | 18 | clearCache(): any { 19 | return DataStore.clearCache(); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/angular-sdk/src/endpoint.service.ts: -------------------------------------------------------------------------------- 1 | import { Inject, Injectable } from '@angular/core'; 2 | import { init, CustomEndpoint } from 'kinvey-html5-sdk'; 3 | import { KinveyConfigToken } from './utils'; 4 | 5 | @Injectable({ 6 | providedIn: 'root' 7 | }) 8 | export class EndpointService { 9 | constructor(@Inject(KinveyConfigToken) config: any) { 10 | init(config); 11 | } 12 | 13 | endpoint(endpoint: string, args?: any, options?: any) { 14 | return CustomEndpoint.execute(endpoint, args, options); 15 | } 16 | 17 | execute(endpoint: string, args?: any, options?: any) { 18 | return this.endpoint(endpoint, args, options); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/angular-sdk/src/files.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Inject } from '@angular/core'; 2 | import { init, Files, Query } from 'kinvey-html5-sdk'; 3 | import { KinveyConfigToken } from './utils'; 4 | 5 | @Injectable({ 6 | providedIn: 'root' 7 | }) 8 | export class FilesService { 9 | constructor(@Inject(KinveyConfigToken) config: any) { 10 | init(config); 11 | } 12 | 13 | create(file: any, metadata: any, options?: any) { 14 | return Files.create(file, metadata, options); 15 | } 16 | 17 | download(id?: string, options?: any) { 18 | return Files.download(id, options); 19 | } 20 | 21 | downloadByUrl(url: string, options?: any) { 22 | return Files.downloadByUrl(url, options); 23 | } 24 | 25 | find(query?: Query, options?: any) { 26 | return Files.find(query, options); 27 | } 28 | 29 | findById(id: string, options?: any) { 30 | return Files.findById(id, options); 31 | } 32 | 33 | remove() { 34 | return Files.remove(); 35 | } 36 | 37 | removeById(id: string, options?: any) { 38 | return Files.removeById(id, options); 39 | } 40 | 41 | stream(id: string, options?: any) { 42 | return Files.stream(id, options); 43 | } 44 | 45 | update(file: any, metadata: any, options?: any) { 46 | return Files.update(file, metadata, options); 47 | } 48 | 49 | upload(file: any, metadata: any, options?: any) { 50 | return Files.upload(file, metadata, options); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/angular-sdk/src/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | getAppVersion, 3 | setAppVersion, 4 | logger, 5 | Acl, 6 | Aggregation, 7 | StorageProvider, 8 | DataStoreType, 9 | Errors, 10 | Kmd, 11 | Query, 12 | AuthorizationGrant, 13 | LoginOptions, 14 | MFAContext, 15 | MFACompleteResult 16 | } from 'kinvey-html5-sdk'; 17 | import { DataStoreService } from './datastore.service'; 18 | import { EndpointService } from './endpoint.service'; 19 | import { FilesService } from './files.service'; 20 | import { KinveyModule } from './kinvey.module'; 21 | import { PingService } from './ping.service'; 22 | import { UserService } from './user.service'; 23 | import { MFAService } from "./mfa.service"; 24 | 25 | export { 26 | // Init 27 | KinveyModule, 28 | StorageProvider, 29 | 30 | // App Version 31 | getAppVersion, 32 | setAppVersion, 33 | 34 | // Logger 35 | logger, 36 | 37 | // Ping 38 | PingService, 39 | 40 | // Acl 41 | Acl, 42 | 43 | // Aggregation 44 | Aggregation, 45 | 46 | // Custom Endpoint 47 | EndpointService, 48 | 49 | // DataStore 50 | DataStoreService, 51 | DataStoreType, 52 | 53 | // Errors 54 | Errors, 55 | 56 | // Files 57 | FilesService, 58 | 59 | // Kmd 60 | Kmd, 61 | Kmd as Metadata, 62 | 63 | // Query 64 | Query, 65 | 66 | // User 67 | UserService, 68 | AuthorizationGrant, 69 | LoginOptions, 70 | MFAContext, 71 | MFACompleteResult, 72 | MFAService 73 | }; 74 | -------------------------------------------------------------------------------- /packages/angular-sdk/src/kinvey.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule, ModuleWithProviders } from '@angular/core'; 2 | import { KinveyConfigToken } from './utils'; 3 | import { DataStoreService } from './datastore.service'; 4 | import { EndpointService } from './endpoint.service'; 5 | import { FilesService } from './files.service'; 6 | import { PingService } from './ping.service'; 7 | import { UserService } from './user.service'; 8 | 9 | @NgModule() 10 | export class KinveyModule { 11 | static init(config: any): ModuleWithProviders { 12 | return { 13 | ngModule: KinveyModule, 14 | providers: [ 15 | DataStoreService, 16 | EndpointService, 17 | FilesService, 18 | PingService, 19 | UserService, 20 | { provide: KinveyConfigToken, useValue: config } 21 | ] 22 | }; 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /packages/angular-sdk/src/mfa.service.ts: -------------------------------------------------------------------------------- 1 | import { Inject, Injectable } from '@angular/core'; 2 | import { init, MFA } from 'kinvey-html5-sdk'; 3 | import { KinveyConfigToken } from './utils'; 4 | 5 | @Injectable({ 6 | providedIn: 'root' 7 | }) 8 | 9 | export class MFAService { 10 | constructor(@Inject(KinveyConfigToken) config: any) { 11 | init(config); 12 | } 13 | 14 | public readonly Authenticators: any = MFA.Authenticators; 15 | 16 | listRecoveryCodes() { 17 | return MFA.listRecoveryCodes(); 18 | } 19 | 20 | regenerateRecoveryCodes() { 21 | return MFA.regenerateRecoveryCodes(); 22 | } 23 | 24 | isEnabled() { 25 | return MFA.isEnabled(); 26 | } 27 | 28 | disable() { 29 | return MFA.disable(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /packages/angular-sdk/src/ping.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Inject } from '@angular/core'; 2 | import { init, ping } from 'kinvey-html5-sdk'; 3 | import { KinveyConfigToken } from './utils'; 4 | 5 | @Injectable({ 6 | providedIn: 'root' 7 | }) 8 | export class PingService { 9 | constructor(@Inject(KinveyConfigToken) config: any) { 10 | init(config); 11 | } 12 | 13 | ping(): Promise { 14 | return ping(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/angular-sdk/src/utils.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from '@angular/core'; 2 | 3 | export const KinveyConfigToken = new InjectionToken('kinvey.config'); 4 | -------------------------------------------------------------------------------- /packages/angular-sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "es6", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "noImplicitUseStrict": true, 10 | "noEmitHelpers": true, 11 | "declaration": true, 12 | "removeComments": false, 13 | "noEmitOnError": true, 14 | "noImplicitAny": false, 15 | "importHelpers": true, 16 | "lib": [ 17 | "dom", 18 | "es6", 19 | "es2015.iterable" 20 | ], 21 | "esModuleInterop": true, 22 | "allowSyntheticDefaultImports": true, 23 | "outDir": "lib" 24 | }, 25 | "angularCompilerOptions": { 26 | "genDir": ".", 27 | "skipMetadataEmit": false, 28 | "skipTemplateCodegen": true, 29 | "strictMetadataEmit": true 30 | }, 31 | "exclude": [ 32 | "node_modules" 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /packages/angular-sdk/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint-config-standard", 4 | "tslint-config-prettier" 5 | ] 6 | } -------------------------------------------------------------------------------- /packages/eslint-config/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Dependency directories 9 | node_modules 10 | 11 | # Optional npm cache directory 12 | .npm 13 | 14 | # Yarn Integrity file 15 | .yarn-integrity 16 | 17 | # dotenv environment variables file 18 | .env 19 | 20 | # Windows 21 | Thumbs.db 22 | Desktop.ini 23 | 24 | # Mac 25 | .DS_Store 26 | 27 | # Build 28 | lib 29 | 30 | # Output of 'npm pack' 31 | *.tgz 32 | -------------------------------------------------------------------------------- /packages/eslint-config/CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | All notable changes to this project will be documented in this file. 4 | See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. 5 | 6 | ## 1.0.2 (2019-09-03) 7 | 8 | 9 | ### Bug Fixes 10 | 11 | * **eslint-config:** add peerDependencies as devDependencies ([9044d35](https://github.com/Kinvey/js-sdk/commit/9044d35)) 12 | -------------------------------------------------------------------------------- /packages/eslint-config/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | 'airbnb-base', 4 | 'plugin:@typescript-eslint/recommended', 5 | 'prettier/@typescript-eslint', 6 | 'plugin:prettier/recommended' 7 | ], 8 | parser: '@typescript-eslint/parser', 9 | parserOptions: { 10 | ecmaVersion: 2018, 11 | sourceType: 'module' 12 | }, 13 | plugins: [ 14 | '@typescript-eslint' 15 | ], 16 | rules: { 17 | 'lines-between-class-members': 'off', 18 | 'no-dupe-class-members': 'off', 19 | 'semi': 'error', 20 | 21 | // Import 22 | 'import/prefer-default-export': 'off', 23 | 24 | // Typescript 25 | '@typescript-eslint/explicit-member-accessibility': 'off', 26 | '@typescript-eslint/no-explicit-any': 'off', 27 | 28 | // Prettier 29 | 'prettier/prettier': ['error', { 'singleQuote': true }] 30 | }, 31 | settings: { 32 | 'import/resolver': { 33 | node: { 34 | extensions: [ 35 | '.js', 36 | '.ts', 37 | '.tsx' 38 | ] 39 | } 40 | } 41 | } 42 | }; 43 | -------------------------------------------------------------------------------- /packages/eslint-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "eslint-config-kinvey-js-sdk", 4 | "description": "Kinvey JavaScript SDK config for ESLint.", 5 | "version": "1.0.2", 6 | "license": "Apache-2.0", 7 | "main": "index.js", 8 | "peerDependencies": { 9 | "@typescript-eslint/eslint-plugin": "^2.0.0", 10 | "@typescript-eslint/parser": "^2.0.0", 11 | "eslint": "^6.2.1", 12 | "eslint-config-airbnb-base": "^14.0.0", 13 | "eslint-config-kinvey-platform": "kinvey/eslint-kinvey-platform#0.1.6", 14 | "eslint-config-prettier": "^6.1.0", 15 | "eslint-plugin-import": "^2.18.2", 16 | "eslint-plugin-prettier": "^3.1.0", 17 | "prettier": "^1.18.2", 18 | "typescript": "^3.5.3" 19 | }, 20 | "devDependencies": { 21 | "@typescript-eslint/eslint-plugin": "^2.0.0", 22 | "@typescript-eslint/parser": "^2.0.0", 23 | "eslint": "^6.2.1", 24 | "eslint-config-airbnb-base": "^14.0.0", 25 | "eslint-config-kinvey-platform": "kinvey/eslint-kinvey-platform#0.1.6", 26 | "eslint-config-prettier": "^6.1.0", 27 | "eslint-plugin-import": "^2.18.2", 28 | "eslint-plugin-prettier": "^3.1.0", 29 | "prettier": "^1.18.2", 30 | "typescript": "^3.5.3" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /packages/html5-sdk/.editorconfig: -------------------------------------------------------------------------------- 1 | #root = true 2 | 3 | [*] 4 | indent_style = space 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | max_line_length = 100 10 | indent_size = 2 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /packages/html5-sdk/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .idea 3 | .DS_Store 4 | *.log 5 | node_modules 6 | lib 7 | dist 8 | *.tgz 9 | -------------------------------------------------------------------------------- /packages/html5-sdk/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | We're really glad you're reading this, because we need volunteer developers to help this project come to fruition. 👏 2 | 3 | ## Instructions 4 | 5 | These steps will guide you through contributing to this project: 6 | 7 | - Fork the repo 8 | - Clone it and install dependencies 9 | 10 | git clone https://github.com/YOUR-USERNAME/typescript-library-starter 11 | npm install 12 | 13 | Keep in mind that after running `npm install` the git repo is reset. So a good way to cope with this is to have a copy of the folder to push the changes, and the other to try them. 14 | 15 | Make and commit your changes. Make sure the commands npm run build and npm run test:prod are working. 16 | 17 | Finally send a [GitHub Pull Request](https://github.com/alexjoverm/typescript-library-starter/compare?expand=1) with a clear list of what you've done (read more [about pull requests](https://help.github.com/articles/about-pull-requests/)). Make sure all of your commits are atomic (one feature per commit). 18 | -------------------------------------------------------------------------------- /packages/html5-sdk/README.md: -------------------------------------------------------------------------------- 1 | # Kinvey HTML5 SDK 2 | 3 | ## Installation 4 | 5 | From the command prompt go to your app's root folder and execute: 6 | 7 | ```bash 8 | npm i kinvey-html5-sdk@next 9 | ``` 10 | 11 | or if you would prefer you can just [download the latest bundle](https://download.kinvey.com/js/kinvey-html5-sdk-3.13.0-next.28.js) and include it in your application. 12 | 13 | ## Usage 14 | 15 | ### Initialize SDK 16 | 17 | We need to initialize the SDK. 18 | 19 | #### JavaScript with NPM 20 | ```js 21 | import * as Kinvey from 'kinvey-html5-sdk'; 22 | 23 | Kinvey.init({ 24 | appKey: '', 25 | appSecret: '' 26 | }); 27 | ``` 28 | 29 | #### JavaScript with bundle 30 | ```js 31 | window.Kinvey.init({ 32 | appKey: '', 33 | appSecret: '' 34 | }); 35 | ``` 36 | 37 | #### Angular 38 | Please take a look at our `kinvey-angular-sdk`. 39 | 40 | ## Build 41 | 42 | If you would like to build the SDK yourself, clone the monorepo, then: 43 | - `npm i` 44 | - `npm run build` 45 | 46 | You can then install the SDK build by running `npm i //packages/html5-sdk` 47 | -------------------------------------------------------------------------------- /packages/html5-sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kinvey-html5-sdk", 3 | "description": "Kinvey JavaScript SDK for HTML5 applications.", 4 | "version": "9.0.0", 5 | "license": "Apache-2.0", 6 | "homepage": "https://github.com/Kinvey/js-sdk/tree/master/packages/html5-sdk", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/Kinvey/js-sdk.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/Kinvey/js-sdk/issues" 13 | }, 14 | "author": { 15 | "name": "Thomas Conner", 16 | "email": "thomas.conner@progress.com" 17 | }, 18 | "keywords": [ 19 | "Kinvey", 20 | "JavaScript", 21 | "HTML5" 22 | ], 23 | "main": "lib/index.js", 24 | "scripts": { 25 | "prebuild": "del lib", 26 | "build": "tsc -p tsconfig.json", 27 | "postbuild": "node scripts/postbuild.js", 28 | "prebundle": "npm run build", 29 | "bundle": "webpack" 30 | }, 31 | "dependencies": { 32 | "axios": "0.26.1", 33 | "kinvey-js-sdk": "8.0.0", 34 | "lodash-es": "4.17.21", 35 | "pubnub": "5.0.1", 36 | "tslib": "2.5.3" 37 | }, 38 | "devDependencies": { 39 | "@types/events": "^3.0.0", 40 | "@types/lodash-es": "4.14.7", 41 | "clean-webpack-plugin": "~3.0.0", 42 | "del-cli": "2.0.0", 43 | "fs-extra": "~8.1.0", 44 | "typescript": "4.2.3", 45 | "webpack": "~4.39.1", 46 | "webpack-cli": "^3.3.0" 47 | }, 48 | "files": [ 49 | "lib/**/*" 50 | ] 51 | } 52 | -------------------------------------------------------------------------------- /packages/html5-sdk/scripts/postbuild.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs-extra'); 2 | const path = require('path'); 3 | 4 | const rootPath = path.join(__dirname, '..'); 5 | const libPath = path.join(rootPath, 'lib'); 6 | const tmpPath = path.join(rootPath, 'tmp'); 7 | 8 | // Copy /lib to /tmp 9 | fs.copySync(libPath, tmpPath); 10 | 11 | // Remove /lib 12 | fs.removeSync(libPath); 13 | 14 | // Copy /tmp/src to /lib 15 | fs.copySync(path.join(tmpPath, 'src'), libPath); 16 | 17 | // Remove /tmp 18 | fs.removeSync(tmpPath); 19 | -------------------------------------------------------------------------------- /packages/html5-sdk/src/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | getAppVersion, 3 | setAppVersion, 4 | logger, 5 | ping, 6 | Acl, 7 | Aggregation, 8 | CustomEndpoint, 9 | DataStore, 10 | DataStoreType, 11 | Errors, 12 | Files, 13 | Kmd, 14 | Query, 15 | User, 16 | AuthorizationGrant, 17 | MFA, 18 | LoginOptions, 19 | MFAContext, 20 | MFACompleteResult, 21 | } from 'kinvey-js-sdk'; 22 | import { init, initialize } from './init'; 23 | import { StorageProvider } from './storage'; 24 | 25 | // SDK 26 | export { 27 | // Init 28 | init, 29 | initialize, 30 | StorageProvider, 31 | 32 | // App Version 33 | getAppVersion, 34 | setAppVersion, 35 | 36 | // Logger 37 | logger, 38 | 39 | // Ping 40 | ping, 41 | 42 | // Acl 43 | Acl, 44 | 45 | // Aggregation 46 | Aggregation, 47 | 48 | // Custom Endpoint 49 | CustomEndpoint, 50 | 51 | // DataStore 52 | DataStore, 53 | DataStoreType, 54 | 55 | // Errors 56 | Errors, 57 | 58 | // Files 59 | Files, 60 | 61 | // Kmd 62 | Kmd, 63 | Kmd as Metadata, 64 | 65 | // Query 66 | Query, 67 | 68 | // User 69 | User, 70 | AuthorizationGrant, 71 | LoginOptions, 72 | MFAContext, 73 | MFACompleteResult, 74 | MFA 75 | }; 76 | -------------------------------------------------------------------------------- /packages/html5-sdk/src/init.ts: -------------------------------------------------------------------------------- 1 | import { init as coreInit } from 'kinvey-js-sdk'; 2 | import PubNub from 'pubnub'; 3 | import * as HttpAdapter from './httpAdapter'; 4 | import * as SessionStore from './sessionStore'; 5 | import * as Popup from './popup'; 6 | import { getStorageAdapter, StorageProvider } from './storage'; 7 | 8 | export interface KinveyConfig { 9 | appKey: string; 10 | appSecret: string; 11 | masterSecret?: string; 12 | appVersion?: string; 13 | instanceId?: string; 14 | storage?: StorageProvider; 15 | } 16 | 17 | export function init(config: KinveyConfig) { 18 | const kinveyConfig = coreInit({ 19 | kinveyConfig: config, 20 | httpAdapter: HttpAdapter, 21 | sessionStore: SessionStore, 22 | popup: Popup, 23 | storageAdapter: getStorageAdapter(config.storage), 24 | pubnub: PubNub 25 | }) 26 | return Object.assign({}, kinveyConfig, { storage: config.storage, _storage: config.storage }); 27 | } 28 | 29 | export function initialize(config: KinveyConfig) { 30 | return init(config); 31 | } 32 | -------------------------------------------------------------------------------- /packages/html5-sdk/src/popup.ts: -------------------------------------------------------------------------------- 1 | import { EventEmitter } from 'events'; 2 | 3 | const LOADED_EVENT = 'loaded'; 4 | const CLOSED_EVENT = 'closed'; 5 | const ERROR_EVENT = 'error'; 6 | 7 | class Popup extends EventEmitter { 8 | private popupWindow: Window | null; 9 | private interval: number | null; 10 | 11 | constructor(popupWindow: Window) { 12 | super(); 13 | this.popupWindow = popupWindow; 14 | this.interval = window.setInterval(() => { 15 | if (popupWindow.closed) { 16 | this.close(); 17 | } else { 18 | try { 19 | const event = { url: popupWindow.location.href }; 20 | this.emit(LOADED_EVENT, event); 21 | } catch (error) { 22 | if (error.code !== (window as any).DOMException.SECURITY_ERR) { 23 | this.emit(ERROR_EVENT, error); 24 | } 25 | } 26 | } 27 | }, 100); 28 | } 29 | 30 | isClosed() { 31 | return this.popupWindow && this.popupWindow.closed === true || false; 32 | } 33 | 34 | onLoaded(listener: (...args: any[]) => void) { 35 | return this.on(LOADED_EVENT, listener); 36 | } 37 | 38 | onClosed(listener: (...args: any[]) => void) { 39 | return this.on(CLOSED_EVENT, listener); 40 | } 41 | 42 | onError(listener: (...args: any[]) => void) { 43 | return this.on(ERROR_EVENT, listener); 44 | } 45 | 46 | async close() { 47 | if (this.interval) { 48 | window.clearInterval(this.interval); 49 | this.interval = null; 50 | } 51 | 52 | if (this.popupWindow && !this.popupWindow.closed) { 53 | this.popupWindow.close(); 54 | this.popupWindow = null; 55 | } 56 | 57 | this.emit(CLOSED_EVENT); 58 | } 59 | 60 | static async open(url: string) { 61 | const popupWindow = window.open(url, '_blank', 'toolbar=no,location=no'); 62 | 63 | if (!popupWindow) { 64 | throw new Error('The popup was blocked.'); 65 | } 66 | 67 | return new Popup(popupWindow); 68 | } 69 | } 70 | 71 | export function open(url: string) { 72 | return Popup.open(url); 73 | } 74 | -------------------------------------------------------------------------------- /packages/html5-sdk/src/sessionStore.ts: -------------------------------------------------------------------------------- 1 | export async function get(key: string): Promise { 2 | return window.localStorage.getItem(key); 3 | } 4 | 5 | export async function set(key: string, session: string): Promise { 6 | window.localStorage.setItem(key, session); 7 | return true; 8 | } 9 | 10 | export async function remove(key: string): Promise { 11 | window.localStorage.removeItem(key); 12 | return true; 13 | } 14 | -------------------------------------------------------------------------------- /packages/html5-sdk/src/storage/index.ts: -------------------------------------------------------------------------------- 1 | import { Errors } from 'kinvey-js-sdk'; 2 | import * as IndexedDB from './indexeddb'; 3 | import * as LocalStorage from './localstorage'; 4 | import * as Memory from './memory'; 5 | import * as SessionStorage from './sessionstorage'; 6 | import * as WebSQL from './websql'; 7 | 8 | export enum StorageProvider { 9 | IndexedDB = 'IndexedDB', 10 | LocalStorage = 'LocalStorage', 11 | Memory = 'Memory', 12 | SessionStorage = 'SessionStorage', 13 | WebSQL = 'WebSQL' 14 | }; 15 | 16 | export function getStorageAdapter(storageProvider) { 17 | if (storageProvider === StorageProvider.IndexedDB) { 18 | return IndexedDB; 19 | } else if (storageProvider === StorageProvider.LocalStorage) { 20 | return LocalStorage; 21 | } else if (storageProvider === StorageProvider.Memory) { 22 | return Memory; 23 | } else if (storageProvider === StorageProvider.SessionStorage) { 24 | return SessionStorage; 25 | } else if (storageProvider === StorageProvider.WebSQL) { 26 | return WebSQL; 27 | } 28 | 29 | throw new Errors.KinveyError(`Please specify 'storage' option. Supported values are: ${Object.values(StorageProvider)}.`); 30 | } 31 | -------------------------------------------------------------------------------- /packages/html5-sdk/src/storage/memory.ts: -------------------------------------------------------------------------------- 1 | const store = new Map>(); 2 | 3 | function getTable(dbName: string, tableName: string) { 4 | return store.get(`${dbName}.${tableName}`) || new Map(); 5 | } 6 | 7 | function setTable(dbName: string, tableName: string, table: Map) { 8 | return store.set(`${dbName}.${tableName}`, table); 9 | } 10 | 11 | export async function find(dbName: string, tableName: string) { 12 | const table = getTable(dbName, tableName); 13 | return Array.from(table.values()); 14 | } 15 | 16 | export async function count(dbName: string, tableName: string) { 17 | const docs = await find(dbName, tableName); 18 | return docs.length; 19 | } 20 | 21 | export async function findById(dbName: string, tableName: string, id: string) { 22 | const docs = await find(dbName, tableName); 23 | return docs.find((doc: any) => doc._id === id); 24 | } 25 | 26 | export async function save(dbName: string, tableName: string, docs: any = []) { 27 | const table = getTable(dbName, tableName); 28 | docs.forEach((doc: { _id: string; }) => { 29 | table.set(doc._id, doc); 30 | }); 31 | setTable(dbName, tableName, table); 32 | return docs; 33 | } 34 | 35 | export async function removeById(dbName: string, tableName: string, id: string) { 36 | const table = getTable(dbName, tableName); 37 | if (table.delete(id)) { 38 | setTable(dbName, tableName, table); 39 | return 1; 40 | } 41 | return 0; 42 | } 43 | 44 | export async function removeManyById(dbName: string, tableName: string, ids: string[]) { 45 | const table = getTable(dbName, tableName); 46 | const deleted = ids.map(id => table.delete(id)); 47 | setTable(dbName, tableName, table); 48 | return deleted.filter(i => i).length; 49 | } 50 | 51 | export async function clear(dbName: string, tableName: string) { 52 | store.delete(`${dbName}.${tableName}`); 53 | return true; 54 | } 55 | 56 | export async function clearDatabase() { 57 | store.clear(); 58 | return true; 59 | } 60 | -------------------------------------------------------------------------------- /packages/html5-sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es6", 4 | "module": "es6", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "noImplicitUseStrict": true, 10 | "noEmitHelpers": true, 11 | "declaration": true, 12 | "removeComments": false, 13 | "noEmitOnError": true, 14 | "noImplicitAny": false, 15 | "importHelpers": true, 16 | "lib": [ 17 | "dom", 18 | "es6", 19 | "es2015.iterable" 20 | ], 21 | "esModuleInterop": true, 22 | "resolveJsonModule": true, 23 | "allowSyntheticDefaultImports": true, 24 | "outDir": "lib", 25 | "skipLibCheck": true 26 | }, 27 | "exclude": [ 28 | "node_modules" 29 | ] 30 | } 31 | -------------------------------------------------------------------------------- /packages/html5-sdk/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "class-name": true, 4 | "comment-format": [ 5 | true, 6 | "check-space" 7 | ], 8 | "indent": [ 9 | true, 10 | "spaces" 11 | ], 12 | "no-duplicate-variable": true, 13 | "no-eval": true, 14 | "no-internal-module": true, 15 | "no-trailing-whitespace": true, 16 | "no-var-keyword": true, 17 | "one-line": [ 18 | true, 19 | "check-open-brace", 20 | "check-whitespace" 21 | ], 22 | "quotemark": [ 23 | false, 24 | "double" 25 | ], 26 | "semicolon": [ 27 | true, 28 | "always" 29 | ], 30 | "triple-equals": [ 31 | true, 32 | "allow-null-check" 33 | ], 34 | "typedef-whitespace": [ 35 | true, 36 | { 37 | "call-signature": "nospace", 38 | "index-signature": "nospace", 39 | "parameter": "nospace", 40 | "property-declaration": "nospace", 41 | "variable-declaration": "nospace" 42 | } 43 | ], 44 | "variable-name": [ 45 | true, 46 | "ban-keywords" 47 | ], 48 | "whitespace": [ 49 | true, 50 | "check-branch", 51 | "check-decl", 52 | "check-operator", 53 | "check-separator", 54 | "check-type" 55 | ] 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/html5-sdk/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | const path = require('path'); 3 | const { CleanWebpackPlugin } = require('clean-webpack-plugin'); 4 | const pkg = require('./package.json'); 5 | 6 | const BANNER = ` 7 | /** 8 | * ${pkg.name} - ${pkg.description} 9 | * @version ${pkg.version} 10 | * @author ${pkg.author.name} 11 | * @license ${pkg.license} 12 | */ 13 | `; 14 | 15 | module.exports = { 16 | mode: 'production', 17 | entry: path.join(__dirname, pkg.main), 18 | output: { 19 | filename: `${pkg.name}-${pkg.version}.min.js`, 20 | path: path.join(__dirname, 'dist'), 21 | libraryTarget: 'umd', 22 | library: 'Kinvey' 23 | }, 24 | resolve: { 25 | extensions: ['.js', '.json'] 26 | }, 27 | plugins: [ 28 | new CleanWebpackPlugin(), 29 | new webpack.BannerPlugin({ 30 | banner: BANNER, 31 | raw: true 32 | }) 33 | ], 34 | performance: { 35 | hints: false, 36 | maxEntrypointSize: 512000, 37 | maxAssetSize: 512000 38 | } 39 | }; 40 | -------------------------------------------------------------------------------- /packages/js-sdk/.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | indent_style = space 3 | end_of_line = lf 4 | charset = utf-8 5 | trim_trailing_whitespace = true 6 | insert_final_newline = true 7 | max_line_length = 120 8 | indent_size = 2 9 | 10 | [*.md] 11 | trim_trailing_whitespace = false 12 | -------------------------------------------------------------------------------- /packages/js-sdk/.eslintignore: -------------------------------------------------------------------------------- 1 | # path/to/project/root/.eslintignore 2 | # /node_modules/* and /bower_components/* in the project root are ignored by default 3 | 4 | # Ignore built files 5 | lib/* 6 | -------------------------------------------------------------------------------- /packages/js-sdk/.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: [ 3 | 'airbnb-base', 4 | 'kinvey-platform', 5 | 'plugin:@typescript-eslint/recommended', 6 | 'prettier/@typescript-eslint', 7 | 'plugin:prettier/recommended', 8 | ], 9 | parser: '@typescript-eslint/parser', 10 | rules: { 11 | // Import 12 | 'import/extensions': [ 13 | 'error', 14 | { 15 | '.js': 'never', 16 | '.jsx': 'never', 17 | '.ts': 'always', 18 | '.tsx': 'never' 19 | } 20 | ], 21 | // 'import/prefer-default-export': 'off', 22 | 23 | // TypeScript 24 | '@typescript-eslint/camelcase': 'off', 25 | '@typescript-eslint/explicit-member-accessibility': 'off', 26 | '@typescript-eslint/no-explicit-any': 'off', 27 | }, 28 | settings: { 29 | 'import/resolver': { 30 | node: { 31 | extensions: [ 32 | '.js', 33 | '.jsx', 34 | '.json', 35 | '.ts', 36 | '.tsx', 37 | ] 38 | } 39 | }, 40 | 'import/extensions': [ 41 | '.js', 42 | '.jsx', 43 | '.json', 44 | '.ts', 45 | '.tsx' 46 | ], 47 | }, 48 | overrides: [ 49 | { 50 | files: ['src/**/*.test.ts'], 51 | rules: { 52 | 'spaced-comment': 'off', 53 | 'func-names': 'off', 54 | 'no-undef': 'off', 55 | 'no-unused-expressions': 'off', 56 | 57 | // Import 58 | 'import/no-extraneous-dependencies': 'off', 59 | 60 | // TypeScript 61 | '@typescript-eslint/ban-ts-ignore': 'off', 62 | '@typescript-eslint/explicit-function-return-type': 'off', 63 | }, 64 | env: { 65 | jest: true, 66 | }, 67 | } 68 | ] 69 | }; 70 | -------------------------------------------------------------------------------- /packages/js-sdk/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Dependency directories 9 | node_modules 10 | 11 | # Optional npm cache directory 12 | .npm 13 | 14 | # Optional eslint cache 15 | .eslintcache 16 | 17 | # Yarn Integrity file 18 | .yarn-integrity 19 | 20 | # dotenv environment variables file 21 | .env 22 | 23 | # Windows 24 | Thumbs.db 25 | Desktop.ini 26 | 27 | # Mac 28 | .DS_Store 29 | 30 | # Build 31 | lib 32 | 33 | # Output of 'npm pack' 34 | *.tgz 35 | 36 | # Code Coverage 37 | .nyc_output 38 | coverage 39 | -------------------------------------------------------------------------------- /packages/js-sdk/.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | arrowParens: 'always', 3 | printWidth: 120, 4 | singleQuote: true, 5 | trailingComma: 'es5', 6 | }; 7 | -------------------------------------------------------------------------------- /packages/js-sdk/README.md: -------------------------------------------------------------------------------- 1 | # Kinvey JavaScript SDK 2 | -------------------------------------------------------------------------------- /packages/js-sdk/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: ['@babel/preset-env'], 3 | }; 4 | -------------------------------------------------------------------------------- /packages/js-sdk/jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | collectCoverage: true, 3 | transform: { 4 | '^.+\\.(js|jsx)?$': 'babel-jest', 5 | '^.+\\.tsx?$': 'ts-jest', 6 | }, 7 | transformIgnorePatterns: ['node_modules\\/(?!(lodash-es)\\/)'], 8 | testMatch: ['/test/*.spec.ts'], 9 | }; 10 | -------------------------------------------------------------------------------- /packages/js-sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kinvey-js-sdk", 3 | "description": "Kinvey JavaScript SDK for JavaScript applications.", 4 | "version": "8.0.0", 5 | "license": "Apache-2.0", 6 | "keywords": [ 7 | "Kinvey", 8 | "JavaScript" 9 | ], 10 | "main": "lib/index.js", 11 | "scripts": { 12 | "prebuild": "del lib", 13 | "build": "tsc -p tsconfig.json", 14 | "lint": "tsc --noEmit && eslint 'src/**/*.{js,ts}' --quiet --fix", 15 | "test": "jest", 16 | "test:watch": "jest --watch" 17 | }, 18 | "dependencies": { 19 | "events": "3.0.0", 20 | "js-base64": "2.5.1", 21 | "lodash-es": "4.17.21", 22 | "loglevel": "1.6.3", 23 | "loglevel-plugin-prefix": "0.8.4", 24 | "p-queue": "~7.0.0", 25 | "rxjs": "~6.5.3", 26 | "sift": "~7.0.1", 27 | "tslib": "1.10.0", 28 | "url": "0.11.0", 29 | "url-join": "4.0.1" 30 | }, 31 | "devDependencies": { 32 | "@babel/preset-env": "7.22.5", 33 | "@types/events": "3.0.0", 34 | "@types/jest": "24.0.18", 35 | "@types/js-base64": "2.3.1", 36 | "@types/lodash-es": "4.17.7", 37 | "@types/loglevel": "1.6.3", 38 | "@types/node": "12.7.2", 39 | "@types/url-join": "4.0.0", 40 | "@typescript-eslint/eslint-plugin": "2.0.0", 41 | "@typescript-eslint/parser": "2.0.0", 42 | "axios": "0.19.0", 43 | "babel-jest": "29.5.0", 44 | "chai": "4.2.0", 45 | "chai-as-promised": "7.1.1", 46 | "del-cli": "2.0.0", 47 | "eslint": "6.2.1", 48 | "eslint-config-airbnb-base": "13.2.0", 49 | "eslint-config-kinvey-platform": "kinvey/eslint-kinvey-platform#0.1.6", 50 | "eslint-config-prettier": "6.1.0", 51 | "eslint-plugin-import": "2.18.2", 52 | "eslint-plugin-prettier": "3.1.0", 53 | "jest": "24.8.0", 54 | "nock": "10.0.6", 55 | "prettier": "1.18.2", 56 | "ts-jest": "24.0.2", 57 | "ts-node": "8.3.0", 58 | "typescript": "4.2.3" 59 | }, 60 | "files": [ 61 | "lib/**/*" 62 | ] 63 | } 64 | -------------------------------------------------------------------------------- /packages/js-sdk/src/config.ts: -------------------------------------------------------------------------------- 1 | const config = new Map(); 2 | 3 | export enum ConfigKey { 4 | KinveyConfig, 5 | HttpAdapter, 6 | SessionStore, 7 | StorageAdapter, 8 | Popup, 9 | PubNub 10 | } 11 | 12 | export function getConfig(key: ConfigKey) { 13 | return config.get(key) as T; 14 | } 15 | 16 | export function setConfig(key: ConfigKey, value: any) { 17 | return config.set(key, value); 18 | } 19 | -------------------------------------------------------------------------------- /packages/js-sdk/src/datastore/cache.ts: -------------------------------------------------------------------------------- 1 | import { isString } from 'lodash-es'; 2 | import { Storage, Entity } from '../storage'; 3 | import { Query } from '../query'; 4 | import { getAppKey } from '../kinvey'; 5 | 6 | const QUERY_CACHE_TAG = '_QueryCache'; 7 | const SYNC_CACHE_TAG = 'kinvey_sync'; 8 | 9 | export function isValidTag(tag: string) { 10 | const regexp = /^[a-z0-9-]+$/i; 11 | return isString(tag) && regexp.test(tag); 12 | } 13 | 14 | export class DataStoreCache extends Storage { 15 | constructor(collectionName: string, tag?: string) { 16 | if (tag && !isValidTag(tag)) { 17 | throw new Error('A tag can only contain letters, numbers, and "-".'); 18 | } 19 | 20 | if (tag) { 21 | super(getAppKey(), `${collectionName}.${tag}`); 22 | } else { 23 | super(getAppKey(), collectionName); 24 | } 25 | } 26 | 27 | static clear() { 28 | return Storage.clear(getAppKey()); 29 | } 30 | } 31 | 32 | export interface QueryEntity extends Entity { 33 | collectionName: string; 34 | query: string; 35 | lastRequest: string | null; 36 | } 37 | 38 | export class QueryCache extends DataStoreCache { 39 | constructor(tag?: string) { 40 | super(QUERY_CACHE_TAG, tag); 41 | } 42 | } 43 | 44 | export enum SyncEvent { 45 | Create = 'POST', 46 | Update = 'PUT', 47 | Delete = 'DELETE' 48 | }; 49 | 50 | export interface SyncEntity extends Entity { 51 | entityId: string; 52 | collection: string; 53 | state: { 54 | operation: SyncEvent; 55 | } 56 | } 57 | 58 | export class SyncCache extends DataStoreCache { 59 | constructor(tag?: string) { 60 | super(SYNC_CACHE_TAG, tag); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /packages/js-sdk/src/datastore/index.ts: -------------------------------------------------------------------------------- 1 | import { isString } from 'lodash-es'; 2 | import { KinveyError } from '../errors/kinvey'; 3 | import { logger } from '../log'; 4 | import { isValidTag } from './cache'; 5 | import { NetworkStore } from './networkstore'; 6 | import { CacheStore } from './cachestore'; 7 | import { DataStoreCache } from './cache'; 8 | import { AutoStore } from './autostore'; 9 | 10 | export enum DataStoreType { 11 | Auto = 'Auto', 12 | Cache = 'Cache', 13 | Network = 'Network', 14 | Sync = 'Sync' 15 | }; 16 | 17 | export function collection(collectionName: string, type = DataStoreType.Cache, options: any = {}) { 18 | let datastore; 19 | const tagWasPassed = options && ('tag' in options); 20 | 21 | if (collectionName == null || !isString(collectionName)) { 22 | throw new KinveyError('A collection is required and must be a string.'); 23 | } 24 | if (tagWasPassed && !isValidTag(options.tag)) { 25 | throw new KinveyError('Please provide a valid data store tag.'); 26 | } 27 | 28 | if (type === DataStoreType.Auto) { 29 | datastore = new AutoStore(collectionName, Object.assign({}, options, { autoSync: true })); 30 | } else if (type === DataStoreType.Cache) { 31 | logger.warn('DataStoreType.Cache will be deprecated soon. Please use DataStoreType.Auto instead.'); 32 | datastore = new CacheStore(collectionName, Object.assign({}, options, { autoSync: true })); 33 | } else if (type === DataStoreType.Network) { 34 | if (tagWasPassed) { 35 | throw new KinveyError('The tagged option is not valid for data stores of type "Network"'); 36 | } 37 | 38 | datastore = new NetworkStore(collectionName); 39 | } else if (type === DataStoreType.Sync) { 40 | datastore = new CacheStore(collectionName, Object.assign({}, options, { autoSync: false })); 41 | } else { 42 | throw new KinveyError('Unknown data store type.'); 43 | } 44 | 45 | return datastore; 46 | } 47 | 48 | export function getInstance(collectionName: string, type?: DataStoreType, options?: any) { 49 | return collection(collectionName, type, options); 50 | } 51 | 52 | export function clearCache() { 53 | return DataStoreCache.clear(); 54 | } 55 | -------------------------------------------------------------------------------- /packages/js-sdk/src/device.ts: -------------------------------------------------------------------------------- 1 | import { getAppKey } from './kinvey'; 2 | import { Storage, Entity } from './storage'; 3 | 4 | const COLLECTION_NAME = '_Device'; 5 | 6 | function s4() { 7 | return Math.floor((1 + Math.random()) * 0x10000) 8 | .toString(16) 9 | .substring(1); 10 | } 11 | 12 | function uuidv4() { 13 | return `${s4()}${s4()}-${s4()}-${s4()}-${s4()}-${s4()}${s4()}${s4()}`; 14 | } 15 | 16 | export interface DeviceEntity extends Entity { 17 | uuid: string; 18 | } 19 | 20 | export async function getDeviceId(): Promise { 21 | const storage = new Storage(getAppKey(), COLLECTION_NAME); 22 | const docs = await storage.find(); 23 | let doc = docs.shift(); 24 | 25 | if (!doc) { 26 | doc = await storage.save({ uuid: uuidv4() }); 27 | } 28 | 29 | return doc.uuid; 30 | } 31 | -------------------------------------------------------------------------------- /packages/js-sdk/src/endpoint.ts: -------------------------------------------------------------------------------- 1 | import { isString } from 'lodash-es'; 2 | import { formatKinveyBaasUrl, HttpRequestMethod, KinveyHttpRequest, KinveyBaasNamespace, KinveyHttpAuth } from './http'; 3 | import { KinveyError } from './errors/kinvey'; 4 | 5 | export interface EndpointOptions { 6 | timeout?: number; 7 | } 8 | 9 | export async function endpoint(endpoint: string, args?: any, options: EndpointOptions = {}) { 10 | if (!isString(endpoint)) { 11 | throw new KinveyError('An endpoint is required and must be a string.'); 12 | } 13 | 14 | const request = new KinveyHttpRequest({ 15 | method: HttpRequestMethod.POST, 16 | auth: KinveyHttpAuth.SessionOrMaster, 17 | url: formatKinveyBaasUrl(KinveyBaasNamespace.Rpc, `/custom/${endpoint}`), 18 | body: args, 19 | timeout: options.timeout 20 | }); 21 | const response = await request.execute(); 22 | return response.data; 23 | } 24 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/activeUser.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class ActiveUserError extends KinveyError { 4 | constructor(message = 'An active user already exists.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'ActiveUserError'; 7 | } 8 | } 9 | 10 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/apiVersionNotAvailable.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class APIVersionNotAvailableError extends KinveyError { 4 | constructor(message = 'This API version is not available for your app.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'APIVersionNotAvailableError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/apiVersionNotImplemented.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class APIVersionNotImplementedError extends KinveyError { 4 | constructor(message = 'This API version is not implemented.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'APIVersionNotImplementedError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/appProblem.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class AppProblemError extends KinveyError { 4 | constructor(message = 'There is a problem with this app backend that prevents execution of this operation. Please contact support@kinvey.com for assistance.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'AppProblemError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/badRequest.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class BadRequestError extends KinveyError { 4 | constructor(message = 'Unable to understand request.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'BadRequestError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/base.ts: -------------------------------------------------------------------------------- 1 | // export default class BaseError extends Error { 2 | // constructor(message = 'An error occurred.', debug?: string, code?: number, kinveyRequestId?: string, ...args) { 3 | // // Pass remaining arguments (including vendor specific ones) to parent constructor 4 | // super(...args); 5 | 6 | // // Maintains proper stack trace for where our error was thrown (only available on V8) 7 | // if (Error.captureStackTrace) { 8 | // Error.captureStackTrace(this, BaseError); 9 | // } 10 | 11 | // // Custom debugging information 12 | // this.name = 'BaseError'; 13 | // this.message = message; 14 | // this.debug = debug; 15 | // this.code = code; 16 | // this.kinveyRequestId = kinveyRequestId; 17 | // } 18 | // } 19 | 20 | export class BaseError extends Error { 21 | constructor(message = 'An error occurred.') { 22 | super(message); 23 | Object.setPrototypeOf(this, new.target.prototype); 24 | this.name = 'BaseError'; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/bl.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class BLError extends KinveyError { 4 | constructor(message = 'The Business Logic script did not complete.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'BLError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/corsDisabled.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class CORSDisabledError extends KinveyError { 4 | constructor(message = 'Cross Origin Support is disabled for this application.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'CORSDisabledError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/duplicateEndUsers.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class DuplicateEndUsersError extends KinveyError { 4 | constructor(message = 'More than one user registered with this username for this application.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'DuplicateEndUsersError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/featureUnavailable.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class FeatureUnavailableError extends KinveyError { 4 | constructor(message = 'Requested functionality is unavailable in this API version.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'FeatureUnavailableError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/incompleteRequestBody.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class IncompleteRequestBodyError extends KinveyError { 4 | constructor(message = 'The request body is either missing or incomplete.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'IncompleteRequestBodyError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/index.ts: -------------------------------------------------------------------------------- 1 | export * from './activeUser'; 2 | export * from './apiVersionNotAvailable'; 3 | export * from './apiVersionNotImplemented'; 4 | export * from './appProblem'; 5 | export * from './badRequest'; 6 | export * from './base'; 7 | export * from './bl'; 8 | export * from './corsDisabled'; 9 | export * from './duplicateEndUsers'; 10 | export * from './featureUnavailable'; 11 | export * from './incompleteRequestBody'; 12 | export * from './indirectCollectionAccessDisallowed'; 13 | export * from './insufficientCredentials'; 14 | export * from './invalidCredentials'; 15 | export * from './invalidIdentifier'; 16 | export * from './invalidQuerySyntax'; 17 | export * from './jsonParse'; 18 | export * from './kinvey'; 19 | export * from './kinveyInternalErrorRetry'; 20 | export * from './kinveyInternalErrorStop'; 21 | export * from './missingConfiguration'; 22 | export * from './missingQuery'; 23 | export * from './missingRequestHeader'; 24 | export * from './missingRequestParameter'; 25 | export * from './mobileIdentityConnect'; 26 | export * from './network'; 27 | export * from './noActiveUser'; 28 | export * from './noResponse'; 29 | export * from './notFound'; 30 | export * from './parameterValueOutOfRange'; 31 | export * from './popup'; 32 | export * from './query'; 33 | export * from './resultSetSizeExceeded'; 34 | export * from './server'; 35 | export * from './staleRequest'; 36 | export * from './sync'; 37 | export * from './timeout'; 38 | export * from './userAlreadyExists'; 39 | export * from './writesToCollectionDisallowed'; 40 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/indirectCollectionAccessDisallowed.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class IndirectCollectionAccessDisallowedError extends KinveyError { 4 | constructor(message = 'Please use the appropriate API to access this collection for this app backend.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'IndirectCollectionAccessDisallowedError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/insufficientCredentials.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class InsufficientCredentialsError extends KinveyError { 4 | constructor(message = 'The credentials used to authenticate this request are not authorized to run this operation. Please retry your request with appropriate credentials.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'InsufficientCredentialsError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/invalidCredentials.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class InvalidCredentialsError extends KinveyError { 4 | constructor(message = 'Invalid credentials. Please retry your request with correct credentials.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'InvalidCredentialsError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/invalidIdentifier.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class InvalidIdentifierError extends KinveyError { 4 | constructor(message = 'One of more identifier names in the request has an invalid format.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'InvalidIdentifierError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/invalidQuerySyntax.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class InvalidQuerySyntaxError extends KinveyError { 4 | constructor(message = 'The query string in the request has an invalid syntax.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'InvalidQuerySyntaxError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/jsonParse.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class JSONParseError extends KinveyError { 4 | constructor(message = 'Unable to parse the JSON in the request.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'JSONParseError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/kinvey.ts: -------------------------------------------------------------------------------- 1 | export class KinveyError extends Error { 2 | public debug: string; 3 | 4 | public index: number; 5 | 6 | constructor(message = 'An error occurred.', debug = '') { 7 | super(message); 8 | Object.setPrototypeOf(this, new.target.prototype); 9 | this.name = 'KinveyError'; 10 | this.debug = debug; 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/kinveyInternalErrorRetry.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class KinveyInternalErrorRetry extends KinveyError { 4 | constructor(message = 'The Kinvey server encountered an unexpected error. Please retry your request.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'KinveyInternalErrorRetry'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/kinveyInternalErrorStop.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class KinveyInternalErrorStop extends KinveyError { 4 | constructor(message = 'The Kinvey server encountered an unexpected error. Please contact support@kinvey.com for assistance.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'KinveyInternalErrorStop'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/missingConfiguration.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class MissingConfigurationError extends KinveyError { 4 | constructor(message = 'Missing configuration error.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'MissingConfigurationError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/missingQuery.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class MissingQueryError extends KinveyError { 4 | constructor(message = 'The request is missing a query string.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'MissingQueryError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/missingRequestHeader.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class MissingRequestHeaderError extends KinveyError { 4 | constructor(message = 'The request is missing a required header.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'MissingRequestHeaderError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/missingRequestParameter.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class MissingRequestParameterError extends KinveyError { 4 | constructor(message = 'A required parameter is missing from the request.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'MissingRequestParameterError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/mobileIdentityConnect.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class MobileIdentityConnectError extends KinveyError { 4 | constructor(message = 'An error has occurred with Mobile Identity Connect.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'MobileIdentityConnectError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/network.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class NetworkError extends KinveyError { 4 | constructor(message = 'There was an error connecting to the network.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'NetworkError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/noActiveUser.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class NoActiveUserError extends KinveyError { 4 | constructor(message = 'There is not an active user.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'NoActiveUserError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/noResponse.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class NoResponseError extends KinveyError { 4 | constructor(message = 'No response was provided.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'NoResponseError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/notFound.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class NotFoundError extends KinveyError { 4 | constructor(message = 'The entity was not found.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'NotFoundError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/parameterValueOutOfRange.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class ParameterValueOutOfRangeError extends KinveyError { 4 | constructor(message = 'The value specified for one of the request parameters is out of range.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'ParameterValueOutOfRangeError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/popup.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class PopupError extends KinveyError { 4 | constructor(message = 'Unable to open a popup on this platform.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'PopupError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/query.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class QueryError extends KinveyError { 4 | constructor(message = 'An error occurred with the query.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'QueryError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/resultSetSizeExceeded.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class ResultSetSizeExceededError extends KinveyError { 4 | constructor(message = 'Result set size exceeded.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'ResultSetSizeExceededError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/server.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class ServerError extends KinveyError { 4 | constructor(message = 'An error occurred on the server.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'ServerError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/staleRequest.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class StaleRequestError extends KinveyError { 4 | constructor(message = 'The time window for this request has expired.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'StaleRequestError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/sync.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class SyncError extends KinveyError { 4 | constructor(message = 'An error occurred during sync.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'SyncError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/timeout.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class TimeoutError extends KinveyError { 4 | constructor(message = 'The request timed out.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'TimeoutError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/userAlreadyExists.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class UserAlreadyExistsError extends KinveyError { 4 | constructor(message = 'This username is already taken. Please retry your request with a different username.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'UserAlreadyExistsError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/errors/writesToCollectionDisallowed.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from './kinvey'; 2 | 3 | export class WritesToCollectionDisallowedError extends KinveyError { 4 | constructor(message = 'This collection is configured to disallow any modifications to an existing entity or creation of new entities.', debug?: string) { 5 | super(message, debug); 6 | this.name = 'WritesToCollectionDisallowedError'; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/js-sdk/src/files/create.ts: -------------------------------------------------------------------------------- 1 | import { upload } from './upload'; 2 | 3 | export async function create(file: any, metadata: any, options?: any) { 4 | return upload(file, metadata, options); 5 | } 6 | -------------------------------------------------------------------------------- /packages/js-sdk/src/files/download.ts: -------------------------------------------------------------------------------- 1 | import { isNumber } from 'lodash-es'; 2 | import { downloadByUrl } from './downloadByUrl'; 3 | import { KinveyHttpRequest, HttpRequestMethod, KinveyHttpAuth, formatKinveyBaasUrl, KinveyBaasNamespace } from '../http'; 4 | 5 | export async function download(id?: string, options: any = {}) { 6 | const { stream = false, tls = true, ttl } = options; 7 | const queryStringObject: any = Object.assign({}, { tls: tls === true }); 8 | 9 | if (isNumber(ttl)) { 10 | queryStringObject.ttl_in_seconds = ttl; 11 | } 12 | 13 | const request = new KinveyHttpRequest({ 14 | method: HttpRequestMethod.GET, 15 | auth: KinveyHttpAuth.SessionOrMaster, 16 | url: formatKinveyBaasUrl(KinveyBaasNamespace.Blob, `/${id}`, queryStringObject), 17 | timeout: options.timeout 18 | }); 19 | const response = await request.execute(); 20 | const file = response.data; 21 | 22 | if (stream) { 23 | return file; 24 | } 25 | 26 | return downloadByUrl(file._downloadURL, options); 27 | } 28 | -------------------------------------------------------------------------------- /packages/js-sdk/src/files/downloadByUrl.ts: -------------------------------------------------------------------------------- 1 | import { HttpRequest, HttpRequestMethod } from '../http'; 2 | 3 | export async function downloadByUrl(url: string, options: any = {}) { 4 | const request = new HttpRequest({ 5 | method: HttpRequestMethod.GET, 6 | url, 7 | timeout: options.timeout 8 | }); 9 | const response = await request.execute(); 10 | return response.data; 11 | } 12 | -------------------------------------------------------------------------------- /packages/js-sdk/src/files/find.ts: -------------------------------------------------------------------------------- 1 | import { isNumber } from 'lodash-es'; 2 | import { Query } from '../query'; 3 | import { KinveyError } from '../errors/kinvey'; 4 | import { KinveyHttpRequest, HttpRequestMethod, KinveyHttpAuth, formatKinveyBaasUrl, KinveyBaasNamespace } from '../http'; 5 | import { downloadByUrl } from './downloadByUrl'; 6 | 7 | export async function find(query = new Query(), options: any = {}) { 8 | const { download = false, tls = true, ttl } = options; 9 | let queryStringObject: any = Object.assign({}, { tls: tls === true }); 10 | 11 | if (query) { 12 | if (!(query instanceof Query)) { 13 | throw new KinveyError('Invalid query. It must be an instance of the Query class.'); 14 | } 15 | 16 | queryStringObject = Object.assign({}, queryStringObject, query.toQueryObject()); 17 | } 18 | 19 | if (isNumber(ttl)) { 20 | queryStringObject.ttl_in_seconds = ttl; 21 | } 22 | 23 | const request = new KinveyHttpRequest({ 24 | method: HttpRequestMethod.GET, 25 | auth: KinveyHttpAuth.SessionOrMaster, 26 | url: formatKinveyBaasUrl(KinveyBaasNamespace.Blob, '/', queryStringObject), 27 | timeout: options.timeout 28 | }); 29 | const response = await request.execute(); 30 | const files = response.data; 31 | 32 | if (download === true) { 33 | return Promise.all(files.map((file: { _downloadURL: string; }) => downloadByUrl(file._downloadURL, options))); 34 | } 35 | 36 | return files; 37 | } 38 | -------------------------------------------------------------------------------- /packages/js-sdk/src/files/findById.ts: -------------------------------------------------------------------------------- 1 | import { download } from './download'; 2 | 3 | export function findById(id: string, options?: any) { 4 | return download(id, options); 5 | } 6 | -------------------------------------------------------------------------------- /packages/js-sdk/src/files/index.ts: -------------------------------------------------------------------------------- 1 | import { create } from './create'; 2 | import { download } from './download'; 3 | import { downloadByUrl } from './downloadByUrl'; 4 | import { find } from './find'; 5 | import { findById } from './findById'; 6 | import { remove } from './remove'; 7 | import { removeById } from './removeById'; 8 | import { stream } from './stream'; 9 | import { update } from './update'; 10 | import { upload } from './upload'; 11 | 12 | export { 13 | create, 14 | download, 15 | downloadByUrl, 16 | find, 17 | findById, 18 | remove, 19 | removeById, 20 | stream, 21 | update, 22 | upload 23 | }; 24 | -------------------------------------------------------------------------------- /packages/js-sdk/src/files/remove.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from '../errors/kinvey'; 2 | 3 | export async function remove() { 4 | throw new KinveyError('Please use removeById() to remove files one by one.'); 5 | } 6 | -------------------------------------------------------------------------------- /packages/js-sdk/src/files/removeById.ts: -------------------------------------------------------------------------------- 1 | import { KinveyHttpRequest, HttpRequestMethod, KinveyHttpAuth, formatKinveyBaasUrl, KinveyBaasNamespace } from '../http'; 2 | 3 | export async function removeById(id: string, options: any = {}) { 4 | const request = new KinveyHttpRequest({ 5 | method: HttpRequestMethod.DELETE, 6 | auth: KinveyHttpAuth.SessionOrMaster, 7 | url: formatKinveyBaasUrl(KinveyBaasNamespace.Blob, `/${id}`), 8 | timeout: options.timeout 9 | }); 10 | const response = await request.execute(); 11 | return response.data; 12 | } 13 | -------------------------------------------------------------------------------- /packages/js-sdk/src/files/stream.ts: -------------------------------------------------------------------------------- 1 | import { findById } from './findById'; 2 | 3 | export async function stream(id: string, options?: any) { 4 | return findById(id, Object.assign({}, options, { stream: true })); 5 | } 6 | -------------------------------------------------------------------------------- /packages/js-sdk/src/files/update.ts: -------------------------------------------------------------------------------- 1 | import { upload } from './upload'; 2 | 3 | export async function update(file: any, metadata: any, options?: any) { 4 | return upload(file, metadata, options); 5 | } 6 | -------------------------------------------------------------------------------- /packages/js-sdk/src/http/http.ts: -------------------------------------------------------------------------------- 1 | import { ConfigKey, getConfig } from '../config'; 2 | import { HttpHeaders } from './headers'; 3 | import { HttpResponse } from './response'; 4 | 5 | export interface HttpRequestObject { 6 | headers: { [name: string]: string }; 7 | method: string; 8 | url: string; 9 | body?: string; 10 | timeout?: number; 11 | } 12 | 13 | export interface HttpResponseObject { 14 | statusCode: number; 15 | headers: { [name: string]: string }; 16 | data?: string; 17 | } 18 | 19 | export interface HttpAdapter { 20 | send: (request: HttpRequestObject) => Promise; 21 | } 22 | 23 | function getHttpAdapter() { 24 | return getConfig(ConfigKey.HttpAdapter); 25 | } 26 | 27 | export async function send(request: HttpRequestObject) { 28 | const responseObject = await getHttpAdapter().send(request); 29 | return new HttpResponse({ 30 | statusCode: responseObject.statusCode, 31 | headers: new HttpHeaders(responseObject.headers), 32 | data: responseObject.data 33 | }); 34 | } 35 | -------------------------------------------------------------------------------- /packages/js-sdk/src/http/index.ts: -------------------------------------------------------------------------------- 1 | export * from './headers'; 2 | export * from './http'; 3 | export * from './request'; 4 | export * from './response'; 5 | export * from './session'; 6 | export * from './utils'; 7 | -------------------------------------------------------------------------------- /packages/js-sdk/src/http/utils.ts: -------------------------------------------------------------------------------- 1 | import { format } from 'url'; 2 | import urlJoin from 'url-join'; 3 | import { isPlainObject } from 'lodash-es'; 4 | import { getBaasProtocol, getBaasHost, getAuthProtocol, getAuthHost, getAppKey } from '../kinvey' 5 | 6 | function clean(value: { [key: string]: any }) { 7 | return Object.keys(value) 8 | .reduce((cleanVal: { [key: string]: any }, key) => { 9 | let objVal = value[key]; 10 | 11 | if (isPlainObject(objVal)) { 12 | objVal = clean(objVal); 13 | } 14 | 15 | if (typeof objVal !== 'undefined' && objVal !== null) { 16 | cleanVal[key] = objVal; 17 | } 18 | 19 | return cleanVal; 20 | }, {}); 21 | } 22 | 23 | export enum KinveyBaasNamespace { 24 | AppData = 'appdata', 25 | Blob = 'blob', 26 | Push = 'push', 27 | Rpc = 'rpc', 28 | User = 'user' 29 | } 30 | 31 | export function formatKinveyBaasUrl(namespace: KinveyBaasNamespace, path?: string, query?: { [key: string]: any }) { 32 | return format({ 33 | protocol: getBaasProtocol(), 34 | host: getBaasHost(), 35 | pathname: path ? urlJoin(namespace, getAppKey(), path) : urlJoin(namespace, getAppKey()), 36 | query: query ? clean(query) : undefined 37 | }); 38 | } 39 | 40 | export function formatKinveyAuthUrl(path?: string, query?: { [key: string]: any }) { 41 | return format({ 42 | protocol: getAuthProtocol(), 43 | host: getAuthHost(), 44 | pathname: path, 45 | query: query ? clean(query) : undefined 46 | }); 47 | } 48 | -------------------------------------------------------------------------------- /packages/js-sdk/src/index.ts: -------------------------------------------------------------------------------- 1 | import { Acl } from './acl'; 2 | import { Aggregation } from './aggregation'; 3 | import { collection, getInstance, clearCache, DataStoreType } from './datastore'; 4 | import { endpoint } from './endpoint'; 5 | import * as Errors from './errors'; 6 | import * as Files from './files'; 7 | import * as MFA from './mfa'; 8 | import { init, initialize } from './init'; 9 | import { Kmd } from './kmd'; 10 | import { logger } from './log'; 11 | import { ping } from './ping'; 12 | import { Query } from './query'; 13 | import { User, AuthorizationGrant } from './user'; 14 | import { LoginOptions } from './user/login'; 15 | import { MFAContext, MFACompleteResult } from './user/loginWithMFA'; 16 | import { getAppVersion, setAppVersion } from './http'; 17 | 18 | const CustomEndpoint = { execute: endpoint }; 19 | const DataStore = { collection, getInstance, clearCache }; 20 | 21 | export { 22 | // Init 23 | init, 24 | initialize, 25 | 26 | // App Version 27 | getAppVersion, 28 | setAppVersion, 29 | 30 | // Logger 31 | logger, 32 | 33 | // Ping 34 | ping, 35 | 36 | // Acl 37 | Acl, 38 | 39 | // Aggregation 40 | Aggregation, 41 | 42 | // Custom Endpoint 43 | CustomEndpoint, 44 | 45 | // DataStore 46 | DataStore, 47 | DataStoreType, 48 | 49 | // Errors 50 | Errors, 51 | 52 | // Files 53 | Files, 54 | 55 | // Kmd 56 | Kmd, 57 | Kmd as Metadata, 58 | 59 | // Query 60 | Query, 61 | 62 | // User 63 | User, 64 | AuthorizationGrant, 65 | LoginOptions, 66 | MFAContext, 67 | MFACompleteResult, 68 | 69 | MFA 70 | }; 71 | -------------------------------------------------------------------------------- /packages/js-sdk/src/kinvey.ts: -------------------------------------------------------------------------------- 1 | import { isNumber } from 'lodash-es'; 2 | import { getConfig, ConfigKey } from './config'; 3 | 4 | export interface KinveyConfig { 5 | appKey: string; 6 | appSecret: string; 7 | masterSecret?: string; 8 | appVersion?: string; 9 | instanceId?: string; 10 | defaultTimeout?: number; 11 | encryptionKey?: string; 12 | apiVersion?: number; 13 | } 14 | 15 | export function getAppKey() { 16 | const config = getConfig(ConfigKey.KinveyConfig); 17 | return config.appKey; 18 | } 19 | 20 | export function getAppSecret() { 21 | const config = getConfig(ConfigKey.KinveyConfig); 22 | return config.appSecret; 23 | } 24 | 25 | export function getMasterSecret() { 26 | const config = getConfig(ConfigKey.KinveyConfig); 27 | return config.masterSecret; 28 | } 29 | 30 | export function getInstanceId() { 31 | const config = getConfig(ConfigKey.KinveyConfig); 32 | return config.instanceId; 33 | } 34 | 35 | export function getBaasProtocol() { 36 | return 'https:'; 37 | } 38 | 39 | export function getBaasHost() { 40 | const instanceId = getInstanceId(); 41 | 42 | if (instanceId) { 43 | return `${instanceId}-baas.kinvey.com`; 44 | } 45 | 46 | return 'baas.kinvey.com'; 47 | } 48 | 49 | export function getAuthProtocol() { 50 | return 'https:'; 51 | } 52 | 53 | export function getAuthHost() { 54 | const instanceId = getInstanceId(); 55 | 56 | if (instanceId) { 57 | return `${instanceId}-auth.kinvey.com`; 58 | } 59 | 60 | return 'auth.kinvey.com'; 61 | } 62 | 63 | export function getDefaultTimeout() { 64 | const config = getConfig(ConfigKey.KinveyConfig); 65 | if (isNumber(config.defaultTimeout)) { 66 | return config.defaultTimeout; 67 | } 68 | return 60000; // 1 minute 69 | } 70 | 71 | export function getEncryptionKey() { 72 | const config = getConfig(ConfigKey.KinveyConfig); 73 | return config.encryptionKey; 74 | } 75 | 76 | export function getApiVersion(): number { 77 | const config = getConfig(ConfigKey.KinveyConfig); 78 | if (isNumber(config.apiVersion) && config.apiVersion >= 3) { 79 | return config.apiVersion; 80 | } 81 | return 6; 82 | } 83 | -------------------------------------------------------------------------------- /packages/js-sdk/src/log.ts: -------------------------------------------------------------------------------- 1 | import * as log from 'loglevel'; 2 | import * as prefix from 'loglevel-plugin-prefix'; 3 | 4 | // Set the default log level to ERROR. This will not overwrite the log level 5 | // if it has already been set. 6 | log.setDefaultLevel(log.levels.ERROR); 7 | 8 | // Register log with the prefix plugin 9 | prefix.reg(log); 10 | 11 | // Create a custom log prefix format 12 | const logPrefix = { 13 | template: '[%t] %l (%n):', 14 | timestampFormatter(date: Date) { 15 | return date.toISOString(); 16 | } 17 | }; 18 | prefix.apply(log, logPrefix); 19 | 20 | // Overrride the getLogger function to apply the custom log prefix format 21 | // const { getLogger } = log; 22 | // log.getLogger = function getLoggerOverride(name: string) { 23 | // const logger = getLogger(name); 24 | // prefix.apply(logger, logPrefix); 25 | // return logger; 26 | // }; 27 | 28 | // Export 29 | export { log as logger }; 30 | -------------------------------------------------------------------------------- /packages/js-sdk/src/mfa/index.ts: -------------------------------------------------------------------------------- 1 | import { getActiveUser } from '../user/getActiveUser'; 2 | import { 3 | createMFAAuthenticator, 4 | CreateMFAAuthenticatorResult, 5 | MFAAuthenticator, 6 | NewMFAAuthenticator, 7 | VerifyContext, 8 | } from '../user/createMFAAuthenticator'; 9 | import { KinveyError } from '../errors/kinvey'; 10 | import { getMFASession } from '../http'; 11 | 12 | async function callOnActiveUser(funcName, ...args): Promise { 13 | const activeUser = await getActiveUser(); 14 | if (!activeUser) { 15 | throw new KinveyError('An active user does not exist. Please login one first.'); 16 | } 17 | 18 | return activeUser[funcName](...args); 19 | } 20 | 21 | const Authenticators = { 22 | create: async function create( 23 | newAuthenticator: NewMFAAuthenticator, 24 | verify: (authenticator: MFAAuthenticator, context: VerifyContext) => Promise 25 | ): Promise { 26 | const activeUser = await getActiveUser(); 27 | if (activeUser) { 28 | return createMFAAuthenticator(activeUser.data._id, newAuthenticator, verify); 29 | } 30 | 31 | const mfaUser = await getMFASession(); 32 | if (!mfaUser) { 33 | throw new KinveyError('An active user, nor an MFA user exists. Please login one first.'); 34 | } 35 | 36 | return createMFAAuthenticator(mfaUser.userId, newAuthenticator, verify); 37 | }, 38 | list: function list(): Promise { 39 | return callOnActiveUser('listAuthenticators'); 40 | }, 41 | remove: function remove(id: string): Promise { 42 | return callOnActiveUser('removeAuthenticator', id); 43 | }, 44 | }; 45 | 46 | function listRecoveryCodes(): Promise { 47 | return callOnActiveUser('listRecoveryCodes'); 48 | } 49 | 50 | function regenerateRecoveryCodes(): Promise { 51 | return callOnActiveUser('regenerateRecoveryCodes'); 52 | } 53 | 54 | async function isEnabled(): Promise { 55 | return callOnActiveUser('isMFAEnabled'); 56 | } 57 | 58 | async function disable(): Promise { 59 | return callOnActiveUser('disableMFA'); 60 | } 61 | 62 | export { 63 | Authenticators, 64 | listRecoveryCodes, 65 | regenerateRecoveryCodes, 66 | isEnabled, 67 | disable, 68 | CreateMFAAuthenticatorResult, 69 | MFAAuthenticator, 70 | NewMFAAuthenticator 71 | }; 72 | -------------------------------------------------------------------------------- /packages/js-sdk/src/observable.ts: -------------------------------------------------------------------------------- 1 | import { Observable } from 'rxjs'; 2 | 3 | export class KinveyObservable extends Observable { 4 | toPromise() { 5 | return new Promise((resolve, reject) => { 6 | let value: any; 7 | this.subscribe((v) => { 8 | value = v; 9 | }, reject, () => { 10 | resolve(value); 11 | }); 12 | }); 13 | } 14 | } 15 | 16 | -------------------------------------------------------------------------------- /packages/js-sdk/src/ping.ts: -------------------------------------------------------------------------------- 1 | import { formatKinveyBaasUrl, HttpRequestMethod, KinveyHttpRequest, KinveyBaasNamespace, KinveyHttpAuth } from './http'; 2 | 3 | export interface PingOptions { 4 | timeout?: number; 5 | } 6 | 7 | export interface PingResponse { 8 | version: string; 9 | kinvey: string; 10 | appName: string; 11 | environmentName: string; 12 | } 13 | 14 | export async function ping(options: PingOptions = {}): Promise { 15 | const request = new KinveyHttpRequest({ 16 | method: HttpRequestMethod.GET, 17 | auth: KinveyHttpAuth.All, 18 | url: formatKinveyBaasUrl(KinveyBaasNamespace.AppData), 19 | timeout: options.timeout 20 | }); 21 | const response = await request.execute(); 22 | return response.data; 23 | } 24 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/exists.ts: -------------------------------------------------------------------------------- 1 | import { isString } from 'lodash-es'; 2 | import { KinveyError } from '../errors/kinvey'; 3 | import { formatKinveyBaasUrl, HttpRequestMethod, KinveyHttpRequest, KinveyBaasNamespace, KinveyHttpAuth } from '../http'; 4 | 5 | export interface ExistsOptions { 6 | timeout?: number; 7 | } 8 | 9 | export async function exists(username: string, options: ExistsOptions = {}) { 10 | if (!username) { 11 | throw new KinveyError('A username was not provided.'); 12 | } 13 | 14 | if (!isString(username)) { 15 | throw new KinveyError('The provided username is not a string.'); 16 | } 17 | 18 | const request = new KinveyHttpRequest({ 19 | method: HttpRequestMethod.POST, 20 | auth: KinveyHttpAuth.App, 21 | url: formatKinveyBaasUrl(KinveyBaasNamespace.Rpc, '/check-username-exists'), 22 | body: { username }, 23 | timeout: options.timeout 24 | }); 25 | const response = await request.execute(); 26 | return response.data.usernameExists === true; 27 | } 28 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/forgotUsername.ts: -------------------------------------------------------------------------------- 1 | import { isString } from 'lodash-es'; 2 | import { KinveyError } from '../errors/kinvey'; 3 | import { formatKinveyBaasUrl, HttpRequestMethod, KinveyHttpRequest, KinveyBaasNamespace, KinveyHttpAuth } from '../http'; 4 | 5 | export interface ForgotUsernameOptions { 6 | timeout?: number; 7 | } 8 | 9 | export async function forgotUsername(email: string, options: ForgotUsernameOptions = {}) { 10 | if (!email) { 11 | throw new KinveyError('An email was not provided.'); 12 | } 13 | 14 | if (!isString(email)) { 15 | throw new KinveyError('The provided email is not a string.'); 16 | } 17 | 18 | const request = new KinveyHttpRequest({ 19 | method: HttpRequestMethod.POST, 20 | auth: KinveyHttpAuth.App, 21 | url: formatKinveyBaasUrl(KinveyBaasNamespace.Rpc, '/user-forgot-username'), 22 | body: { email }, 23 | timeout: options.timeout 24 | }); 25 | const response = await request.execute(); 26 | return response.data; 27 | } 28 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/getActiveUser.ts: -------------------------------------------------------------------------------- 1 | import { getSession } from '../http'; 2 | import { User } from './user'; 3 | 4 | export async function getActiveUser() { 5 | const session = await getSession(); 6 | 7 | if (session) { 8 | return new User(session); 9 | } 10 | 11 | return null; 12 | } 13 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/invalidateTokens.ts: -------------------------------------------------------------------------------- 1 | import { getActiveUser } from './getActiveUser'; 2 | 3 | export async function invalidateTokens() { 4 | const activeUser = await getActiveUser(); 5 | 6 | if (!activeUser) { 7 | return null; 8 | } 9 | 10 | return activeUser.invalidateTokens(); 11 | } 12 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/loginWithMIC.ts: -------------------------------------------------------------------------------- 1 | import { loginWithRedirectUri } from './loginWithRedirectUri'; 2 | 3 | export enum AuthorizationGrant { 4 | AuthorizationCodeLoginPage 5 | } 6 | 7 | export async function loginWithMIC(redirectUri: string, authorizationGrant?: AuthorizationGrant, options?: any) { 8 | return loginWithRedirectUri(redirectUri, options); 9 | } 10 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/loginWithMICUsingResourceOwnerCredentials.ts: -------------------------------------------------------------------------------- 1 | import { isString } from 'lodash-es'; 2 | import { ActiveUserError } from '../errors/activeUser'; 3 | import { NotFoundError } from '../errors/notFound'; 4 | import { KinveyError } from '../errors/kinvey'; 5 | import { getAppKey } from '../kinvey'; 6 | import { login } from './login'; 7 | import { getTokenWithUsernamePassword, GetTokenWithUsernamePasswordOptions } from './mic'; 8 | import { signup } from './signup'; 9 | import { getActiveUser } from './getActiveUser'; 10 | import { loginWithSocialIdentity } from "./loginWithSocialIdentity"; 11 | 12 | export interface MICOptions extends GetTokenWithUsernamePasswordOptions { 13 | micId?: string; 14 | version?: string | number; 15 | } 16 | 17 | export async function loginWithMICUsingResourceOwnerCredentials(username: string, password: string, options: MICOptions = {}) { 18 | const activeUser = await getActiveUser(); 19 | const { micId } = options; 20 | let clientId = getAppKey(); 21 | 22 | if (activeUser) { 23 | throw new ActiveUserError('An active user already exists. Please logout the active user before you login with Mobile Identity Connect.'); 24 | } 25 | if (!isString(username) || !isString(password)) { 26 | throw new KinveyError('A username and password are required and must be a string.'); 27 | } 28 | 29 | if (isString(micId)) { 30 | clientId = `${clientId}.${micId}`; 31 | } 32 | 33 | const token = await getTokenWithUsernamePassword(username, password, clientId, options); 34 | const socialIdentity = { [token.identity]: token }; 35 | const credentials = { _socialIdentity: socialIdentity }; 36 | 37 | try { 38 | return await loginWithSocialIdentity(socialIdentity); 39 | } catch (error) { 40 | if (error instanceof NotFoundError) { 41 | return await signup(credentials); 42 | } 43 | 44 | throw error; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/loginWithRecoveryCode.ts: -------------------------------------------------------------------------------- 1 | import { trim } from 'lodash-es'; 2 | import { KinveyError } from '../errors/kinvey'; 3 | import { setSession } from '../http'; 4 | import { User } from './user'; 5 | import { LoginOptions, validateNoActiveUser, executeLoginRequest, validateCredentials } from './login'; 6 | 7 | export async function loginWithRecoveryCode( 8 | username: string, 9 | password: string, 10 | recoveryCode: string, 11 | options: LoginOptions = {} 12 | ): Promise { 13 | await validateNoActiveUser(); 14 | 15 | const credentials = validateCredentials(username, password); 16 | const trimmedCode = trim(recoveryCode); 17 | if (trimmedCode === '') { 18 | throw new KinveyError('Recovery code is missing.'); 19 | } 20 | 21 | credentials.recoveryCode = trimmedCode; 22 | const loginResult = await executeLoginRequest(credentials, options.timeout); 23 | await setSession(loginResult.user); 24 | return new User(loginResult.user); 25 | } 26 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/loginWithRedirectUri.ts: -------------------------------------------------------------------------------- 1 | import { isString } from 'lodash-es'; 2 | import { ActiveUserError } from '../errors/activeUser'; 3 | import { NotFoundError } from '../errors/notFound'; 4 | import { KinveyError } from '../errors/kinvey'; 5 | import { getAppKey } from '../kinvey'; 6 | import { loginWithPopup, getTokenWithCode } from './mic'; 7 | import { signup } from './signup'; 8 | import { getActiveUser } from './getActiveUser'; 9 | import { loginWithSocialIdentity } from './loginWithSocialIdentity'; 10 | 11 | export interface MICOptions { 12 | micId?: string; 13 | version?: string | number; 14 | timeout?: number; 15 | } 16 | 17 | export async function loginWithRedirectUri(redirectUri: string, options: MICOptions = {}) { 18 | const activeUser = await getActiveUser(); 19 | const { micId, version } = options; 20 | let clientId = getAppKey(); 21 | 22 | if (activeUser) { 23 | throw new ActiveUserError('An active user already exists. Please logout the active user before you login with Mobile Identity Connect.'); 24 | } 25 | 26 | if (!isString(redirectUri)) { 27 | throw new KinveyError('A redirectUri is required and must be a string.'); 28 | } 29 | 30 | if (isString(micId)) { 31 | clientId = `${clientId}.${micId}`; 32 | } 33 | 34 | const code = await loginWithPopup(clientId, redirectUri, version); 35 | const token = await getTokenWithCode(code, clientId, redirectUri, options); 36 | const socialIdentity = { [token.identity]: token }; 37 | const credentials = { _socialIdentity: socialIdentity }; 38 | 39 | try { 40 | return await loginWithSocialIdentity(socialIdentity); 41 | } catch (error) { 42 | if (error instanceof NotFoundError) { 43 | return await signup(credentials); 44 | } 45 | 46 | throw error; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/loginWithSocialIdentity.ts: -------------------------------------------------------------------------------- 1 | import { User } from './user'; 2 | import { mergeSocialIdentity } from './utils'; 3 | import { setSession } from '../http'; 4 | import { executeLoginRequest } from './login'; 5 | 6 | export async function loginWithSocialIdentity(socialIdentity: any): Promise { 7 | const { user } = await executeLoginRequest({ _socialIdentity: socialIdentity }); 8 | user._socialIdentity = mergeSocialIdentity(socialIdentity, user._socialIdentity); 9 | await setSession(user); 10 | return new User(user); 11 | } 12 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/logout.ts: -------------------------------------------------------------------------------- 1 | import { getActiveUser } from './getActiveUser'; 2 | 3 | export async function logout(options?: any) { 4 | const activeUser = await getActiveUser(); 5 | 6 | if (activeUser) { 7 | return activeUser.logout(options); 8 | } 9 | 10 | return null; 11 | } 12 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/lookup.ts: -------------------------------------------------------------------------------- 1 | import { Observable } from 'rxjs'; 2 | import { Query } from '../query'; 3 | import { KinveyError } from '../errors/kinvey'; 4 | import { formatKinveyBaasUrl, HttpRequestMethod, KinveyHttpRequest, KinveyHttpAuth, KinveyBaasNamespace } from '../http'; 5 | 6 | export interface LookupOptions { 7 | timeout?: number; 8 | } 9 | 10 | export function lookup(query?: Query, options: LookupOptions = {}) { 11 | const stream = Observable.create(async (observer: any) => { 12 | try { 13 | if (query && !(query instanceof Query)) { 14 | throw new KinveyError('Invalid query. It must be an instance of the Query class.'); 15 | } 16 | 17 | const request = new KinveyHttpRequest({ 18 | method: HttpRequestMethod.POST, 19 | auth: KinveyHttpAuth.SessionOrMaster, 20 | url: formatKinveyBaasUrl(KinveyBaasNamespace.User, '/_lookup'), 21 | body: query ? query.filter : undefined, 22 | timeout: options.timeout 23 | }); 24 | const response = await request.execute(); 25 | observer.next(response.data); 26 | observer.complete(); 27 | } catch (error) { 28 | observer.error(error); 29 | } 30 | }); 31 | return stream; 32 | } 33 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/me.ts: -------------------------------------------------------------------------------- 1 | import { getActiveUser } from './getActiveUser'; 2 | 3 | export async function me(options?: { timeout?: number }) { 4 | const activeUser = await getActiveUser(); 5 | 6 | if (activeUser) { 7 | return activeUser.me(options); 8 | } 9 | 10 | return null; 11 | } 12 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/mic/getTokenWithCode.ts: -------------------------------------------------------------------------------- 1 | import { Base64 } from 'js-base64'; 2 | import { formatKinveyAuthUrl, HttpRequestMethod, KinveyHttpRequest, KinveyHttpAuth, KinveyHttpHeaders } from '../../http'; 3 | import { getAuthProtocol, getAuthHost, getAppSecret } from '../../kinvey'; 4 | import { Identity, getVersion } from './utils'; 5 | 6 | export interface GetTokenWithCodeOptions { 7 | timeout?: number; 8 | version?: string | number; 9 | } 10 | 11 | // export interface Token { 12 | // identity: string; 13 | // client_id: string; 14 | // redirect_uri: string; 15 | // protocol: string; 16 | // host: string; 17 | // } 18 | 19 | export async function getTokenWithCode(code: string, clientId: string, redirectUri: string, options: GetTokenWithCodeOptions = {}) { 20 | const request = new KinveyHttpRequest({ 21 | method: HttpRequestMethod.POST, 22 | headers: new KinveyHttpHeaders({ 23 | 'Content-Type': () => 'application/x-www-form-urlencoded', 24 | Authorization: () => { 25 | const credentials = Base64.encode(`${clientId}:${getAppSecret()}`); 26 | return `Basic ${credentials}`; 27 | } 28 | }), 29 | url: formatKinveyAuthUrl(`/${getVersion(options.version)}/oauth/token`), 30 | body: { 31 | grant_type: 'authorization_code', 32 | client_id: clientId, 33 | redirect_uri: redirectUri, 34 | code 35 | }, 36 | timeout: options.timeout 37 | }); 38 | const response = await request.execute(); 39 | const token = response.data; 40 | return Object.assign({}, { 41 | identity: Identity, 42 | client_id: clientId, 43 | redirect_uri: redirectUri, 44 | protocol: getAuthProtocol(), 45 | host: getAuthHost() 46 | }, token); 47 | } 48 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/mic/getTokenWithUsernamePassword.ts: -------------------------------------------------------------------------------- 1 | import { Base64 } from 'js-base64'; 2 | import { formatKinveyAuthUrl, HttpRequestMethod, KinveyHttpRequest, KinveyHttpAuth, KinveyHttpHeaders } from '../../http'; 3 | import { getAuthProtocol, getAuthHost, getAppSecret } from '../../kinvey'; 4 | import { Identity, getVersion } from './utils'; 5 | 6 | export interface GetTokenWithUsernamePasswordOptions { 7 | timeout?: number; 8 | version?: string | number; 9 | } 10 | 11 | // export interface Token { 12 | // identity: string; 13 | // client_id: string; 14 | // redirect_uri: string; 15 | // protocol: string; 16 | // host: string; 17 | // } 18 | 19 | export async function getTokenWithUsernamePassword(username: string, password: string, clientId: string, options: GetTokenWithUsernamePasswordOptions = {}) { 20 | const request = new KinveyHttpRequest({ 21 | method: HttpRequestMethod.POST, 22 | headers: new KinveyHttpHeaders({ 23 | 'Content-Type': () => 'application/x-www-form-urlencoded', 24 | Authorization: () => { 25 | const credentials = Base64.encode(`${clientId}:${getAppSecret()}`); 26 | return `Basic ${credentials}`; 27 | } 28 | }), 29 | url: formatKinveyAuthUrl(`/${getVersion(options.version)}/oauth/token`), 30 | body: { 31 | grant_type: 'password', 32 | client_id: clientId, 33 | username, 34 | password 35 | }, 36 | timeout: options.timeout 37 | }); 38 | const response = await request.execute(); 39 | const token = response.data; 40 | return Object.assign({}, { 41 | identity: Identity, 42 | client_id: clientId, 43 | protocol: getAuthProtocol(), 44 | host: getAuthHost() 45 | }, token); 46 | } 47 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/mic/index.ts: -------------------------------------------------------------------------------- 1 | export * from './getTokenWithCode'; 2 | export * from './getTokenWithUsernamePassword'; 3 | export * from './loginWithPopup'; 4 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/mic/loginWithPopup.ts: -------------------------------------------------------------------------------- 1 | import { parse } from 'url'; 2 | import { formatKinveyAuthUrl } from '../../http'; 3 | import { KinveyError } from '../../errors/kinvey'; 4 | import { getVersion } from './utils'; 5 | import { open } from './popup'; 6 | 7 | export function loginWithPopup(clientId: string, redirectUri: string, version?: string | number): Promise { 8 | return new Promise(async (resolve, reject) => { 9 | const url = formatKinveyAuthUrl(`/${getVersion(version)}/oauth/auth`, { 10 | client_id: clientId, 11 | redirect_uri: redirectUri, 12 | response_type: 'code', 13 | scope: 'openid' 14 | }); 15 | const popup = await open(url); 16 | let redirected = false; 17 | 18 | popup.onLoaded(async (event) => { 19 | try { 20 | if (event.url && event.url.indexOf(redirectUri) === 0 && redirected === false) { 21 | const parsedUrl = parse(event.url, true); 22 | const { code, error, error_description } = parsedUrl.query; 23 | 24 | redirected = true; 25 | popup.removeAllListeners(); 26 | await popup.close(); 27 | 28 | if (code) { 29 | resolve(code as string); 30 | } else if (error) { 31 | reject(new KinveyError(error as string)); 32 | } else { 33 | reject(new KinveyError('No code or error was provided.')); 34 | } 35 | } 36 | } catch (error) { 37 | // Just catch the error 38 | } 39 | }); 40 | 41 | popup.onClosed(() => { 42 | if (!redirected) { 43 | popup.removeAllListeners(); 44 | reject(new KinveyError('Login has been cancelled.')); 45 | } 46 | }); 47 | }); 48 | } 49 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/mic/popup.ts: -------------------------------------------------------------------------------- 1 | import { getConfig, ConfigKey } from '../../config'; 2 | import { EventEmitter } from 'events'; 3 | 4 | export interface PopupEvent { 5 | url?: string; 6 | } 7 | 8 | export interface PopupWindow extends EventEmitter { 9 | isClosed(): boolean; 10 | onLoaded(listener: (event: PopupEvent) => void): this; 11 | onClosed(listener: () => void): this; 12 | onError(listener: () => void): this; 13 | close(): Promise; 14 | } 15 | 16 | export interface Popup { 17 | open(url: string): Promise; 18 | } 19 | 20 | export function open(url: string) { 21 | const popup = getConfig(ConfigKey.Popup); 22 | return popup.open(url); 23 | } 24 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/mic/utils.ts: -------------------------------------------------------------------------------- 1 | export const Identity = 'kinveyAuth'; 2 | 3 | export function getVersion(version: string | number = 3) { 4 | return String(version).indexOf('v') === 0 ? version : `v${version}`; 5 | } 6 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/registerForLiveService.ts: -------------------------------------------------------------------------------- 1 | import { getActiveUser } from './getActiveUser'; 2 | 3 | export async function registerForLiveService(options?: { timeout?: number }) { 4 | const activeUser = await getActiveUser(); 5 | 6 | if (activeUser) { 7 | return activeUser.registerForLiveService(options); 8 | } 9 | 10 | return null; 11 | } 12 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/remove.ts: -------------------------------------------------------------------------------- 1 | import { isString } from 'lodash-es'; 2 | import { KinveyError } from '../errors/kinvey'; 3 | import { formatKinveyBaasUrl, HttpRequestMethod, KinveyHttpRequest, KinveyBaasNamespace, KinveyHttpAuth } from '../http'; 4 | import { getActiveUser } from './getActiveUser'; 5 | 6 | export async function remove(id: string, options: { timeout?: number, hard?: boolean } = {}) { 7 | const { hard } = options; 8 | const activeUser = await getActiveUser(); 9 | 10 | if (!id) { 11 | throw new KinveyError('An id was not provided.'); 12 | } 13 | 14 | if (!isString(id)) { 15 | throw new KinveyError('The id provided is not a string.'); 16 | } 17 | 18 | // Remove the user from the backend 19 | const url = formatKinveyBaasUrl(KinveyBaasNamespace.User, `/${id}`, { hard: hard ? hard === true : undefined }); 20 | const request = new KinveyHttpRequest({ 21 | method: HttpRequestMethod.DELETE, 22 | auth: KinveyHttpAuth.Master, 23 | url, 24 | timeout: options.timeout 25 | }); 26 | const response = await request.execute(); 27 | 28 | // Logout the active user if it is the user we removed 29 | if (activeUser && activeUser._id === id) { 30 | await activeUser.logout(); 31 | } 32 | 33 | // Return the response 34 | return response.data; 35 | } 36 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/resetPassword.ts: -------------------------------------------------------------------------------- 1 | import { isString } from 'lodash-es'; 2 | import { KinveyError } from '../errors/kinvey'; 3 | import { formatKinveyBaasUrl, HttpRequestMethod, KinveyHttpRequest, KinveyBaasNamespace, KinveyHttpAuth } from '../http'; 4 | 5 | export async function resetPassword(username: string, options: { timeout?: number } = {}) { 6 | if (!username) { 7 | throw new KinveyError('A username was not provided.'); 8 | } 9 | 10 | if (!isString(username)) { 11 | throw new KinveyError('The provided username is not a string.'); 12 | } 13 | 14 | const request = new KinveyHttpRequest({ 15 | method: HttpRequestMethod.POST, 16 | auth: KinveyHttpAuth.App, 17 | url: formatKinveyBaasUrl(KinveyBaasNamespace.Rpc, `/${username}/user-password-reset-initiate`), 18 | timeout: options.timeout 19 | }); 20 | const response = await request.execute(); 21 | return response.data; 22 | } 23 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/restore.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from '../errors/kinvey'; 2 | 3 | export async function restore() { 4 | throw new KinveyError('This function requires a master secret to be provided for your application. We strongly advise not to do this.'); 5 | } 6 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/signup.ts: -------------------------------------------------------------------------------- 1 | import { isEmpty, isPlainObject } from 'lodash-es'; 2 | import { KinveyError } from '../errors/kinvey'; 3 | import { formatKinveyBaasUrl, HttpRequestMethod, KinveyHttpRequest, KinveyBaasNamespace, KinveyHttpAuth } from '../http'; 4 | import { User } from './user'; 5 | 6 | export async function signup(data?: object | User, options: { timeout?: number } = {}) { 7 | if (data && !isPlainObject(data)) { 8 | throw new KinveyError('The provided data must be an object.'); 9 | } 10 | 11 | const request = new KinveyHttpRequest({ 12 | method: HttpRequestMethod.POST, 13 | auth: KinveyHttpAuth.App, 14 | url: formatKinveyBaasUrl(KinveyBaasNamespace.User), 15 | timeout: options.timeout 16 | }); 17 | 18 | if (data instanceof User) { 19 | request.body = isEmpty(data.data) ? null : data.data; 20 | } else { 21 | request.body = isEmpty(data) ? null : data; 22 | } 23 | 24 | const response = await request.execute(); 25 | const session = response.data; 26 | 27 | return new User(session); 28 | } 29 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/signupWithIdentity.ts: -------------------------------------------------------------------------------- 1 | import { KinveyError } from '../errors/kinvey'; 2 | 3 | export async function signUpWithIdentity() { 4 | throw new KinveyError('This function has been deprecated. You should use MIC to login instead.'); 5 | } 6 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/unregisterFromLiveService.ts: -------------------------------------------------------------------------------- 1 | import { getActiveUser } from './getActiveUser'; 2 | 3 | export async function unregisterFromLiveService(options?: { timeout?: number }) { 4 | const activeUser = await getActiveUser(); 5 | 6 | if (activeUser) { 7 | return activeUser.unregisterFromLiveService(options); 8 | } 9 | 10 | return null; 11 | } 12 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/update.ts: -------------------------------------------------------------------------------- 1 | import { getActiveUser } from './getActiveUser'; 2 | 3 | export async function update(data: any, options?: { timeout?: number }) { 4 | const activeUser = await getActiveUser(); 5 | 6 | if (activeUser) { 7 | return activeUser.update(data, options); 8 | } 9 | 10 | return null; 11 | } 12 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/utils.ts: -------------------------------------------------------------------------------- 1 | // eslint-disable-next-line import/prefer-default-export 2 | export function mergeSocialIdentity(origSocialIdentity: any = {}, newSocialIdentity: any = {}) { 3 | const mergedSocialIdentity = JSON.parse(JSON.stringify(origSocialIdentity)); 4 | return Object 5 | .keys(newSocialIdentity) 6 | .reduce((socialIdentity, identity) => { 7 | socialIdentity[identity] = Object.assign({}, origSocialIdentity[identity], newSocialIdentity[identity]); 8 | return socialIdentity; 9 | }, mergedSocialIdentity); 10 | } 11 | -------------------------------------------------------------------------------- /packages/js-sdk/src/user/verifyEmail.ts: -------------------------------------------------------------------------------- 1 | import { isString } from 'lodash-es'; 2 | import { KinveyError } from '../errors/kinvey'; 3 | import { formatKinveyBaasUrl, HttpRequestMethod, KinveyHttpRequest, KinveyBaasNamespace, KinveyHttpAuth } from '../http'; 4 | 5 | export interface VerifyEmailOptions { 6 | timeout?: number; 7 | } 8 | 9 | export async function verifyEmail(username: string, options: VerifyEmailOptions = {}) { 10 | if (!username) { 11 | throw new KinveyError('A username was not provided.'); 12 | } 13 | 14 | if (!isString(username)) { 15 | throw new KinveyError('The provided username is not a string.'); 16 | } 17 | 18 | const request = new KinveyHttpRequest({ 19 | method: HttpRequestMethod.POST, 20 | auth: KinveyHttpAuth.App, 21 | url: formatKinveyBaasUrl(KinveyBaasNamespace.Rpc, `/${username}/user-email-verification-initiate`), 22 | timeout: options.timeout 23 | }); 24 | const response = await request.execute(); 25 | return response.data; 26 | } 27 | -------------------------------------------------------------------------------- /packages/js-sdk/test/http.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { NetworkError } from '../src/errors/network'; 3 | 4 | export async function send(request: any) { 5 | const { url, method, headers, body, timeout } = request; 6 | let response; 7 | 8 | try { 9 | response = await axios({ 10 | headers, 11 | method, 12 | url, 13 | data: body, 14 | timeout 15 | }); 16 | } catch (error) { 17 | if (!error.response) { 18 | throw new NetworkError(); 19 | } 20 | response = error.response; 21 | } 22 | 23 | return { 24 | statusCode: response.status, 25 | headers: response.headers, 26 | data: response.data 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /packages/js-sdk/test/kinvey.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { getBaasProtocol, getAuthProtocol } from '../src/kinvey'; 3 | 4 | describe('Kinvey SDK Config', function () { 5 | it('should have baas protocol set to https: by default', function() { 6 | expect(getBaasProtocol()).to.equal('https:'); 7 | }); 8 | 9 | it('should have auth protocol set to https: by default', function () { 10 | expect(getAuthProtocol()).to.equal('https:'); 11 | }); 12 | }); 13 | -------------------------------------------------------------------------------- /packages/js-sdk/test/memory.ts: -------------------------------------------------------------------------------- 1 | const store = new Map>(); 2 | 3 | function getTable(dbName: string, tableName: string) { 4 | return store.get(`${dbName}.${tableName}`) || new Map(); 5 | } 6 | 7 | function setTable(dbName: string, tableName: string, table: Map) { 8 | return store.set(`${dbName}.${tableName}`, table); 9 | } 10 | 11 | export async function find(dbName: string, tableName: string) { 12 | const table = getTable(dbName, tableName); 13 | return Array.from(table.values()); 14 | } 15 | 16 | export async function count(dbName: string, tableName: string) { 17 | const docs = await find(dbName, tableName); 18 | return docs.length; 19 | } 20 | 21 | export async function findById(dbName: string, tableName: string, id: string) { 22 | const docs = await find(dbName, tableName); 23 | return docs.find((doc: any) => doc._id === id); 24 | } 25 | 26 | export async function save(dbName: string, tableName: string, docs: any = []) { 27 | const table = getTable(dbName, tableName); 28 | docs.forEach((doc: { _id: string; }) => { 29 | table.set(doc._id, doc); 30 | }); 31 | setTable(dbName, tableName, table); 32 | return docs; 33 | } 34 | 35 | export async function removeById(dbName: string, tableName: string, id: string) { 36 | const table = getTable(dbName, tableName); 37 | if (table.delete(id)) { 38 | setTable(dbName, tableName, table); 39 | return 1; 40 | } 41 | return 0; 42 | } 43 | 44 | export async function clear(dbName: string, tableName: string) { 45 | store.delete(`${dbName}.${tableName}`); 46 | return true; 47 | } 48 | 49 | export async function clearDatabase() { 50 | store.clear(); 51 | return true; 52 | } 53 | -------------------------------------------------------------------------------- /packages/js-sdk/test/sessionStore.ts: -------------------------------------------------------------------------------- 1 | const store = new Map(); 2 | 3 | export async function get(key: string) { 4 | return store.get(key); 5 | } 6 | 7 | export async function set(key: string, session: string) { 8 | store.set(key, session); 9 | return true; 10 | } 11 | 12 | export async function remove(key: string): Promise { 13 | return store.delete(key); 14 | } 15 | -------------------------------------------------------------------------------- /packages/js-sdk/test/user/signup.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { KinveyError } from '../../src/errors'; 3 | import { signup } from '../../src/user/signup'; 4 | import {init} from "../../src"; 5 | import * as httpAdapter from "../http"; 6 | import * as sessionStore from "../sessionStore"; 7 | import * as memoryStorageAdapter from "../memory"; 8 | 9 | const APP_KEY = 'appKey'; 10 | const APP_SECRET = 'appSecret'; 11 | 12 | describe('User Signup', function () { 13 | beforeAll(function () { 14 | return init({ 15 | kinveyConfig: { 16 | appKey: APP_KEY, 17 | appSecret: APP_SECRET 18 | }, 19 | httpAdapter, 20 | sessionStore: sessionStore, 21 | popup: null, 22 | storageAdapter: memoryStorageAdapter, 23 | pubnub: null 24 | }) 25 | }); 26 | 27 | it('should throw an error if a plain object is not provided', async function () { 28 | try { 29 | // @ts-ignore 30 | await signup('name', 'pass'); 31 | throw new Error('This test should fail.'); 32 | } catch (error) { 33 | expect(error).to.be.instanceof(KinveyError); 34 | expect(error.message).to.equal('The provided data must be an object.') 35 | } 36 | }); 37 | }); 38 | -------------------------------------------------------------------------------- /packages/js-sdk/test/user/user.spec.ts: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import { User } from '../../src/user'; 3 | 4 | describe('User', function () { 5 | describe('signup()', function() { 6 | it('should exist', function() { 7 | const user = new User(); 8 | expect(user.signup).to.exist; 9 | }); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /packages/js-sdk/tests/sample.spec.ts: -------------------------------------------------------------------------------- 1 | describe('Sample Test', () => { 2 | it('it should be true', () => { 3 | expect(true).toBeTruthy(); 4 | }); 5 | }); 6 | -------------------------------------------------------------------------------- /packages/js-sdk/tests/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "types": [ 4 | "jest" 5 | ] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/js-sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "esModuleInterop": true, 5 | "outDir": "lib", 6 | "sourceMap": true, 7 | "target": "es6", 8 | "moduleResolution": "node", 9 | "skipLibCheck": true 10 | }, 11 | "exclude": ["node_modules", "src/**/*.test.ts", "test", "tests"] 12 | } 13 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/.editorconfig: -------------------------------------------------------------------------------- 1 | #root = true 2 | 3 | [*] 4 | indent_style = space 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | max_line_length = 100 10 | indent_size = 2 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .idea 3 | .DS_Store 4 | *.log 5 | !src/references.d.ts 6 | node_modules 7 | lib 8 | dist 9 | *.tgz 10 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | We're really glad you're reading this, because we need volunteer developers to help this project come to fruition. 👏 2 | 3 | ## Instructions 4 | 5 | These steps will guide you through contributing to this project: 6 | 7 | - Fork the repo 8 | - Clone it and install dependencies 9 | 10 | git clone https://github.com/YOUR-USERNAME/typescript-library-starter 11 | npm install 12 | 13 | Keep in mind that after running `npm install` the git repo is reset. So a good way to cope with this is to have a copy of the folder to push the changes, and the other to try them. 14 | 15 | Make and commit your changes. Make sure the commands npm run build and npm run test:prod are working. 16 | 17 | Finally send a [GitHub Pull Request](https://github.com/alexjoverm/typescript-library-starter/compare?expand=1) with a clear list of what you've done (read more [about pull requests](https://help.github.com/articles/about-pull-requests/)). Make sure all of your commits are atomic (one feature per commit). 18 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/angular/index.d.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | export * from '../lib/angular'; 3 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/angular/index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../lib/angular'); 2 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/angular/push.d.ts: -------------------------------------------------------------------------------- 1 | // @ts-ignore 2 | export * from '../lib/angular/push'; 3 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/angular/push.js: -------------------------------------------------------------------------------- 1 | module.exports = require('../lib/angular/push'); 2 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/nativescript-hook-scripts/before-preview-sync.js: -------------------------------------------------------------------------------- 1 | module.exports = function ($logger, hookArgs) { 2 | const platform = hookArgs && ((hookArgs.config && hookArgs.config.platform) || (hookArgs.platform || '')).toLowerCase(); 3 | const projectIdentifier = platform && hookArgs.projectData && hookArgs.projectData.projectIdentifiers && hookArgs.projectData.projectIdentifiers[platform]; 4 | const previewScheme = projectIdentifier === 'com.kinvey.preview' ? 'kspreviewresume://' : 'nsplayresume://'; 5 | $logger.warn(`If you are using loginWithMIC() ensure that you have added ${previewScheme} as a Redirect URI to your Mobile Identity Connect configuration at https://console.kinvey.com in order for Mobile Identity Connect login to work in the Preview app.`); 6 | }; 7 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/nativescript-hook-scripts/postinstall.js: -------------------------------------------------------------------------------- 1 | try { 2 | var path = require('path'); 3 | require('nativescript-hook')(path.join(__dirname, '..')).postinstall(); 4 | } catch (error) { 5 | // Catch the error 6 | } 7 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/nativescript-hook-scripts/preuninstall.js: -------------------------------------------------------------------------------- 1 | try { 2 | var path = require('path'); 3 | require('nativescript-hook')(path.join(__dirname, '..')).preuninstall(); 4 | } catch (error) { 5 | // Catch the error 6 | } 7 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/platforms/android/AndroidManifest.default.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/platforms/android/AndroidManifest.mic.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/platforms/android/include.gradle: -------------------------------------------------------------------------------- 1 | repositories { 2 | mavenCentral() 3 | } 4 | 5 | dependencies { 6 | compile 'com.android.support:appcompat-v7:27.0.2' 7 | compile 'com.android.support:customtabs:27.0.2' 8 | } 9 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/platforms/ios/app.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | keychain-access-groups 6 | 7 | $(AppIdentifierPrefix)$(PRODUCT_BUNDLE_IDENTIFIER) 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/platforms/ios/info.default.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/platforms/ios/info.mic.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleURLTypes 6 | 7 | 8 | CFBundleTypeRole 9 | Editor 10 | CFBundleURLSchemes 11 | 12 | {redirectUriScheme} 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/push.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/nativescript/push'); 2 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/reference.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/scripts/postbuild.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs-extra'); 2 | const path = require('path'); 3 | 4 | const rootPath = path.join(__dirname, '..'); 5 | const libPath = path.join(rootPath, 'lib'); 6 | const tmpPath = path.join(rootPath, 'tmp'); 7 | 8 | // Copy /lib to /tmp 9 | fs.copySync(libPath, tmpPath); 10 | 11 | // Remove /lib 12 | fs.removeSync(libPath); 13 | 14 | // Copy /tmp/src to /lib 15 | fs.copySync(path.join(tmpPath, 'src'), libPath); 16 | 17 | // Remove /tmp 18 | fs.removeSync(tmpPath); 19 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/angular/datastore.service.ts: -------------------------------------------------------------------------------- 1 | import { Inject, Injectable } from '@angular/core'; 2 | import { init, DataStore, DataStoreType } from '../nativescript'; 3 | import { KinveyConfigToken } from './utils'; 4 | 5 | @Injectable({ 6 | providedIn: 'root' 7 | }) 8 | export class DataStoreService { 9 | constructor(@Inject(KinveyConfigToken) config: any) { 10 | init(config); 11 | } 12 | 13 | collection(collectionName: string, type?: DataStoreType, options?: any): any { 14 | return DataStore.collection(collectionName, type, options); 15 | } 16 | 17 | clearCache(): any { 18 | return DataStore.clearCache(); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/angular/endpoint.service.ts: -------------------------------------------------------------------------------- 1 | import { Inject, Injectable } from '@angular/core'; 2 | import { init, CustomEndpoint } from '../nativescript'; 3 | import { KinveyConfigToken } from './utils'; 4 | 5 | @Injectable({ 6 | providedIn: 'root' 7 | }) 8 | export class EndpointService { 9 | constructor(@Inject(KinveyConfigToken) config: any) { 10 | init(config); 11 | } 12 | 13 | endpoint(endpoint: string, args?: any, options?: any) { 14 | return CustomEndpoint.execute(endpoint, args, options); 15 | } 16 | 17 | execute(endpoint: string, args?: any, options?: any) { 18 | return this.endpoint(endpoint, args, options); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/angular/files.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Inject } from '@angular/core'; 2 | import { init, Files, Query } from '../nativescript'; 3 | import { KinveyConfigToken } from './utils'; 4 | 5 | @Injectable({ 6 | providedIn: 'root' 7 | }) 8 | export class FilesService { 9 | constructor(@Inject(KinveyConfigToken) config: any) { 10 | init(config); 11 | } 12 | 13 | create(file: any, metadata: any, options?: any) { 14 | return Files.create(file, metadata, options); 15 | } 16 | 17 | download(id?: string, options?: any) { 18 | return Files.download(id, options); 19 | } 20 | 21 | downloadByUrl(url: string, options?: any) { 22 | return Files.downloadByUrl(url, options); 23 | } 24 | 25 | find(query?: Query, options?: any) { 26 | return Files.find(query, options); 27 | } 28 | 29 | findById(id: string, options?: any) { 30 | return Files.findById(id, options); 31 | } 32 | 33 | remove() { 34 | return Files.remove(); 35 | } 36 | 37 | removeById(id: string, options?: any) { 38 | return Files.removeById(id, options); 39 | } 40 | 41 | stream(id: string, options?: any) { 42 | return Files.stream(id, options); 43 | } 44 | 45 | update(file: any, metadata: any, options?: any) { 46 | return Files.update(file, metadata, options); 47 | } 48 | 49 | upload(file: any, metadata: any, options?: any) { 50 | return Files.upload(file, metadata, options); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/angular/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | getAppVersion, 3 | setAppVersion, 4 | logger, 5 | Acl, 6 | Aggregation, 7 | StorageProvider, 8 | DataStoreType, 9 | Errors, 10 | Kmd, 11 | Query, 12 | AuthorizationGrant, 13 | MFA 14 | } from '../nativescript'; 15 | import { DataStoreService } from './datastore.service'; 16 | import { EndpointService } from './endpoint.service'; 17 | import { FilesService } from './files.service'; 18 | import { KinveyModule } from './kinvey.module'; 19 | import { PingService } from './ping.service'; 20 | import { UserService } from './user.service'; 21 | 22 | export { 23 | // Init 24 | KinveyModule, 25 | StorageProvider, 26 | 27 | // App Version 28 | getAppVersion, 29 | setAppVersion, 30 | 31 | // Logger 32 | logger, 33 | 34 | // Ping 35 | PingService, 36 | 37 | // Acl 38 | Acl, 39 | 40 | // Aggregation 41 | Aggregation, 42 | 43 | // Custom Endpoint 44 | EndpointService, 45 | 46 | // DataStore 47 | DataStoreService, 48 | DataStoreType, 49 | 50 | // Errors 51 | Errors, 52 | 53 | // Files 54 | FilesService, 55 | 56 | // Kmd 57 | Kmd, 58 | Kmd as Metadata, 59 | 60 | // Query 61 | Query, 62 | 63 | // User 64 | UserService, 65 | AuthorizationGrant, 66 | 67 | MFA 68 | }; 69 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/angular/kinvey.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule, ModuleWithProviders } from '@angular/core'; 2 | import { KinveyConfigToken } from './utils'; 3 | import { DataStoreService } from './datastore.service'; 4 | import { EndpointService } from './endpoint.service'; 5 | import { FilesService } from './files.service'; 6 | import { PingService } from './ping.service'; 7 | import { UserService } from './user.service'; 8 | 9 | @NgModule() 10 | export class KinveyModule { 11 | static init(config?: any): ModuleWithProviders { 12 | return { 13 | ngModule: KinveyModule, 14 | providers: [ 15 | DataStoreService, 16 | EndpointService, 17 | FilesService, 18 | PingService, 19 | UserService, 20 | { provide: KinveyConfigToken, useValue: config } 21 | ] 22 | }; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/angular/ping.service.ts: -------------------------------------------------------------------------------- 1 | import { Injectable, Inject } from '@angular/core'; 2 | import { init, ping } from '../nativescript'; 3 | import { KinveyConfigToken } from './utils'; 4 | 5 | @Injectable({ 6 | providedIn: 'root' 7 | }) 8 | export class PingService { 9 | constructor(@Inject(KinveyConfigToken) config: any) { 10 | init(config); 11 | } 12 | 13 | ping(): Promise { 14 | return ping(); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/angular/push.module.ts: -------------------------------------------------------------------------------- 1 | import { NgModule } from '@angular/core'; 2 | import { PushService } from './push.service'; 3 | 4 | @NgModule({ 5 | providers: [ 6 | PushService 7 | ] 8 | }) 9 | export class KinveyPushModule { } 10 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/angular/push.service.ts: -------------------------------------------------------------------------------- 1 | import { Inject, Injectable } from '@angular/core'; 2 | import { init } from '../nativescript/init'; 3 | import * as Push from '../nativescript/push'; 4 | import { KinveyConfigToken } from './utils'; 5 | 6 | @Injectable({ 7 | providedIn: 'root' 8 | }) 9 | export class PushService { 10 | constructor(@Inject(KinveyConfigToken) config: any) { 11 | init(config); 12 | } 13 | 14 | register(callback: (message: any) => void, options?: any) { 15 | return Push.register(callback, options); 16 | } 17 | 18 | unregister(options?: any) { 19 | return Push.unregister(options); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/angular/push.ts: -------------------------------------------------------------------------------- 1 | export * from './push.module'; 2 | export * from './push.service'; 3 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/angular/utils.ts: -------------------------------------------------------------------------------- 1 | import { InjectionToken } from '@angular/core'; 2 | 3 | export const KinveyConfigToken = new InjectionToken('kinvey.config'); 4 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/nativescript/files/index.ts: -------------------------------------------------------------------------------- 1 | import { create } from 'kinvey-js-sdk/lib/files/create'; 2 | import { download } from 'kinvey-js-sdk/lib/files/download'; 3 | import { downloadByUrl } from 'kinvey-js-sdk/lib/files/downloadByUrl'; 4 | import { find } from 'kinvey-js-sdk/lib/files/find'; 5 | import { findById } from 'kinvey-js-sdk/lib/files/findById'; 6 | import { remove } from 'kinvey-js-sdk/lib/files/remove'; 7 | import { removeById } from 'kinvey-js-sdk/lib/files/removeById'; 8 | import { stream } from 'kinvey-js-sdk/lib/files/stream'; 9 | import { update } from 'kinvey-js-sdk/lib/files/update'; 10 | import { upload } from './upload'; 11 | 12 | export { 13 | create, 14 | download, 15 | downloadByUrl, 16 | find, 17 | findById, 18 | remove, 19 | removeById, 20 | stream, 21 | update, 22 | upload 23 | }; 24 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/nativescript/files/upload.ts: -------------------------------------------------------------------------------- 1 | import isFunction from 'lodash/isFunction'; 2 | import * as bghttp from '@nativescript/background-http'; 3 | import { File } from '@nativescript/core'; 4 | import { transformMetadata, saveFileMetadata } from 'kinvey-js-sdk/lib/files/upload'; 5 | import { KinveyError } from 'kinvey-js-sdk/lib/errors'; 6 | 7 | const MAX_BACKOFF = 32 * 1000; 8 | 9 | function uploadFile(url: string, file: File, metadata: any, options: any = {}): Promise { 10 | return new Promise((resolve, reject) => { 11 | const session = bghttp.session('file-upload'); 12 | const request = { 13 | url, 14 | method: 'POST', 15 | headers: Object.assign({}, options.headers, { 16 | 'Content-Type': metadata.mimeType 17 | }), 18 | description: 'Kinvey File Upload' 19 | }; 20 | const task = session.uploadFile(file.path, request); 21 | 22 | task.on('error', (e) => { 23 | reject(e.error); 24 | }); 25 | 26 | task.on('cancelled', (e) => { 27 | reject(new KinveyError(`File upload for ${file.path} has been cancelled.`)); 28 | }); 29 | 30 | if (isFunction(options.onProgress)) { 31 | task.on('progress', (e) => { 32 | options.onProgress(e); 33 | }); 34 | } 35 | 36 | task.on('complete', () => { 37 | resolve(); 38 | }); 39 | }); 40 | } 41 | 42 | export async function upload(filePath: string | File, metadata: any = {}, options: any = {}) { 43 | let file; 44 | 45 | if (filePath instanceof File) { 46 | file = filePath; 47 | } else if (File.exists(filePath)) { 48 | file = File.fromPath(filePath); 49 | } else { 50 | throw new KinveyError(`A file does not exist at ${filePath}.`); 51 | } 52 | 53 | const fileMetadata = transformMetadata(file, metadata); 54 | const kinveyFile = await saveFileMetadata(fileMetadata, options); 55 | await uploadFile(kinveyFile._uploadURL, file, fileMetadata, { 56 | timeout: options.timeout, 57 | headers: kinveyFile._requiredHeaders, 58 | onProgress: options.onProgress 59 | }); 60 | 61 | delete kinveyFile._expiresAt; 62 | delete kinveyFile._requiredHeaders; 63 | delete kinveyFile._uploadURL; 64 | return kinveyFile; 65 | } 66 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/nativescript/httpAdapter.ts: -------------------------------------------------------------------------------- 1 | import { Http, Device } from '@nativescript/core'; 2 | import { name, version } from '../../package.json'; 3 | 4 | function deviceInformation() { 5 | const platform = Device.os; 6 | const version = Device.osVersion; 7 | const manufacturer = Device.manufacturer; 8 | const parts = [`js-${name}/${version}`]; 9 | 10 | return parts.concat([platform, version, manufacturer]).map((part) => { 11 | if (part) { 12 | return part.toString().replace(/\s/g, '_').toLowerCase(); 13 | } 14 | 15 | return 'unknown'; 16 | }).join(' '); 17 | } 18 | 19 | function deviceInfo() { 20 | return { 21 | hv: 1, 22 | md: Device.model, 23 | os: Device.os, 24 | ov: Device.osVersion, 25 | sdk: { 26 | name, 27 | version 28 | }, 29 | pv: Device.sdkVersion, 30 | ty: Device.deviceType, 31 | id: Device.uuid 32 | }; 33 | } 34 | 35 | export async function send(request: any): Promise { 36 | const { url, method, headers, body, timeout } = request; 37 | const kinveyUrlRegex = /kinvey\.com/gm; 38 | 39 | // Add kinvey device information headers 40 | if (kinveyUrlRegex.test(url)) { 41 | headers['X-Kinvey-Device-Information'] = deviceInformation(); 42 | headers['X-Kinvey-Device-Info'] = JSON.stringify(deviceInfo()); 43 | } 44 | 45 | const response = await Http.request({ 46 | headers, 47 | method, 48 | url, 49 | content: body, 50 | timeout 51 | }); 52 | 53 | let data; 54 | if (response.content) { 55 | try { 56 | data = response.content.toString(); 57 | } catch (e) { 58 | // TODO: log error 59 | data = response.content.raw; 60 | } 61 | } 62 | 63 | return { 64 | statusCode: response.statusCode, 65 | headers: response.headers, 66 | data 67 | }; 68 | } 69 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/nativescript/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | getAppVersion, 3 | setAppVersion, 4 | logger, 5 | ping, 6 | Acl, 7 | Aggregation, 8 | CustomEndpoint, 9 | DataStore, 10 | DataStoreType, 11 | Errors, 12 | Kmd, 13 | Query, 14 | AuthorizationGrant, 15 | MFA 16 | } from 'kinvey-js-sdk'; 17 | import * as Files from './files'; 18 | import { User } from './user'; 19 | import { init, initialize } from './init'; 20 | import { StorageProvider } from './storage'; 21 | 22 | // SDK 23 | export { 24 | // Init 25 | init, 26 | initialize, 27 | StorageProvider, 28 | 29 | // App Version 30 | getAppVersion, 31 | setAppVersion, 32 | 33 | // Logger 34 | logger, 35 | 36 | // Ping 37 | ping, 38 | 39 | // Acl 40 | Acl, 41 | 42 | // Aggregation 43 | Aggregation, 44 | 45 | // Custom Endpoint 46 | CustomEndpoint, 47 | 48 | // DataStore 49 | DataStore, 50 | DataStoreType, 51 | 52 | // Errors 53 | Errors, 54 | 55 | // Files 56 | Files, 57 | 58 | // Kmd 59 | Kmd, 60 | Kmd as Metadata, 61 | 62 | // Query 63 | Query, 64 | 65 | // User 66 | User, 67 | AuthorizationGrant, 68 | 69 | MFA 70 | }; 71 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/nativescript/init.ts: -------------------------------------------------------------------------------- 1 | import { init as coreInit } from 'kinvey-js-sdk'; 2 | import PubNub from 'pubnub/lib/nativescript'; 3 | import * as HttpAdapter from './httpAdapter'; 4 | import * as SessionStore from './sessionStore'; 5 | import * as Popup from './popup'; 6 | import { getStorageAdapter, StorageProvider } from './storage'; 7 | import { getDataFromPackageJson } from './utils'; 8 | 9 | export interface KinveyConfig { 10 | appKey: string; 11 | appSecret: string; 12 | masterSecret?: string; 13 | appVersion?: string; 14 | instanceId?: string; 15 | storage?: StorageProvider; 16 | } 17 | 18 | export function init(config?: KinveyConfig) { 19 | const configFromPackageJson = getDataFromPackageJson(); 20 | const mergedConfig = Object.assign({}, configFromPackageJson, config); 21 | const kinveyConfig = coreInit({ 22 | kinveyConfig: mergedConfig, 23 | httpAdapter: HttpAdapter, 24 | sessionStore: SessionStore, 25 | popup: Popup, 26 | storageAdapter: getStorageAdapter(mergedConfig.storage), 27 | pubnub: PubNub 28 | }); 29 | return Object.assign({}, kinveyConfig, { storage: mergedConfig.storage, _storage: mergedConfig.storage }); 30 | } 31 | 32 | export function initialize(config?: KinveyConfig) { 33 | return init(config); 34 | } 35 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/nativescript/live.ts: -------------------------------------------------------------------------------- 1 | import { Application, isIOS, Connectivity } from '@nativescript/core'; 2 | import * as live from 'kinvey-js-sdk/lib/live'; 3 | let currentConnectionType = Connectivity.getConnectionType(); 4 | 5 | export function startMonitoring() { 6 | // Reconnect live service on the application resume event 7 | Application.off(Application.resumeEvent); 8 | Application.on(Application.resumeEvent, () => { 9 | if (isIOS) { 10 | live.reconnect(); 11 | } 12 | }); 13 | 14 | // Monitor network connectivity and reconnect live service when necessary 15 | Connectivity.stopMonitoring(); 16 | Connectivity.startMonitoring((newConnectionType) => { 17 | if (currentConnectionType === Connectivity.connectionType.none && (newConnectionType === Connectivity.connectionType.wifi || newConnectionType === Connectivity.connectionType.mobile)) { 18 | live.reconnect(); 19 | } 20 | 21 | currentConnectionType = newConnectionType; 22 | }); 23 | } 24 | 25 | export function stopMonitoring() { 26 | Application.off(Application.resumeEvent); 27 | Connectivity.stopMonitoring(); 28 | } 29 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/nativescript/popup/index.ts: -------------------------------------------------------------------------------- 1 | import { Popup } from './popup'; 2 | 3 | export function open(url: string) { 4 | return Popup.open(url); 5 | } 6 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/nativescript/popup/popup.ts: -------------------------------------------------------------------------------- 1 | /* THIS IS A PLACEHOLDER FILE AND WILL BE REMOVED WHEN NATIVESCRIPT BUILDS */ 2 | 3 | import { EventEmitter } from 'events'; 4 | 5 | export class Popup extends EventEmitter { 6 | isClosed() { 7 | return true; 8 | } 9 | 10 | onLoaded(listener: (event: any) => void): this { 11 | return this; 12 | } 13 | 14 | onClosed(listener: () => void): this { 15 | return this; 16 | } 17 | 18 | onError(listener: () => void): this { 19 | return this; 20 | } 21 | 22 | async close(): Promise { 23 | return; 24 | } 25 | 26 | static async open(url: string, options?: any): Promise { 27 | throw new Error('Popup does not work.') 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/nativescript/sessionStore.ts: -------------------------------------------------------------------------------- 1 | import { SecureStorage } from '@nativescript/secure-storage'; 2 | import * as live from './live'; 3 | 4 | export async function get(key: string): Promise { 5 | const secureStorage = new SecureStorage(); 6 | return secureStorage.getSync({ key }); 7 | } 8 | 9 | export async function set(key: string, session: string): Promise { 10 | const secureStorage = new SecureStorage(); 11 | const result = secureStorage.setSync({ 12 | key, 13 | value: session 14 | }); 15 | 16 | if (result) { 17 | live.startMonitoring(); 18 | } 19 | 20 | return result; 21 | } 22 | 23 | export async function remove(key: string): Promise { 24 | const secureStorage = new SecureStorage(); 25 | const result = secureStorage.removeSync({ key }); 26 | 27 | if (result) { 28 | live.stopMonitoring(); 29 | } 30 | 31 | return result; 32 | } 33 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/nativescript/storage/index.ts: -------------------------------------------------------------------------------- 1 | import { Errors } from 'kinvey-js-sdk'; 2 | import * as SQLite from './sqlite'; 3 | 4 | export enum StorageProvider { 5 | SQLite = 'SQLite' 6 | }; 7 | 8 | export function getStorageAdapter(storageProvider = StorageProvider.SQLite) { 9 | if (storageProvider === StorageProvider.SQLite) { 10 | return SQLite; 11 | } 12 | 13 | throw new Errors.KinveyError(`Please specify 'storage' option. Supported values are: ${Object.values(StorageProvider)}.`); 14 | } 15 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/nativescript/user/index.ts: -------------------------------------------------------------------------------- 1 | import { User as CoreUser, AuthorizationGrant } from 'kinvey-js-sdk'; 2 | import { loginWithMIC } from './loginWithMIC'; 3 | import { loginWithRedirectUri } from './loginWithRedirectUri'; 4 | 5 | export class User extends CoreUser { 6 | static loginWithMIC(redirectUri?: string, authorizationGrant?: AuthorizationGrant, options?: any) { 7 | return loginWithMIC(redirectUri, authorizationGrant, options); 8 | } 9 | 10 | static loginWithRedirectUri(redirectUri?: string, options?: any) { 11 | return loginWithRedirectUri(redirectUri, options); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/nativescript/user/loginWithMIC.ts: -------------------------------------------------------------------------------- 1 | import { AuthorizationGrant } from 'kinvey-js-sdk'; 2 | import { loginWithRedirectUri } from './loginWithRedirectUri'; 3 | 4 | export async function loginWithMIC(redirectUri?: string, authorizationGrant?: AuthorizationGrant, options?: any) { 5 | return loginWithRedirectUri(redirectUri, options); 6 | } 7 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/nativescript/user/loginWithRedirectUri.ts: -------------------------------------------------------------------------------- 1 | import { Application, isAndroid, isIOS } from '@nativescript/core'; 2 | import { loginWithRedirectUri as loginWithRedirectUriCommon } from 'kinvey-js-sdk/lib/user/loginWithRedirectUri'; 3 | import { getDataFromPackageJson } from '../utils'; 4 | 5 | declare const NSBundle: any; 6 | 7 | function getAppIdentifier(): string | null { 8 | if (isAndroid) { 9 | return Application.android.packageName; 10 | } else if (isIOS) { 11 | return NSBundle.mainBundle.bundleIdentifier; 12 | } 13 | return null; 14 | } 15 | 16 | function getRedirectUri(redirectUri?: string) { 17 | const appIdentifier = getAppIdentifier(); 18 | 19 | if (appIdentifier) { 20 | if (appIdentifier === 'org.nativescript.preview') { 21 | return 'nsplayresume://'; 22 | } else if (appIdentifier === 'com.kinvey.preview') { 23 | return 'kspreviewresume://'; 24 | } 25 | } 26 | 27 | return redirectUri; 28 | } 29 | 30 | export function loginWithRedirectUri(providedRedirectUri?: string, options?: any) { 31 | const redirectUri = getRedirectUri(providedRedirectUri); 32 | const config = getDataFromPackageJson(); 33 | return loginWithRedirectUriCommon(redirectUri || config.redirectUri, options); 34 | } 35 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/src/nativescript/utils.ts: -------------------------------------------------------------------------------- 1 | import { knownFolders } from '@nativescript/core'; 2 | 3 | export function getDataFromPackageJson() { 4 | try { 5 | const currentAppDir = knownFolders.currentApp(); 6 | const packageJsonFile = currentAppDir.getFile('package.json'); 7 | const packageJsonData = JSON.parse(packageJsonFile.readTextSync()); 8 | 9 | const pluginsData = packageJsonData && packageJsonData.pluginsData; 10 | const kinveyNativeScriptSdkData = pluginsData && pluginsData['kinvey-nativescript-sdk'] && pluginsData['kinvey-nativescript-sdk'].config; 11 | return kinveyNativeScriptSdkData; 12 | } catch (err) { 13 | return null; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2017", 4 | "module": "esnext", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "noImplicitUseStrict": true, 10 | "noEmitHelpers": true, 11 | "declaration": true, 12 | "removeComments": false, 13 | "noEmitOnError": true, 14 | "noImplicitAny": false, 15 | "importHelpers": false, 16 | "lib": ["es2017", "dom"], 17 | "esModuleInterop": true, 18 | "resolveJsonModule": true, 19 | "allowSyntheticDefaultImports": true, 20 | "outDir": "./lib", 21 | "skipLibCheck": true 22 | }, 23 | "angularCompilerOptions": { 24 | "genDir": ".", 25 | "skipMetadataEmit": false, 26 | "skipTemplateCodegen": true, 27 | "strictMetadataEmit": true 28 | }, 29 | "exclude": [ 30 | "node_modules", 31 | "platforms" 32 | ] 33 | } 34 | -------------------------------------------------------------------------------- /packages/nativescript-sdk/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "class-name": true, 4 | "comment-format": [ 5 | true, 6 | "check-space" 7 | ], 8 | "indent": [ 9 | true, 10 | "spaces" 11 | ], 12 | "no-duplicate-variable": true, 13 | "no-eval": true, 14 | "no-internal-module": true, 15 | "no-trailing-whitespace": true, 16 | "no-var-keyword": true, 17 | "one-line": [ 18 | true, 19 | "check-open-brace", 20 | "check-whitespace" 21 | ], 22 | "quotemark": [ 23 | false, 24 | "double" 25 | ], 26 | "semicolon": [ 27 | true, 28 | "always" 29 | ], 30 | "triple-equals": [ 31 | true, 32 | "allow-null-check" 33 | ], 34 | "typedef-whitespace": [ 35 | true, 36 | { 37 | "call-signature": "nospace", 38 | "index-signature": "nospace", 39 | "parameter": "nospace", 40 | "property-declaration": "nospace", 41 | "variable-declaration": "nospace" 42 | } 43 | ], 44 | "variable-name": [ 45 | true, 46 | "ban-keywords" 47 | ], 48 | "whitespace": [ 49 | true, 50 | "check-branch", 51 | "check-decl", 52 | "check-operator", 53 | "check-separator", 54 | "check-type" 55 | ] 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/node-sdk/.editorconfig: -------------------------------------------------------------------------------- 1 | #root = true 2 | 3 | [*] 4 | indent_style = space 5 | end_of_line = lf 6 | charset = utf-8 7 | trim_trailing_whitespace = true 8 | insert_final_newline = true 9 | max_line_length = 100 10 | indent_size = 2 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /packages/node-sdk/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .idea 3 | .DS_Store 4 | *.log 5 | node_modules 6 | lib 7 | dist 8 | *.tgz 9 | -------------------------------------------------------------------------------- /packages/node-sdk/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | We're really glad you're reading this, because we need volunteer developers to help this project come to fruition. 👏 2 | 3 | ## Instructions 4 | 5 | These steps will guide you through contributing to this project: 6 | 7 | - Fork the repo 8 | - Clone it and install dependencies 9 | 10 | git clone https://github.com/YOUR-USERNAME/typescript-library-starter 11 | npm install 12 | 13 | Keep in mind that after running `npm install` the git repo is reset. So a good way to cope with this is to have a copy of the folder to push the changes, and the other to try them. 14 | 15 | Make and commit your changes. Make sure the commands npm run build and npm run test:prod are working. 16 | 17 | Finally send a [GitHub Pull Request](https://github.com/alexjoverm/typescript-library-starter/compare?expand=1) with a clear list of what you've done (read more [about pull requests](https://help.github.com/articles/about-pull-requests/)). Make sure all of your commits are atomic (one feature per commit). 18 | -------------------------------------------------------------------------------- /packages/node-sdk/README.md: -------------------------------------------------------------------------------- 1 | # Kinvey NodeJS SDK 2 | 3 | ## Installation 4 | 5 | From the command prompt go to your app's root folder and execute: 6 | 7 | ```bash 8 | npm i kinvey-node-sdk@next 9 | ``` 10 | 11 | ## Usage 12 | 13 | ### Initialize SDK 14 | 15 | We need to initialize the SDK. 16 | 17 | #### JavaScript with NPM 18 | ```js 19 | var Kinvey = require('kinvey-node-sdk'); 20 | 21 | Kinvey.init({ 22 | appKey: '', 23 | appSecret: '' 24 | }); 25 | ``` 26 | 27 | ## Build 28 | 29 | If you would like to build the SDK yourself, clone the monorepo, then: 30 | - `npm i` 31 | - `npm run build` 32 | 33 | You can then install the SDK build by running `npm i //packages/node-sdk` 34 | -------------------------------------------------------------------------------- /packages/node-sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kinvey-node-sdk", 3 | "description": "Kinvey JavaScript SDK for NodeJS applications.", 4 | "version": "7.0.0", 5 | "license": "Apache-2.0", 6 | "homepage": "https://github.com/Kinvey/js-sdk/tree/master/packages/node-sdk", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/Kinvey/js-sdk.git" 10 | }, 11 | "bugs": { 12 | "url": "https://github.com/Kinvey/js-sdk/issues" 13 | }, 14 | "author": { 15 | "name": "Thomas Conner", 16 | "email": "thomas.conner@progress.com" 17 | }, 18 | "keywords": [ 19 | "Kinvey", 20 | "JavaScript", 21 | "NodeJS" 22 | ], 23 | "main": "lib/index.js", 24 | "scripts": { 25 | "prebuild": "del lib", 26 | "build": "tsc -p tsconfig.json", 27 | "postbuild": "node scripts/postbuild.js" 28 | }, 29 | "dependencies": { 30 | "axios": "0.26.1", 31 | "events": "3.0.0", 32 | "kinvey-js-sdk": "^7.0.0", 33 | "lodash": "4.17.21", 34 | "pubnub": "5.0.1", 35 | "tslib": "1.10.0" 36 | }, 37 | "devDependencies": { 38 | "@types/events": "~3.0.0", 39 | "@types/lodash": "4.14.137", 40 | "@types/node": "~12.7.2", 41 | "del-cli": "2.0.0", 42 | "fs-extra": "~8.1.0", 43 | "typescript": "~3.5.3" 44 | }, 45 | "files": [ 46 | "lib/**/*" 47 | ] 48 | } 49 | -------------------------------------------------------------------------------- /packages/node-sdk/scripts/postbuild.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs-extra'); 2 | const path = require('path'); 3 | 4 | const rootPath = path.join(__dirname, '..'); 5 | const libPath = path.join(rootPath, 'lib'); 6 | const tmpPath = path.join(rootPath, 'tmp'); 7 | 8 | // Copy /lib to /tmp 9 | fs.copySync(libPath, tmpPath); 10 | 11 | // Remove /lib 12 | fs.removeSync(libPath); 13 | 14 | // Copy /tmp/src to /lib 15 | fs.copySync(path.join(tmpPath, 'src'), libPath); 16 | 17 | // Remove /tmp 18 | fs.removeSync(tmpPath); 19 | -------------------------------------------------------------------------------- /packages/node-sdk/src/httpAdapter.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import os from 'os'; 3 | import { NetworkError } from 'kinvey-js-sdk/lib/errors/network'; 4 | import { TimeoutError } from 'kinvey-js-sdk/lib/errors/timeout'; 5 | import { name, version } from '../package.json'; 6 | 7 | function deviceInformation() { 8 | const platform = process.title; 9 | const { version } = process; 10 | const manufacturer = process.platform; 11 | 12 | // Return the device information string. 13 | const parts = [`js-${name}/${version}`]; 14 | 15 | return parts.concat([platform, version, manufacturer]).map((part) => { 16 | if (part) { 17 | return part.toString().replace(/\s/g, '_').toLowerCase(); 18 | } 19 | 20 | return 'unknown'; 21 | }).join(' '); 22 | } 23 | 24 | export function deviceInfo() { 25 | return { 26 | hv: 1, 27 | os: os.platform(), 28 | ov: os.release(), 29 | sdk: { 30 | name, 31 | version 32 | }, 33 | pv: process.version 34 | }; 35 | } 36 | 37 | export async function send(request: any) { 38 | const { url, method, headers, body, timeout } = request; 39 | let response; 40 | 41 | // Add kinvey device information headers 42 | if (/kinvey\.com/gm.test(url)) { 43 | headers['X-Kinvey-Device-Information'] = deviceInformation(); 44 | headers['X-Kinvey-Device-Info'] = JSON.stringify(deviceInfo()); 45 | } 46 | 47 | try { 48 | response = await axios({ 49 | headers, 50 | method, 51 | url, 52 | data: body, 53 | timeout 54 | }); 55 | } catch (error) { 56 | if (error.code === 'ESOCKETTIMEDOUT' 57 | || error.code === 'ETIMEDOUT' 58 | || error.code === 'ECONNABORTED') { 59 | throw new TimeoutError('The network request timed out.'); 60 | } 61 | 62 | if (error.code === 'ENOENT' 63 | || !error.response) { 64 | throw new NetworkError(); 65 | } 66 | 67 | response = error.response; 68 | } 69 | 70 | return { 71 | statusCode: response.status, 72 | headers: response.headers, 73 | data: response.data 74 | }; 75 | } 76 | -------------------------------------------------------------------------------- /packages/node-sdk/src/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | getAppVersion, 3 | setAppVersion, 4 | logger, 5 | ping, 6 | Acl, 7 | Aggregation, 8 | CustomEndpoint, 9 | DataStore, 10 | DataStoreType, 11 | Errors, 12 | Files, 13 | Kmd, 14 | Query, 15 | User, 16 | AuthorizationGrant, 17 | MFA 18 | } from 'kinvey-js-sdk'; 19 | import { init, initialize } from './init'; 20 | import { StorageProvider } from './storage'; 21 | 22 | // SDK 23 | export { 24 | // Init 25 | init, 26 | initialize, 27 | StorageProvider, 28 | 29 | // App Version 30 | getAppVersion, 31 | setAppVersion, 32 | 33 | // Logger 34 | logger, 35 | 36 | // Ping 37 | ping, 38 | 39 | // Acl 40 | Acl, 41 | 42 | // Aggregation 43 | Aggregation, 44 | 45 | // Custom Endpoint 46 | CustomEndpoint, 47 | 48 | // DataStore 49 | DataStore, 50 | DataStoreType, 51 | 52 | // Errors 53 | Errors, 54 | 55 | // Files 56 | Files, 57 | 58 | // Kmd 59 | Kmd, 60 | Kmd as Metadata, 61 | 62 | // Query 63 | Query, 64 | 65 | // User 66 | User, 67 | AuthorizationGrant, 68 | 69 | MFA 70 | }; 71 | -------------------------------------------------------------------------------- /packages/node-sdk/src/init.ts: -------------------------------------------------------------------------------- 1 | import { init as coreInit } from 'kinvey-js-sdk'; 2 | import PubNub from 'pubnub'; 3 | import * as HttpAdapter from './httpAdapter'; 4 | import * as SessionStore from './sessionStore'; 5 | import * as Popup from './popup'; 6 | import { getStorageAdapter, StorageProvider } from './storage'; 7 | 8 | export interface KinveyConfig { 9 | appKey: string; 10 | appSecret: string; 11 | masterSecret?: string; 12 | appVersion?: string; 13 | instanceId?: string; 14 | storage?: StorageProvider; 15 | } 16 | export function init(config: KinveyConfig) { 17 | const kinveyConfig = coreInit({ 18 | kinveyConfig: config, 19 | httpAdapter: HttpAdapter, 20 | sessionStore: SessionStore, 21 | popup: Popup, 22 | storageAdapter: getStorageAdapter(config.storage), 23 | pubnub: PubNub 24 | }) 25 | return Object.assign({}, kinveyConfig, { storage: config.storage, _storage: config.storage }); 26 | } 27 | 28 | export function initialize(config: KinveyConfig) { 29 | return init(config); 30 | } 31 | -------------------------------------------------------------------------------- /packages/node-sdk/src/popup.ts: -------------------------------------------------------------------------------- 1 | import { Errors } from 'kinvey-js-sdk'; 2 | 3 | export async function open(url: string): Promise { 4 | throw new Errors.KinveyError('NodeJS does not support the opening of popups.'); 5 | } 6 | -------------------------------------------------------------------------------- /packages/node-sdk/src/sessionStore.ts: -------------------------------------------------------------------------------- 1 | const store = new Map(); 2 | 3 | export async function get(key: string): Promise { 4 | return store.get(key); 5 | } 6 | 7 | export async function set(key: string, session: string): Promise { 8 | store.set(key, session); 9 | return true; 10 | } 11 | 12 | export async function remove(key: string): Promise { 13 | return store.delete(key); 14 | } 15 | -------------------------------------------------------------------------------- /packages/node-sdk/src/storage/index.ts: -------------------------------------------------------------------------------- 1 | import { Errors } from 'kinvey-js-sdk'; 2 | import * as Memory from './memory'; 3 | 4 | export enum StorageProvider { 5 | Memory = 'Memory' 6 | }; 7 | 8 | export function getStorageAdapter(storageProvider = StorageProvider.Memory) { 9 | if (storageProvider === StorageProvider.Memory) { 10 | return Memory; 11 | } 12 | 13 | throw new Errors.KinveyError(`Please specify 'storage' option. Supported values are: ${Object.values(StorageProvider)}.`); 14 | } 15 | -------------------------------------------------------------------------------- /packages/node-sdk/src/storage/memory.ts: -------------------------------------------------------------------------------- 1 | const store = new Map>(); 2 | 3 | function getTable(dbName: string, tableName: string) { 4 | return store.get(`${dbName}.${tableName}`) || new Map(); 5 | } 6 | 7 | function setTable(dbName: string, tableName: string, table: Map) { 8 | return store.set(`${dbName}.${tableName}`, table); 9 | } 10 | 11 | export async function find(dbName: string, tableName: string) { 12 | const table = getTable(dbName, tableName); 13 | return Array.from(table.values()); 14 | } 15 | 16 | export async function count(dbName: string, tableName: string) { 17 | const docs = await find(dbName, tableName); 18 | return docs.length; 19 | } 20 | 21 | export async function findById(dbName: string, tableName: string, id: string) { 22 | const docs = await find(dbName, tableName); 23 | return docs.find((doc: any) => doc._id === id); 24 | } 25 | 26 | export async function save(dbName: string, tableName: string, docs: any = []) { 27 | const table = getTable(dbName, tableName); 28 | docs.forEach((doc: { _id: string; }) => { 29 | table.set(doc._id, doc); 30 | }); 31 | setTable(dbName, tableName, table); 32 | return docs; 33 | } 34 | 35 | export async function removeById(dbName: string, tableName: string, id: string) { 36 | const table = getTable(dbName, tableName); 37 | if (table.delete(id)) { 38 | setTable(dbName, tableName, table); 39 | return 1; 40 | } 41 | return 0; 42 | } 43 | 44 | export async function removeManyById(dbName: string, tableName: string, ids: string[]) { 45 | const table = getTable(dbName, tableName); 46 | const deleted = ids.map(id => table.delete(id)); 47 | setTable(dbName, tableName, table); 48 | return deleted.filter(i => i).length; 49 | } 50 | 51 | export async function clear(dbName: string, tableName: string) { 52 | store.delete(`${dbName}.${tableName}`); 53 | return true; 54 | } 55 | 56 | export async function clearDatabase() { 57 | store.clear(); 58 | return true; 59 | } 60 | -------------------------------------------------------------------------------- /packages/node-sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "module": "commonjs", 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "emitDecoratorMetadata": true, 8 | "experimentalDecorators": true, 9 | "noImplicitUseStrict": true, 10 | "noEmitHelpers": true, 11 | "declaration": true, 12 | "removeComments": false, 13 | "noEmitOnError": true, 14 | "noImplicitAny": false, 15 | "importHelpers": true, 16 | "lib": [ 17 | "dom", 18 | "es6", 19 | "es2015.iterable" 20 | ], 21 | "esModuleInterop": true, 22 | "resolveJsonModule": true, 23 | "allowSyntheticDefaultImports": true, 24 | "outDir": "lib" 25 | }, 26 | "exclude": [ 27 | "node_modules" 28 | ] 29 | } 30 | -------------------------------------------------------------------------------- /packages/node-sdk/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "rules": { 3 | "class-name": true, 4 | "comment-format": [ 5 | true, 6 | "check-space" 7 | ], 8 | "indent": [ 9 | true, 10 | "spaces" 11 | ], 12 | "no-duplicate-variable": true, 13 | "no-eval": true, 14 | "no-internal-module": true, 15 | "no-trailing-whitespace": true, 16 | "no-var-keyword": true, 17 | "one-line": [ 18 | true, 19 | "check-open-brace", 20 | "check-whitespace" 21 | ], 22 | "quotemark": [ 23 | false, 24 | "double" 25 | ], 26 | "semicolon": [ 27 | true, 28 | "always" 29 | ], 30 | "triple-equals": [ 31 | true, 32 | "allow-null-check" 33 | ], 34 | "typedef-whitespace": [ 35 | true, 36 | { 37 | "call-signature": "nospace", 38 | "index-signature": "nospace", 39 | "parameter": "nospace", 40 | "property-declaration": "nospace", 41 | "variable-declaration": "nospace" 42 | } 43 | ], 44 | "variable-name": [ 45 | true, 46 | "ban-keywords" 47 | ], 48 | "whitespace": [ 49 | true, 50 | "check-branch", 51 | "check-decl", 52 | "check-operator", 53 | "check-separator", 54 | "check-type" 55 | ] 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /packages/react-native-sdk/.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | indent_style = space 3 | end_of_line = lf 4 | charset = utf-8 5 | trim_trailing_whitespace = true 6 | insert_final_newline = true 7 | max_line_length = 100 8 | indent_size = 2 9 | 10 | [*.md] 11 | trim_trailing_whitespace = false 12 | -------------------------------------------------------------------------------- /packages/react-native-sdk/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["kinvey-js-sdk"], 3 | "rules": { 4 | "no-underscore-dangle": "off" 5 | }, 6 | "overrides": [ 7 | { 8 | "files": [ 9 | "jest/**/*.js", 10 | "jest/**/*.ts", 11 | "**/*.spec.js", 12 | "**/*.spec.ts", 13 | "__mocks__/**/*.js", 14 | "__mocks__/**/*.ts" 15 | ], 16 | "rules": { 17 | "spaced-comment": "off", 18 | "func-names": "off", 19 | "no-undef": "off", 20 | "no-unused-expressions": "off", 21 | "@typescript-eslint/ban-ts-ignore": "off", 22 | "@typescript-eslint/explicit-function-return-type": "off", 23 | "import/first": "off", 24 | "import/no-extraneous-dependencies": "off", 25 | "jest/no-disabled-tests": "warn", 26 | "jest/no-focused-tests": "error", 27 | "jest/no-identical-title": "error", 28 | "jest/prefer-to-have-length": "warn", 29 | "jest/valid-expect": "error" 30 | }, 31 | "env": { 32 | "jest": true 33 | }, 34 | "plugins": ["jest"] 35 | } 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /packages/react-native-sdk/.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Dependency directories 9 | node_modules 10 | 11 | # Optional npm cache directory 12 | .npm 13 | 14 | # Optional eslint cache 15 | .eslintcache 16 | 17 | # Yarn Integrity file 18 | .yarn-integrity 19 | 20 | # dotenv environment variables file 21 | .env 22 | 23 | # Windows 24 | Thumbs.db 25 | Desktop.ini 26 | 27 | # Mac 28 | .DS_Store 29 | 30 | # Build 31 | lib 32 | 33 | # Output of 'npm pack' 34 | *.tgz 35 | 36 | # Code Coverage 37 | .nyc_output 38 | coverage 39 | 40 | # Jest 41 | __mocks__ 42 | -------------------------------------------------------------------------------- /packages/react-native-sdk/.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 120, 3 | "singleQuote": true 4 | } 5 | -------------------------------------------------------------------------------- /packages/react-native-sdk/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | We're really glad you're reading this, because we need volunteer developers to help this project come to fruition. 👏 2 | 3 | ## Instructions 4 | 5 | These steps will guide you through contributing to this project: 6 | 7 | - Fork the repo 8 | - Clone it and install dependencies 9 | 10 | git clone https://github.com/YOUR-USERNAME/js-sdk 11 | npm install 12 | 13 | Keep in mind that after running `npm install` the git repo is reset. So a good way to cope with this is to have a copy of the folder to push the changes, and the other to try them. 14 | 15 | Make and commit your changes. 16 | 17 | Finally send a [GitHub Pull Request](https://github.com/Kinvey/js-sdk/compare?expand=1) with a clear list of what you've done (read more [about pull requests](https://help.github.com/articles/about-pull-requests/)). Make sure all of your commits are atomic (one feature per commit). 18 | -------------------------------------------------------------------------------- /packages/react-native-sdk/README.md: -------------------------------------------------------------------------------- 1 | # Kinvey React Native SDK 2 | 3 | The Kinvey React Native SDK is used to develop an React Native application that connects to Kinvey. 4 | 5 | ## Install 6 | 7 | Using npm install the sdk: 8 | 9 | ```bash 10 | npm i --save kinvey-react-native-sdk 11 | ``` 12 | 13 | #### Install Peer Dependencies 14 | 15 | You will need to install the peer dependencies `@react-native-async-storage/async-storage`, `react-native-keychain` and `react-native-inappbrowser-reborn` 16 | 17 | ```bash 18 | npm i --save @react-native-async-storage/async-storage 19 | ``` 20 | 21 | ```bash 22 | npm i --save react-native-keychain 23 | ``` 24 | 25 | ```bash 26 | npm i --save react-native-inappbrowser-reborn 27 | ``` 28 | 29 | After installing them, make sure you install the cocoapods for iOS. 30 | 31 | ```bash 32 | cd ios && pod install && cd .. 33 | ``` 34 | 35 | #### **Optional** Install Push Notification 36 | 37 | If you would like your application to receive push notifications you will need to install the peer dependency `react-native-push-notification`. 38 | 39 | ```bash 40 | npm i --save react-native-push-notification 41 | ``` 42 | 43 | ##### For iOS 44 | 45 | To receive push notifications on iOS you will need to install `@react-native-community/push-notification-ios`. 46 | 47 | ```bash 48 | npm i --save @react-native-community/push-notification-ios 49 | ``` 50 | 51 | After installing `@react-native-community/push-notification-ios` make sure you install the cocoapods for iOS. 52 | 53 | ```bash 54 | cd ios && pod install && cd .. 55 | ``` 56 | 57 | Follow [this guide](https://github.com/react-native-community/react-native-push-notification-ios) to add the needed Push Notification capabilities in Xcode and also to update your `AppDelegate.m` and `AppDelegate.h`. 58 | 59 | ##### For Android 60 | Setup a Firebase project and download the `google-services.json` file in your `android/app` folder as explained [here](https://firebase.google.com/docs/cloud-messaging/android/client). 61 | Then follow [this guide](https://github.com/zo0r/react-native-push-notification#android-manual-installation) to complete the setup for Android. 62 | -------------------------------------------------------------------------------- /packages/react-native-sdk/jest.config.js: -------------------------------------------------------------------------------- 1 | const config = { 2 | preset: 'react-native', 3 | collectCoverage: true, 4 | moduleDirectories: ['node_modules', 'src', 'test'], 5 | transform: { 6 | '^.+\\.js$': '/node_modules/react-native/jest/preprocessor.js', 7 | '^.+\\.tsx?$': 'ts-jest' 8 | }, 9 | globals: { 10 | 'ts-jest': { 11 | tsConfigFile: 'tsconfig.jest.json' 12 | } 13 | }, 14 | moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'], 15 | testRegex: '(/test/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$', 16 | setupFiles: ['/jest.setup.ts'], 17 | transformIgnorePatterns: ['node_modules/(?!(jest-)?react-native|@react-native)'], 18 | coveragePathIgnorePatterns: ['/node_modules/', '/jest', '/demo'], 19 | testPathIgnorePatterns: ['/node_modules/', '/demo'] 20 | }; 21 | 22 | module.exports = config; 23 | -------------------------------------------------------------------------------- /packages/react-native-sdk/jest.setup.ts: -------------------------------------------------------------------------------- 1 | import mockAsyncStorage from '@react-native-async-storage/async-storage/jest/async-storage-mock'; 2 | 3 | jest.mock('@react-native-async-storage/async-storage', () => mockAsyncStorage); 4 | 5 | const mockSecureStore = new Map(); 6 | 7 | jest.mock('react-native-keychain', () => ({ 8 | SECURITY_LEVEL_ANY: "MOCK_SECURITY_LEVEL_ANY", 9 | SECURITY_LEVEL_SECURE_SOFTWARE: "MOCK_SECURITY_LEVEL_SECURE_SOFTWARE", 10 | SECURITY_LEVEL_SECURE_HARDWARE: "MOCK_SECURITY_LEVEL_SECURE_HARDWARE", 11 | setGenericPassword: async (key, value) => { 12 | mockSecureStore.set(key, value); 13 | return true; 14 | }, 15 | getGenericPassword: async ({ service }) => { 16 | return { password: mockSecureStore.get(service) }; 17 | }, 18 | resetGenericPassword: async ({ service }) => mockSecureStore.delete(service), 19 | })); 20 | 21 | jest.mock('react-native-push-notification', () => ({ 22 | configure: jest.fn((options) => options.onRegister({ 23 | os: 'macos', 24 | token: 'push_test_token' 25 | })), 26 | unregister: jest.fn() 27 | })); 28 | 29 | jest.mock('@react-native-community/push-notification-ios', () => { 30 | return { 31 | addEventListener: jest.fn(), 32 | requestPermissions: jest.fn(() => Promise.resolve()), 33 | getInitialNotification: jest.fn(() => Promise.resolve()) 34 | }; 35 | }); 36 | 37 | jest.mock('react-native/Libraries/Utilities/NativePlatformConstantsIOS', () => ({ 38 | getConstants: () => ({ 39 | isTesting: true 40 | }) 41 | })); 42 | -------------------------------------------------------------------------------- /packages/react-native-sdk/scripts/postbuild.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs-extra'); 2 | const path = require('path'); 3 | 4 | const rootPath = path.join(__dirname, '..'); 5 | const libPath = path.join(rootPath, 'lib'); 6 | const tmpPath = path.join(rootPath, 'tmp'); 7 | 8 | // Copy /lib to /tmp 9 | fs.copySync(libPath, tmpPath); 10 | 11 | // Remove /lib 12 | fs.removeSync(libPath); 13 | 14 | // Copy /tmp/src to /lib 15 | fs.copySync(path.join(tmpPath, 'src'), libPath); 16 | 17 | // Remove /tmp 18 | fs.removeSync(tmpPath); 19 | -------------------------------------------------------------------------------- /packages/react-native-sdk/src/httpAdapter.ts: -------------------------------------------------------------------------------- 1 | import axios from 'axios'; 2 | import { Platform } from 'react-native'; 3 | import { NetworkError } from 'kinvey-js-sdk/lib/errors/network'; 4 | import { TimeoutError } from 'kinvey-js-sdk/lib/errors/timeout'; 5 | import { name, version } from '../package.json'; 6 | 7 | export function deviceInfo() { 8 | return { 9 | hv: 1, 10 | os: Platform.OS, 11 | ov: Platform.Version, 12 | pv: Platform.Version, 13 | sdk: { 14 | name, 15 | version 16 | } 17 | }; 18 | } 19 | 20 | export async function send(request: any) { 21 | const { url, method, headers, body, timeout } = request; 22 | let response; 23 | 24 | // Add kinvey device information headers 25 | if (/kinvey\.com/gm.test(url)) { 26 | headers['X-Kinvey-Device-Info'] = JSON.stringify(deviceInfo()); 27 | } 28 | 29 | try { 30 | response = await axios({ 31 | headers, 32 | method, 33 | url, 34 | data: body, 35 | timeout 36 | }); 37 | } catch (error) { 38 | if (error.code === 'ESOCKETTIMEDOUT' || error.code === 'ETIMEDOUT' || error.code === 'ECONNABORTED') { 39 | throw new TimeoutError('The network request timed out.'); 40 | } 41 | 42 | if (error.code === 'ENOENT' || !error.response) { 43 | throw new NetworkError(); 44 | } 45 | 46 | response = error.response; 47 | } 48 | 49 | return { 50 | statusCode: response.status, 51 | headers: response.headers, 52 | data: response.data 53 | }; 54 | } 55 | -------------------------------------------------------------------------------- /packages/react-native-sdk/src/index.ts: -------------------------------------------------------------------------------- 1 | import { 2 | getAppVersion, 3 | setAppVersion, 4 | logger, 5 | ping, 6 | Acl, 7 | Aggregation, 8 | CustomEndpoint, 9 | DataStore, 10 | DataStoreType, 11 | Errors, 12 | Files, 13 | Kmd, 14 | Query, 15 | User, 16 | AuthorizationGrant, 17 | MFA 18 | } from 'kinvey-js-sdk'; 19 | import { init, initialize } from './init'; 20 | import { StorageProvider } from './storage'; 21 | 22 | // SDK 23 | export { 24 | // Init 25 | init, 26 | initialize, 27 | StorageProvider, 28 | 29 | // App Version 30 | getAppVersion, 31 | setAppVersion, 32 | // Logger 33 | logger, 34 | // Ping 35 | ping, 36 | // Acl 37 | Acl, 38 | // Aggregation 39 | Aggregation, 40 | // Custom Endpoint 41 | CustomEndpoint, 42 | // DataStore 43 | DataStore, 44 | DataStoreType, 45 | // Errors 46 | Errors, 47 | // Files 48 | Files, 49 | // Kmd 50 | Kmd, 51 | Kmd as Metadata, 52 | // Query 53 | Query, 54 | // User 55 | User, 56 | AuthorizationGrant, 57 | MFA 58 | }; 59 | -------------------------------------------------------------------------------- /packages/react-native-sdk/src/init.ts: -------------------------------------------------------------------------------- 1 | import { init as coreInit } from 'kinvey-js-sdk'; 2 | import PubNub from 'pubnub'; 3 | import * as HttpAdapter from './httpAdapter'; 4 | import * as SessionStore from './sessionStore'; 5 | import * as PopupBrowser from './popup'; 6 | import { getStorageAdapter, StorageProvider } from './storage'; 7 | 8 | export interface KinveyConfig { 9 | appKey: string; 10 | appSecret: string; 11 | masterSecret?: string; 12 | appVersion?: string; 13 | instanceId?: string; 14 | storage?: StorageProvider; 15 | } 16 | 17 | export function init(config: KinveyConfig) { 18 | const kinveyConfig = coreInit({ 19 | kinveyConfig: config, 20 | httpAdapter: HttpAdapter, 21 | sessionStore: SessionStore, 22 | popup: PopupBrowser, 23 | storageAdapter: getStorageAdapter(config.storage), 24 | pubnub: PubNub 25 | }); 26 | return { ...kinveyConfig, storage: config.storage, _storage: config.storage }; 27 | } 28 | 29 | export function initialize(config: KinveyConfig) { 30 | return init(config); 31 | } 32 | -------------------------------------------------------------------------------- /packages/react-native-sdk/src/sessionStore.ts: -------------------------------------------------------------------------------- 1 | import * as keychain from 'react-native-keychain'; 2 | 3 | export async function get(key: string): Promise { 4 | const credentials = await keychain.getGenericPassword({ service: key }) 5 | return credentials ? credentials.password : null; 6 | } 7 | 8 | export async function set(key: string, session: string): Promise { 9 | return keychain.setGenericPassword(key, session, { service: key }).then(result => !!result); 10 | } 11 | 12 | export async function remove(key: string): Promise { 13 | return keychain.resetGenericPassword({ service: key }); 14 | } 15 | -------------------------------------------------------------------------------- /packages/react-native-sdk/src/storage/asyncStorage.ts: -------------------------------------------------------------------------------- 1 | import AsyncStorage from '@react-native-async-storage/async-storage'; 2 | 3 | const SEPARATOR = ':'; 4 | 5 | function getKey(dbName: string, tableName: string, id: string) { 6 | return `${dbName}${SEPARATOR}${tableName}${SEPARATOR}${id}`; 7 | } 8 | 9 | async function getTableKeys(dbName: string, tableName: string) { 10 | const allKeys = await AsyncStorage.getAllKeys(); 11 | return allKeys.filter(key => key.indexOf(`${dbName}${SEPARATOR}${tableName}${SEPARATOR}`) === 0); 12 | } 13 | 14 | export async function find(dbName: string, tableName: string) { 15 | const tableRecords = await AsyncStorage.multiGet(await getTableKeys(dbName, tableName)); 16 | return tableRecords.map(([key, value]) => JSON.parse(value)); 17 | } 18 | 19 | export async function count(dbName: string, tableName: string) { 20 | const tableKeys = await getTableKeys(dbName, tableName); 21 | return tableKeys.length; 22 | } 23 | 24 | export async function findById(dbName: string, tableName: string, id: string) { 25 | const doc = await AsyncStorage.getItem(getKey(dbName, tableName, id)); 26 | return doc ? JSON.parse(doc) : undefined; 27 | } 28 | 29 | export async function save(dbName: string, tableName: string, docs: any = []) { 30 | const kvPairs = docs.map(doc => [getKey(dbName, tableName, doc._id), JSON.stringify(doc)]); 31 | await AsyncStorage.multiSet(kvPairs); 32 | return kvPairs; 33 | } 34 | 35 | export async function removeById(dbName: string, tableName: string, id: string) { 36 | const key = getKey(dbName, tableName, id); 37 | const doc = await AsyncStorage.getItem(key); 38 | if (doc) { 39 | await AsyncStorage.removeItem(key); 40 | return 1; 41 | } 42 | return 0; 43 | } 44 | 45 | export async function clear(dbName: string, tableName: string) { 46 | await AsyncStorage.multiRemove(await getTableKeys(dbName, tableName)); 47 | return true; 48 | } 49 | 50 | export async function clearDatabase(dbName: string, exclude: string[] = []) { 51 | const allKeys = await AsyncStorage.getAllKeys(); 52 | const keysToRemove = allKeys.filter(key => key.indexOf(`${dbName}${SEPARATOR}`) === 0 && !exclude.includes(key)); 53 | await AsyncStorage.multiRemove(keysToRemove); 54 | return true; 55 | } 56 | -------------------------------------------------------------------------------- /packages/react-native-sdk/src/storage/index.ts: -------------------------------------------------------------------------------- 1 | import { Errors } from 'kinvey-js-sdk'; 2 | import * as Memory from './memory'; 3 | import * as AsyncStorage from './asyncStorage'; 4 | 5 | export enum StorageProvider { 6 | AsyncStorage = 'AsyncStorage', 7 | Memory = 'Memory' 8 | } 9 | 10 | export function getStorageAdapter(storageProvider = StorageProvider.AsyncStorage) { 11 | if (storageProvider === StorageProvider.Memory) { 12 | return Memory; 13 | } 14 | if (storageProvider === StorageProvider.AsyncStorage) { 15 | return AsyncStorage; 16 | } 17 | 18 | throw new Errors.KinveyError(`Please specify 'storage' option. Supported values are: ${Object.values(StorageProvider)}.`); 19 | } 20 | -------------------------------------------------------------------------------- /packages/react-native-sdk/src/storage/memory.ts: -------------------------------------------------------------------------------- 1 | const store = new Map>(); 2 | 3 | function getTable(dbName: string, tableName: string) { 4 | return store.get(`${dbName}.${tableName}`) || new Map(); 5 | } 6 | 7 | function setTable(dbName: string, tableName: string, table: Map) { 8 | return store.set(`${dbName}.${tableName}`, table); 9 | } 10 | 11 | export async function find(dbName: string, tableName: string) { 12 | const table = getTable(dbName, tableName); 13 | return Array.from(table.values()); 14 | } 15 | 16 | export async function count(dbName: string, tableName: string) { 17 | const docs = await find(dbName, tableName); 18 | return docs.length; 19 | } 20 | 21 | export async function findById(dbName: string, tableName: string, id: string) { 22 | const docs = await find(dbName, tableName); 23 | return docs.find((doc: any) => doc._id === id); 24 | } 25 | 26 | export async function save(dbName: string, tableName: string, docs: any = []) { 27 | const table = getTable(dbName, tableName); 28 | docs.forEach((doc: { _id: string }) => { 29 | table.set(doc._id, doc); 30 | }); 31 | setTable(dbName, tableName, table); 32 | return docs; 33 | } 34 | 35 | export async function removeById(dbName: string, tableName: string, id: string) { 36 | const table = getTable(dbName, tableName); 37 | if (table.delete(id)) { 38 | setTable(dbName, tableName, table); 39 | return 1; 40 | } 41 | return 0; 42 | } 43 | 44 | export async function clear(dbName: string, tableName: string) { 45 | store.delete(`${dbName}.${tableName}`); 46 | return true; 47 | } 48 | 49 | export async function clearDatabase() { 50 | store.clear(); 51 | return true; 52 | } 53 | -------------------------------------------------------------------------------- /packages/react-native-sdk/tsconfig.jest.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./tsconfig", 3 | "compilerOptions": { 4 | "jsx": "react", 5 | "module": "commonjs" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/react-native-sdk/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "declaration": true, 4 | "esModuleInterop": true, 5 | "moduleResolution": "node", 6 | "sourceMap": true, 7 | "target": "es5", 8 | "lib": [], 9 | "outDir": "lib", 10 | "resolveJsonModule": true, 11 | "downlevelIteration": true 12 | }, 13 | "exclude": ["node_modules", "src/**/__tests__", "test", "demo"] 14 | } 15 | -------------------------------------------------------------------------------- /tests/integration/clean.js: -------------------------------------------------------------------------------- 1 | const os = require('os'); 2 | const axios = require('axios'); 3 | const async = require('async'); 4 | const argv = require('yargs').argv; 5 | const { callbackify } = require('util'); 6 | const { login } = require('./shared'); 7 | 8 | let target = argv.target; 9 | if (process.env.CIRRUS_BRANCH) { 10 | target += `-${process.env.CIRRUS_BRANCH}`; 11 | } else { 12 | target += `-${os.hostname()}`; 13 | } 14 | 15 | 16 | function deleteEntitiesOneByOne(entityPath, items) { 17 | return Promise.all(items.map(item => { 18 | return new Promise(resolve => 19 | setTimeout(() => { 20 | return axios({ 21 | method: 'DELETE', 22 | url: `/${entityPath}/${item.id}`, 23 | }) 24 | .then(resolve) 25 | .catch((err) => console.error(err.message)); 26 | }, 500 * items.indexOf(item))); 27 | })); 28 | } 29 | 30 | function getApps() { 31 | return axios({ 32 | method: 'GET', 33 | url: '/apps', 34 | }).then(({ data }) => { 35 | return data.filter(app => app.name.startsWith(`JSSDK-${target}`) && app.organizationId === process.env.TEST_ORG_ID); 36 | }).catch((err) => { 37 | console.error(err.response.data); 38 | }); 39 | } 40 | 41 | function getAuthServices() { 42 | return axios({ 43 | method: 'GET', 44 | url: '/auth-services', 45 | }).then(({ data }) => { 46 | return data.filter(i => i.name.startsWith(`JSSDK-${target}`)); 47 | }).catch((err) => { 48 | console.error(err.response.data); 49 | }); 50 | } 51 | 52 | function getIdentityStores() { 53 | return axios({ 54 | method: 'GET', 55 | url: '/identity-stores', 56 | }).then(({ data }) => { 57 | return data.filter(i => i.name.startsWith(`JSSDK-${target}`)); 58 | }).catch((err) => { 59 | console.error(err.response.data); 60 | }); 61 | } 62 | 63 | 64 | async.waterfall([ 65 | callbackify(login), 66 | callbackify(getApps), 67 | callbackify(async.apply(deleteEntitiesOneByOne, 'apps')), 68 | callbackify(getAuthServices), 69 | callbackify(async.apply(deleteEntitiesOneByOne, 'auth-services')), 70 | callbackify(getIdentityStores), 71 | callbackify(async.apply(deleteEntitiesOneByOne, 'identity-stores')) 72 | ]); 73 | -------------------------------------------------------------------------------- /tests/integration/copy-specs.js: -------------------------------------------------------------------------------- 1 | const argv = require('yargs').argv; 2 | const fs = require('fs-extra'); 3 | const path = require('path'); 4 | const glob = require('glob-promise'); 5 | const babel = require('@babel/core'); 6 | require('dotenv').config({ path: path.join(__dirname, '.env') }); 7 | 8 | if (!argv.target) { 9 | throw new Error('Required parameter "--target" missing.'); 10 | } 11 | 12 | const SPECS_DIR = path.join(__dirname, './specs'); 13 | const TEST_DIR = path.join(__dirname, `./${argv.target}/test`); 14 | 15 | function build(file) { 16 | let singular = false; 17 | let files = file; 18 | 19 | if (!Array.isArray(file)) { 20 | singular = true; 21 | files = [file]; 22 | } 23 | 24 | return Promise 25 | .all(files.map(function (file) { 26 | return babel.transformFileAsync(file); 27 | })) 28 | .then(function (results) { 29 | return singular ? results[0] : results; 30 | }); 31 | } 32 | 33 | function copy(files) { 34 | return build(files) 35 | .then(function (results) { 36 | return Promise.all(results 37 | .map(function (result) { 38 | result.code = result.code.replace('__SDK__', `kinvey-${argv.target}-sdk`); 39 | 40 | if (argv.runner === 'jest') { 41 | // Adjust mocha-style `before`s to jest syntax 42 | result.code = result.code.replace(/before\(/g, 'beforeAll('); 43 | result.code = result.code.replace(/after\(/g, 'afterAll('); 44 | } 45 | 46 | return result; 47 | }) 48 | .map(function (result) { 49 | const filePath = path.join(TEST_DIR, result.options.filename.replace(SPECS_DIR, '')); 50 | return fs.outputFile(filePath, result.code); 51 | })); 52 | }); 53 | } 54 | 55 | fs.remove(TEST_DIR) 56 | .then(() => { 57 | return [] 58 | .concat(glob.sync(path.join(SPECS_DIR, '*.js'))) 59 | .concat(glob.sync(path.join(SPECS_DIR, 'common/**/*.js'))) 60 | .concat(glob.sync(path.join(SPECS_DIR, `${argv.target}/**/*.js`))); 61 | }) 62 | .then((files) => copy(files)) 63 | .catch(function (error) { 64 | console.log(error); 65 | }); 66 | -------------------------------------------------------------------------------- /tests/integration/html5/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .idea 3 | .DS_Store 4 | *.log 5 | node_modules 6 | lib 7 | .env 8 | src 9 | test 10 | -------------------------------------------------------------------------------- /tests/integration/html5/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | const presets = [ 5 | ['@babel/env', { 6 | "targets": { 7 | "chrome": "84", 8 | }, 9 | corejs: '3', 10 | useBuiltIns: 'usage' 11 | }] 12 | ]; 13 | const plugins = [ 14 | '@babel/plugin-transform-runtime', 15 | 'transform-inline-environment-variables' 16 | ]; 17 | 18 | return { 19 | presets, 20 | plugins 21 | }; 22 | } 23 | -------------------------------------------------------------------------------- /tests/integration/html5/mocha.opts: -------------------------------------------------------------------------------- 1 | --timeout 999999 2 | --colors 3 | -------------------------------------------------------------------------------- /tests/integration/html5/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "kinvey-html5-integration-tests", 4 | "description": "Integration tests for kinvey-html5-sdk.", 5 | "version": "0.0.16", 6 | "scripts": { 7 | "symlink-js-sdk": "symlink-dir ../../../packages/js-sdk ../../../packages/node_modules/kinvey-js-sdk", 8 | "build-js-sdk": "cd ../../../packages/js-sdk && npm run build", 9 | "build": "cd ../../../packages/html5-sdk/ && npm i --no-audit && rimraf node_modules/kinvey-js-sdk && npm run build", 10 | "pretest": "npm run symlink-js-sdk && npm run build-js-sdk && npm run build && OFFLINE_STORAGE=WebSQL node ../setup.js --target=html5 && node ../copy-specs.js --target=html5", 11 | "test": "karma start karma.conf.js --browsers=ChromeHeadless_without_security || (npm run posttest && exit 1)", 12 | "test-debug": "npm run pretest && karma start karma.conf.js --browsers=Chrome_without_security --single-run=false; npm run posttest", 13 | "posttest": "node ../clean.js --target=html5" 14 | }, 15 | "dependencies": {}, 16 | "devDependencies": { 17 | "@babel/core": "~7.4.3", 18 | "@babel/plugin-transform-runtime": "~7.4.3", 19 | "@babel/preset-env": "~7.4.3", 20 | "@babel/runtime": "~7.4.3", 21 | "axios": "~0.19.0", 22 | "babel-plugin-transform-inline-environment-variables": "~0.4.3", 23 | "chai": "~4.2.0", 24 | "core-js": "^3.0.1", 25 | "buffer": "6.0.3", 26 | "dotenv": "~7.0.0", 27 | "idb": "~4.0.4", 28 | "karma": "6.3.19", 29 | "karma-chrome-launcher": "~2.2.0", 30 | "karma-mocha": "~1.3.0", 31 | "karma-mocha-reporter": "~2.2.5", 32 | "karma-webpack": "5.0.0", 33 | "mocha": "~6.0.2", 34 | "rimraf": "~3.0.2", 35 | "sinon": "~7.3.1", 36 | "symlink-dir": "~4.0.3", 37 | "webpack": "5.72.0" 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /tests/integration/html5/webpack.config.js: -------------------------------------------------------------------------------- 1 | const webpack = require('webpack'); 2 | 3 | module.exports = { 4 | // Source maps support ('inline-source-map' also works) 5 | devtool: 'source-map', 6 | mode: "development", 7 | optimization: { 8 | minimize: false 9 | }, 10 | resolve: { 11 | fallback: { 12 | buffer: require.resolve('buffer/'), 13 | }, 14 | }, 15 | plugins: [ 16 | new webpack.ProvidePlugin({ 17 | Buffer: ['buffer', 'Buffer'], 18 | }), 19 | ], 20 | stats: { 21 | errorDetails: true, 22 | }, 23 | }; 24 | -------------------------------------------------------------------------------- /tests/integration/nativescript/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .idea 3 | .DS_Store 4 | *.log 5 | node_modules 6 | lib 7 | .env 8 | src 9 | TestApp 10 | -------------------------------------------------------------------------------- /tests/integration/nativescript/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | const presets = [ 5 | ['@babel/env', { 6 | corejs: '3', 7 | useBuiltIns: 'usage' 8 | }] 9 | ]; 10 | const plugins = [ 11 | '@babel/plugin-transform-runtime', 12 | 'transform-inline-environment-variables' 13 | ]; 14 | 15 | return { 16 | presets, 17 | plugins 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /tests/integration/nativescript/mocha.opts: -------------------------------------------------------------------------------- 1 | --timeout 999999 2 | --colors 3 | -------------------------------------------------------------------------------- /tests/integration/nativescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "kinvey-nativescript-integration-tests", 4 | "description": "Integration tests for kinvey-nativescript-sdk.", 5 | "version": "0.0.16", 6 | "scripts": { 7 | "symlink-js-sdk": "symlink-dir ../../../packages/js-sdk ../../../packages/node_modules/kinvey-js-sdk", 8 | "build-js-sdk": "cd ../../../packages/js-sdk && npm run build", 9 | "build": "cd ../../../packages/nativescript-sdk/ && npm i --no-audit && rimraf node_modules/kinvey-js-sdk && npm run build", 10 | "pretest": "npm run symlink-js-sdk && npm run build-js-sdk && npm run build && node ../setup.js --target=nativescript && node scripts/test.js --clean", 11 | "test": "npm run test:ios && npm run test:android", 12 | "test-android": "npm run pretest && npm run test:android && npm run posttest", 13 | "test-ios": "npm run pretest && npm run test:ios && npm run posttest", 14 | "test:android": "cd TestApp && tns test android && cd ... || (npm run posttest && exit 1)", 15 | "test:ios": "cd TestApp && tns platform add ios@8.2.2 && npm i nativescript@8.3.3 && node_modules/nativescript/bin/tns test ios && cd .. || (npm run posttest && exit 1)", 16 | "test:android-with-test-script": "node scripts/test.js && npm run test:android", 17 | "test:ios-with-test-script": "node scripts/test.js && npm run test:ios", 18 | "posttest": "node ../clean.js --target=nativescript" 19 | }, 20 | "dependencies": { 21 | "nativescript": "7.0.11" 22 | }, 23 | "devDependencies": { 24 | "@babel/core": "~7.4.3", 25 | "@babel/plugin-transform-runtime": "~7.4.3", 26 | "@babel/preset-env": "~7.4.3", 27 | "@babel/runtime": "~7.4.3", 28 | "axios": "~0.19.0", 29 | "babel-plugin-transform-inline-environment-variables": "~0.4.3", 30 | "chai": "~4.2.0", 31 | "chalk": "~2.4.2", 32 | "core-js": "~3.0.1", 33 | "cross-spawn": "~6.0.5", 34 | "del": "~4.1.0", 35 | "dotenv": "~7.0.0", 36 | "fs-extra": "~7.0.1", 37 | "glob": "~7.1.3", 38 | "rimraf": "~3.0.2", 39 | "sinon": "~7.3.1", 40 | "symlink-dir": "~4.0.3", 41 | "webpack": "~4.30.0", 42 | "webpack-node-externals": "~1.7.2", 43 | "yargs": "^15.3.1" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /tests/integration/nativescript/scripts/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 24 | 25 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /tests/integration/nativescript/scripts/app.gradle: -------------------------------------------------------------------------------- 1 | android { 2 | defaultConfig { 3 | minSdkVersion 18 4 | generatedDensities = [] 5 | } 6 | aaptOptions { 7 | additionalParameters "--no-version-vectors" 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /tests/integration/nativescript/scripts/fix-nativescript-build-xcconfig.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const filePath = path.join(__dirname, '..', '..', 'platforms', 'ios', 'internal', 'nativescript-build.xcconfig'); 4 | if (fs.existsSync(filePath)) { 5 | fs.appendFile(filePath, '\nVALIDATE_WORKSPACE = YES', function (err) { 6 | if (err) { 7 | throw err; 8 | } 9 | console.log('Modified successfully nativescript-build.xcconfig...'); 10 | }); 11 | } 12 | -------------------------------------------------------------------------------- /tests/integration/nativescript/scripts/nativescript.config.ts: -------------------------------------------------------------------------------- 1 | import { NativeScriptConfig } from '@nativescript/core'; 2 | 3 | export default { 4 | id: 'org.nativescript.TestApp', 5 | appResourcesPath: 'App_Resources', 6 | android: { 7 | v8Flags: '--expose_gc', 8 | markingMode: 'none' 9 | } 10 | } as NativeScriptConfig; 11 | -------------------------------------------------------------------------------- /tests/integration/nativescript/webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const glob = require('glob'); 3 | 4 | const appName = 'TestApp'; 5 | const rootPath = path.join(__dirname); 6 | const appPath = path.join(rootPath, appName); 7 | const appTestsPath = path.join(appPath, '/app/tests'); 8 | const tmpPath = path.join(rootPath, 'tmp'); 9 | 10 | module.exports = { 11 | mode: 'development', 12 | entry: function () { 13 | return glob.sync(path.resolve(tmpPath, '**/*.spec.js')).reduce((entries, testFile) => { 14 | const basename = path.basename(testFile); 15 | entries[basename] = testFile; 16 | return entries; 17 | }, {}) 18 | }, 19 | output: { 20 | path: appTestsPath, 21 | filename: '[name].js', 22 | libraryTarget: 'umd' 23 | }, 24 | externals: [ 25 | 'kinvey-nativescript-sdk', 26 | 'kinvey-js-sdk', 27 | '@nativescript/core', 28 | 'nativescript' 29 | ], 30 | target: 'node', 31 | optimization: { 32 | minimize: false 33 | }, 34 | } 35 | -------------------------------------------------------------------------------- /tests/integration/node/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .idea 3 | .DS_Store 4 | *.log 5 | node_modules 6 | lib 7 | .env 8 | src 9 | test 10 | -------------------------------------------------------------------------------- /tests/integration/node/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = function (api) { 2 | api.cache(true); 3 | 4 | const presets = [ 5 | ['@babel/env', { 6 | corejs: '3', 7 | useBuiltIns: 'usage' 8 | }] 9 | ]; 10 | const plugins = [ 11 | '@babel/plugin-transform-runtime', 12 | 'transform-inline-environment-variables' 13 | ]; 14 | 15 | return { 16 | presets, 17 | plugins 18 | }; 19 | } 20 | -------------------------------------------------------------------------------- /tests/integration/node/mocha.opts: -------------------------------------------------------------------------------- 1 | --timeout 60000 2 | --colors 3 | -------------------------------------------------------------------------------- /tests/integration/node/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "kinvey-node-integration-tests", 4 | "description": "Integration tests for kinvey-nodejs-sdk.", 5 | "version": "0.0.16", 6 | "scripts": { 7 | "symlink-js-sdk": "symlink-dir ../../../packages/js-sdk ../../../packages/node_modules/kinvey-js-sdk", 8 | "build-js-sdk": "cd ../../../packages/js-sdk && npm run build", 9 | "build-with-local-js-sdk": "cd ../../../packages/node-sdk/ && npm i --no-audit && rimraf node_modules/kinvey-js-sdk && npm run build", 10 | "build": "cd ../../../packages/node-sdk/ && npm i --no-audit && npm run build", 11 | "pretest": "npm run build && node ../setup.js --target=node && node ../copy-specs.js --target=node", 12 | "pretest:local-js-sdk": "npm run symlink-js-sdk && npm run build-js-sdk && npm run build && node ../setup.js --target=node && node ../copy-specs.js --target=node", 13 | "test": "mocha --opts mocha.opts \"test/**/*.spec.js\" || (npm run posttest && exit 1)", 14 | "test-debug": "npm run pretest && mocha --opts mocha.opts \"test/**/*.spec.js\"", 15 | "posttest": "node ../clean.js --target=node" 16 | }, 17 | "dependencies": {}, 18 | "devDependencies": { 19 | "@babel/core": "~7.4.3", 20 | "@babel/plugin-transform-runtime": "~7.4.3", 21 | "@babel/preset-env": "~7.4.3", 22 | "@babel/runtime": "~7.4.3", 23 | "axios": "~0.19.0", 24 | "babel-plugin-transform-inline-environment-variables": "~0.4.3", 25 | "chai": "~4.2.0", 26 | "core-js": "^3.0.1", 27 | "dotenv": "~7.0.0", 28 | "mocha": "~6.0.2", 29 | "rimraf": "~3.0.2", 30 | "sinon": "~7.3.1", 31 | "symlink-dir": "~4.0.3" 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /tests/integration/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "kinvey-integration-tests", 4 | "devDependencies": { 5 | "@babel/core": "7.14.3", 6 | "async": "3.2.0", 7 | "axios": "~0.19.0", 8 | "chai-as-promised": "7.1.1", 9 | "dotenv": "~7.0.0", 10 | "fs-extra": "10.0.0", 11 | "glob": "7.1.7", 12 | "glob-promise": "3.4.0", 13 | "totp.js": "0.0.1", 14 | "yargs": "^15.3.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /tests/integration/react-native/.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .idea 3 | .DS_Store 4 | *.log 5 | node_modules 6 | lib 7 | .env 8 | src 9 | test 10 | -------------------------------------------------------------------------------- /tests/integration/react-native/babel.config.json: -------------------------------------------------------------------------------- 1 | { 2 | "retainLines": true, 3 | "presets": [ 4 | "module:metro-react-native-babel-preset" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /tests/integration/react-native/jest.setup.ts: -------------------------------------------------------------------------------- 1 | import dotenv from 'dotenv'; 2 | import mockAsyncStorage from '@react-native-async-storage/async-storage/jest/async-storage-mock'; 3 | 4 | // Init environment 5 | dotenv.config({ path: '../.env' }); 6 | 7 | // Setup mocks 8 | jest.mock('@react-native-async-storage/async-storage', () => mockAsyncStorage); 9 | 10 | jest.mock('@react-native-community/push-notification-ios', () => ({ 11 | addEventListener: jest.fn(), 12 | requestPermissions: jest.fn(() => Promise.resolve()), 13 | getInitialNotification: jest.fn(() => Promise.resolve()) 14 | })); 15 | 16 | const mockSecureStore = new Map(); 17 | 18 | jest.mock('react-native-keychain', () => ({ 19 | SECURITY_LEVEL_ANY: "MOCK_SECURITY_LEVEL_ANY", 20 | SECURITY_LEVEL_SECURE_SOFTWARE: "MOCK_SECURITY_LEVEL_SECURE_SOFTWARE", 21 | SECURITY_LEVEL_SECURE_HARDWARE: "MOCK_SECURITY_LEVEL_SECURE_HARDWARE", 22 | setGenericPassword: async (key, value) => { 23 | mockSecureStore.set(key, value); 24 | return true; 25 | }, 26 | getGenericPassword: async ({ service }) => { 27 | return { password: mockSecureStore.get(service) }; 28 | }, 29 | resetGenericPassword: async ({ service }) => mockSecureStore.delete(service), 30 | })); 31 | -------------------------------------------------------------------------------- /tests/integration/react-native/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kinvey-react-native-integration-tests", 3 | "description": "Integration tests for kinvey-react-native-sdk.", 4 | "version": "0.0.1", 5 | "scripts": { 6 | "build": "cd ../../../packages/react-native-sdk/ && npm i --no-audit && npm run build", 7 | "pretest": "npm run build && node ../setup.js --target=react-native && node ../copy-specs.js --target=react-native --runner=jest", 8 | "test": "jest -i", 9 | "posttest": "node ../clean.js --target=react-native", 10 | "test-debug": "jest -i --testMatch '**/autostore.spec.js'" 11 | }, 12 | "dependencies": {}, 13 | "devDependencies": { 14 | "@babel/core": "7.14.3", 15 | "@babel/runtime": "7.14.0", 16 | "@react-native-async-storage/async-storage": "1.15.4", 17 | "@react-native-community/push-notification-ios": "1.8.0", 18 | "babel-jest": "27.0.2", 19 | "chai": "4.3.4", 20 | "dotenv": "7.0.0", 21 | "jest": "26.6.3", 22 | "jest-progress-bar-reporter": "1.0.21", 23 | "metro-react-native-babel-preset": "0.66.0", 24 | "react": "17.0.1", 25 | "react-native": "0.64.1", 26 | "react-native-keychain": "7.0.0", 27 | "react-native-push-notification": "7.3.1", 28 | "sinon": "10.0.0" 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /tests/integration/shared.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const axios = require('axios'); 4 | const totp = require('totp.js'); 5 | 6 | const envPath = path.join(__dirname, '.env'); 7 | if (fs.existsSync(envPath)) { 8 | require('dotenv').config({ path: envPath }); 9 | } 10 | 11 | axios.defaults.baseURL = 'https://console.kinvey.com/_api/v4/'; 12 | axios.defaults.headers.post['Content-Type'] = 'application/json'; 13 | 14 | function login(retries=3) { 15 | const twoFactorToken = process.env.ACCOUNT_SECRET ? new totp(process.env.ACCOUNT_SECRET).genOTP() : undefined; 16 | return axios({ 17 | method: 'POST', 18 | url: '/session', 19 | data: { 20 | email: process.env.ACCOUNT_EMAIL, 21 | password: process.env.ACCOUNT_PASSWORD, 22 | twoFactorToken 23 | }, 24 | }).then(({ data }) => { 25 | axios.defaults.headers.common['Authorization'] = `Kinvey ${data.token}`; 26 | return data; 27 | }).catch((err) => { 28 | console.error(err.response.data); 29 | return login(--retries); 30 | }) 31 | } 32 | 33 | module.exports = { 34 | login 35 | }; 36 | -------------------------------------------------------------------------------- /tests/integration/specs/config.js: -------------------------------------------------------------------------------- 1 | export const collectionName = 'Books'; 2 | export const deltaCollectionName = 'BooksDelta'; 3 | export const secondDeltaCollectioName = 'NewsDelta'; 4 | export const fbEmail = process.env.FACEBOOK_EMAIL; 5 | export const fbPassword = process.env.FACEBOOK_PASSWORD; 6 | export const authServiceId = 'af8e35a15aba4c369de921cc9d837e96'; 7 | export const wrongSetupAuthServiceId = '82c61e6711e547e69ea5153cbe9bb854'; 8 | -------------------------------------------------------------------------------- /tests/integration/specs/constants.js: -------------------------------------------------------------------------------- 1 | export const TextFieldName = 'textField'; 2 | export const NumberFieldName = 'numberField'; 3 | export const ArrayFieldName = 'arrayField'; 4 | -------------------------------------------------------------------------------- /tests/integration/specs/fixtures/test1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Kinvey/js-sdk/c41448007075d726519828d1a4f5208fe30c1d0b/tests/integration/specs/fixtures/test1.png -------------------------------------------------------------------------------- /tests/integration/specs/fixtures/test1.txt: -------------------------------------------------------------------------------- 1 | some_text1 -------------------------------------------------------------------------------- /tests/integration/specs/fixtures/test2.txt: -------------------------------------------------------------------------------- 1 | some_text2 -------------------------------------------------------------------------------- /tests/integration/specs/html5/files.spec.js: -------------------------------------------------------------------------------- 1 | import { expect } from 'chai'; 2 | import * as Kinvey from '__SDK__'; 3 | import * as utilities from '../utils'; 4 | 5 | describe('Files', function() { 6 | // this.retries(4); 7 | const stringContent = utilities.randomString(); 8 | const blob = new Blob([stringContent]); 9 | const file = new File([stringContent], utilities.randomString()); 10 | const fileRepresentations = [stringContent, blob, file]; 11 | // const arrayBuffer = utilities.ArrayBufferFromString(stringContent); 12 | // ArrayBuffer does not work currently - it should be discussed if we support it 13 | 14 | before(() => { 15 | const initProperties = { 16 | appKey: process.env.APP_KEY, 17 | appSecret: process.env.APP_SECRET, 18 | masterSecret: process.env.MASTER_SECRET 19 | }; 20 | return Kinvey.init(utilities.setOfflineProvider(initProperties, process.env.OFFLINE_STORAGE)); 21 | }); 22 | 23 | before((done) => { 24 | Kinvey.User.logout() 25 | .then(() => Kinvey.User.signup()) 26 | .then(() => done()) 27 | .catch(done); 28 | }); 29 | 30 | describe('upload()', () => { 31 | let metadata; 32 | let expectedMetadata; 33 | 34 | beforeEach((done) => { 35 | metadata = utilities.getFileMetadata(utilities.randomString()); 36 | expectedMetadata = utilities.getExpectedFileMetadata(metadata); 37 | done(); 38 | }); 39 | 40 | fileRepresentations.forEach((representation) => { 41 | it(`should upload a file by ${representation.constructor.name}`, (done) => { 42 | utilities.testFileUpload(representation, metadata, expectedMetadata, stringContent, null, done); 43 | }); 44 | }); 45 | 46 | it('should set options.timeout', (done) => { 47 | Kinvey.Files.upload(stringContent, undefined, { timeout: 1 }) 48 | .then(() => done(new Error('Should not be called'))) 49 | .catch((error) => { 50 | expect(error.message).to.contain('request timed out'); 51 | done(); 52 | }) 53 | .catch(done); 54 | }); 55 | }); 56 | }); 57 | -------------------------------------------------------------------------------- /tests/node_modules/kinvey-html5-sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kinvey-html5-sdk", 3 | "main": "../../../packages/html5-sdk/lib/index.js" 4 | } 5 | -------------------------------------------------------------------------------- /tests/node_modules/kinvey-nativescript-sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kinvey-nativescript-sdk", 3 | "main": "../../../packages/nativescript-sdk/lib/nativescript/index.js" 4 | } 5 | -------------------------------------------------------------------------------- /tests/node_modules/kinvey-node-sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kinvey-node-sdk", 3 | "main": "../../../packages/node-sdk/lib/index.js" 4 | } 5 | -------------------------------------------------------------------------------- /tests/node_modules/kinvey-react-native-sdk/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kinvey-react-native-sdk", 3 | "main": "../../../packages/react-native-sdk/lib/index.js" 4 | } 5 | -------------------------------------------------------------------------------- /tests/unit/user/utils.js: -------------------------------------------------------------------------------- 1 | export function mergeSocialIdentity(origSocialIdentity = {}, newSocialIdentity = {}) { 2 | const _origSocialIdentity = JSON.parse(JSON.stringify(origSocialIdentity)); 3 | const _newSocialIdentity = JSON.parse(JSON.stringify(newSocialIdentity)); 4 | const result = Object.keys(_newSocialIdentity).reduce((socialIdentity, identity) => { 5 | socialIdentity[identity] = Object.assign(_newSocialIdentity[identity], _origSocialIdentity[identity]); 6 | return socialIdentity; 7 | }, _newSocialIdentity); 8 | return result; 9 | } 10 | --------------------------------------------------------------------------------