├── .DS_Store ├── .gitignore ├── .gitlab-ci.yml ├── LICENSE ├── README.md ├── ci-scripts └── publish-tsdocs.sh ├── lerna.json ├── package.json ├── packages ├── .DS_Store ├── core │ ├── .editorconfig │ ├── .gitignore │ ├── .travis.yml │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── README.md │ ├── code-of-conduct.md │ ├── package.json │ ├── rollup.config.ts │ ├── src │ │ ├── Mitter.ts │ │ ├── MitterApiConfiguration.ts │ │ ├── MitterApiGateway.ts │ │ ├── MitterClientSet.ts │ │ ├── auth │ │ │ ├── interceptors-base.ts │ │ │ └── user-interceptors.ts │ │ ├── config.ts │ │ ├── constants.ts │ │ ├── custom_typings │ │ │ └── index.d.ts │ │ ├── driver-host │ │ │ └── MessagingPipelineDriverHost.ts │ │ ├── mitter-core.ts │ │ ├── models │ │ │ ├── auth │ │ │ │ ├── credentials-base.ts │ │ │ │ └── user-credentials.ts │ │ │ ├── base-types.ts │ │ │ ├── named-entities.ts │ │ │ ├── platformImplementedFeatures.ts │ │ │ └── type-matchers │ │ │ │ └── pipeline-payloads.ts │ │ ├── objects │ │ │ ├── ParticipatedChannel.ts │ │ │ ├── Users.ts │ │ │ └── mitter-objects.ts │ │ ├── services │ │ │ ├── ChannelsClient.ts │ │ │ ├── MessagesClient.ts │ │ │ ├── UserTokensClient.ts │ │ │ ├── UsersClient.ts │ │ │ ├── common.ts │ │ │ ├── constants.ts │ │ │ └── index.ts │ │ ├── specs │ │ │ └── MessagingPipelineDriver.ts │ │ └── utils │ │ │ ├── StatefulPromise.ts │ │ │ ├── index.ts │ │ │ ├── pagination │ │ │ ├── ChannelPaginationManager.ts │ │ │ ├── MessagePaginationManager.ts │ │ │ ├── PaginationInterface.ts │ │ │ └── ParticipatedChannelsPaginationManager.ts │ │ │ ├── presenceBuilder │ │ │ ├── StandardUserPresenceTypes.ts │ │ │ └── UserPresenceBuilder.ts │ │ │ ├── profileBuilder │ │ │ ├── ChannelProfileBuilder.ts │ │ │ ├── ProfileBaseBuilder.ts │ │ │ └── UserProfileBuilder.ts │ │ │ ├── response-utils.ts │ │ │ └── ui │ │ │ └── ui-utils.ts │ ├── test │ │ └── mitter-core.test.ts │ ├── tools │ │ ├── gh-pages-publish.ts │ │ └── semantic-release-prepare.ts │ ├── tsconfig.json │ ├── tslint.json │ └── yarn.lock ├── models │ ├── .editorconfig │ ├── .gitignore │ ├── .travis.yml │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── README.md │ ├── code-of-conduct.md │ ├── package.json │ ├── rollup.config.ts │ ├── src │ │ ├── accesscredential │ │ │ ├── AccessCredential.ts │ │ │ ├── AccessCredentialStub.ts │ │ │ ├── AccessKey.ts │ │ │ └── AccessSecret.ts │ │ ├── acolyte │ │ │ └── AppliedAclList.ts │ │ ├── annotations │ │ │ ├── Identifiable.ts │ │ │ ├── IdentifiableEntity.ts │ │ │ └── Identifier.ts │ │ ├── application │ │ │ ├── Application.ts │ │ │ └── properties │ │ │ │ ├── ApplicationProperty.ts │ │ │ │ ├── StandardApplicationProperty.ts │ │ │ │ ├── external │ │ │ │ ├── ServiceIntegrationProperty.ts │ │ │ │ ├── aws │ │ │ │ │ ├── AwsAccessCredentials.ts │ │ │ │ │ ├── AwsServiceIntegrationProperty.ts │ │ │ │ │ ├── AwsSnsTopicProperty.ts │ │ │ │ │ └── AwsSqsQueueProperty.ts │ │ │ │ ├── google │ │ │ │ │ ├── GoogleApiCredential.ts │ │ │ │ │ ├── GoogleCredential.ts │ │ │ │ │ ├── GoogleOAuthCredential.ts │ │ │ │ │ └── GoogleServiceAccountCredential.ts │ │ │ │ ├── messaging │ │ │ │ │ ├── MessagingProperty.ts │ │ │ │ │ └── mechanism │ │ │ │ │ │ ├── APNSProperties.ts │ │ │ │ │ │ ├── FCMProperties.ts │ │ │ │ │ │ └── MessagingMechanismProperty.ts │ │ │ │ └── oauth │ │ │ │ │ └── OAuthIntegrationProperty.ts │ │ │ │ └── outflow │ │ │ │ ├── EventBusProperty.ts │ │ │ │ └── TransactionalWebhookProperty.ts │ │ ├── commons │ │ │ └── common-models.ts │ │ ├── counts │ │ │ └── counts.ts │ │ ├── delman │ │ │ ├── chat │ │ │ │ ├── mardle-payloads.ts │ │ │ │ └── payloads.ts │ │ │ ├── delivery-endpoints.ts │ │ │ └── delman-models.ts │ │ ├── entity │ │ │ ├── EntityMetadata.ts │ │ │ └── EntityProfile.ts │ │ ├── events │ │ │ ├── central.ts │ │ │ ├── delivery-management.ts │ │ │ ├── mardle.ts │ │ │ └── media-management.ts │ │ ├── fcm │ │ │ └── fcm.ts │ │ ├── messaging │ │ │ ├── ChannelProfile.ts │ │ │ ├── Channels.ts │ │ │ ├── Commons.ts │ │ │ ├── ContextFreeMessage.ts │ │ │ ├── Messages.ts │ │ │ ├── ReservedMessageKeys.ts │ │ │ ├── Streams.ts │ │ │ └── TimelineEvents.ts │ │ ├── mitter-models.ts │ │ ├── nerif │ │ │ └── event-annotation.ts │ │ ├── requests │ │ │ └── IssuedTokens.ts │ │ ├── subscriber │ │ │ └── Subscriber.ts │ │ ├── user │ │ │ ├── Presence.ts │ │ │ ├── Profile.ts │ │ │ ├── User.ts │ │ │ ├── VerificationStatus.ts │ │ │ └── locators │ │ │ │ ├── EmailLocator.ts │ │ │ │ ├── MobileNumberLocator.ts │ │ │ │ └── UserLocator.ts │ │ ├── utils │ │ │ ├── model-types.ts │ │ │ └── ts-types.ts │ │ ├── weaver │ │ │ ├── DeliveryTarget │ │ │ │ ├── DeliveryTarget.ts │ │ │ │ ├── RegisteredDeliveryTarget.ts │ │ │ │ ├── RegisteredSubscription.ts │ │ │ │ └── StandardDeliveryTargetType.ts │ │ │ └── Subscriptions │ │ │ │ ├── MessageResolutionSubscription.ts │ │ │ │ ├── Subscriptions.ts │ │ │ │ └── UserResolutionSubscription.ts │ │ ├── web │ │ │ └── objects │ │ │ │ ├── GoogleOAuthConfig.ts │ │ │ │ └── PayloadUri.ts │ │ └── wire │ │ │ ├── MessageWireObjects.ts │ │ │ ├── TimelineEventWireObjects.ts │ │ │ └── errors.ts │ ├── test │ │ └── mitter-models.test.ts │ ├── tools │ │ ├── gh-pages-publish.ts │ │ └── semantic-release-prepare.ts │ ├── tsconfig.json │ ├── tslint.json │ └── yarn.lock ├── node │ ├── .editorconfig │ ├── .gitignore │ ├── .travis.yml │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── README.md │ ├── code-of-conduct.md │ ├── package.json │ ├── rollup.config.ts │ ├── src │ │ ├── auth │ │ │ ├── AccessKeySigner.ts │ │ │ ├── access-key-interceptor.ts │ │ │ ├── application-credentials.ts │ │ │ └── digest-objects.ts │ │ ├── config.ts │ │ ├── mitter-node.ts │ │ └── utils.ts │ ├── tsconfig.json │ ├── tslint.json │ └── yarn.lock ├── react-native │ ├── .editorconfig │ ├── .gitignore │ ├── .travis.yml │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── README.md │ ├── code-of-conduct.md │ ├── package.json │ ├── rollup.config.ts │ ├── src │ │ ├── drivers │ │ │ └── MitterFcmPipelineDriver.ts │ │ ├── kv-store │ │ │ └── kvStore.ts │ │ ├── mitter-react-native.ts │ │ ├── nativeSpecificImplementations │ │ │ └── nativeFileUploader.ts │ │ └── utils.ts │ ├── test │ │ └── mitter-react-native.test.ts │ ├── tools │ │ ├── gh-pages-publish.ts │ │ └── semantic-release-prepare.ts │ ├── tsconfig.json │ ├── tslint.json │ ├── types │ │ └── rn-fetch-blob-type.d.ts │ └── yarn.lock ├── react-scl │ ├── .editorconfig │ ├── .gitignore │ ├── .travis.yml │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── README.md │ ├── backup │ │ ├── src │ │ │ ├── !!ProducerInterface.ts │ │ │ ├── List.tsx │ │ │ ├── ListInterface.ts │ │ │ ├── MessageList.tsx │ │ │ ├── MessageListManager.tsx │ │ │ ├── Producer │ │ │ │ └── Producer.ts │ │ │ ├── ViewProducers │ │ │ │ ├── channelViewProducer.ts │ │ │ │ ├── messageViewProducer.ts │ │ │ │ └── utils.ts │ │ │ └── mitter-react-component-library.ts │ │ └── statefulSrc │ │ │ └── src │ │ │ ├── !!ProducerInterface.ts │ │ │ ├── List.tsx │ │ │ ├── ListInterface.ts │ │ │ ├── MessageList.tsx │ │ │ ├── MessageListManager.tsx │ │ │ ├── Producer │ │ │ └── Producer.ts │ │ │ ├── ViewProducers │ │ │ ├── channelViewProducer.ts │ │ │ ├── messageViewProducer.ts │ │ │ └── utils.ts │ │ │ └── mitter-react-component-library.ts │ ├── code-of-conduct.md │ ├── package.json │ ├── rollup.config.ts │ ├── src │ │ ├── !!ProducerInterface.ts │ │ ├── List.tsx │ │ ├── ListInterface.ts │ │ ├── MessageList.tsx │ │ ├── MessageListManager.tsx │ │ ├── MessageWindow.tsx │ │ ├── MessageWindowManager.tsx │ │ ├── Producer │ │ │ └── Producer.ts │ │ ├── ViewProducers │ │ │ ├── channelViewProducer.ts │ │ │ ├── messageViewProducer.ts │ │ │ └── utils.ts │ │ ├── mitter-react-component-library.ts │ │ └── utils.ts │ ├── test │ │ └── mitter-react-component-library.test.ts │ ├── tools │ │ ├── gh-pages-publish.ts │ │ └── semantic-release-prepare.ts │ ├── tsconfig.json │ ├── tslint.json │ └── yarn.lock └── web │ ├── .editorconfig │ ├── .gitignore │ ├── .travis.yml │ ├── CONTRIBUTING.md │ ├── LICENSE │ ├── README.md │ ├── code-of-conduct.md │ ├── mitter-web.iml │ ├── package.json │ ├── rollup.config.ts │ ├── src │ ├── drivers │ │ ├── WebSocketConstants.ts │ │ ├── WebSocketMessagingPipelineDriver.ts │ │ └── WebSocketStandardHeaders.ts │ ├── kv-store │ │ └── KvStore.tsx │ ├── mitter-web.ts │ └── utils.ts │ ├── test │ └── mitter-web.test.ts │ ├── tools │ ├── gh-pages-publish.ts │ └── semantic-release-prepare.ts │ ├── tsconfig.json │ ├── tslint.json │ └── yarn.lock └── yarn.lock /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mitterio/js-sdk/4f816f41604590fe77dc81030f9d342cc98ba69e/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | lerna-debug.log 3 | node_modules 4 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: mitterio/build-image:stretch-standard-gcp 2 | 3 | stages: 4 | - build 5 | - publish 6 | 7 | before_script: 8 | - source ~/.nvm/nvm.sh 9 | - nvm use 8 10 | 11 | build: 12 | stage: build 13 | script: 14 | - lerna bootstrap 15 | - lerna run build 16 | except: 17 | - /^v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$/ 18 | 19 | publish: 20 | stage: publish 21 | variables: 22 | GIT_STRATEGY: clone 23 | GIT_CHECKOUT: "false" 24 | script: 25 | - git checkout master 26 | - lerna bootstrap 27 | - git reset --hard 28 | - echo "//registry.npmjs.org/:_authToken=${NPM_AUTH_TOKEN}" >> ~/.npmrc 29 | - echo "unsafe-perm = true" >> ~/.npmrc 30 | - lerna run build 31 | - lerna publish from-package --yes --no-verify-access 32 | only: 33 | # Run only on tags with semantic versioning 34 | - /^v(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(-(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(\+[0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*)?$/ 35 | except: 36 | # And never run on branches 37 | - branches 38 | 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 mitter-io 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mitter-io javascript SDK 2 | 3 | Docs: [JavaScript SDK docs](https://docs.mitter.io/sdks/web) 4 | 5 | Master repo for all js-sdk related code. 6 | 7 | The following SDKs are available: 8 | 9 | 1. React Native 10 | 2. Web 11 | 3. node.js 12 | 13 | The following additional packages are available: 14 | 15 | 1. Models (for typescript users) 16 | 2. React SCL (standard component library for ReactJS) 17 | -------------------------------------------------------------------------------- /ci-scripts/publish-tsdocs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | exit 0 4 | 5 | rm -Rfv ~/.aws 6 | mkdir ~/.aws 7 | echo "[default]" >> ~/.aws/credentials 8 | echo "aws_access_key_id = ${S3_DOCS_PUBLISH_ACCESS_KEY}" >> ~/.aws/credentials 9 | echo "aws_secret_access_key = ${S3_DOCS_PUBLISH_ACCESS_SECRET}" >> ~/.aws/credentials 10 | 11 | yarn run s3p sync -y -u docs/ "s3://mitter-sourcedocs/tsdocs/$npm_package_name/$npm_package_version" 12 | yarn run s3p sync -y -u docs/ "s3://mitter-sourcedocs/tsdocs/$npm_package_name/latest" 13 | 14 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "npmClient": "yarn", 3 | "packages": [ 4 | "packages/*" 5 | ], 6 | "version": "0.7.6" 7 | } 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "root", 3 | "private": true, 4 | "devDependencies": { 5 | "lerna": "^3.8.0" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mitterio/js-sdk/4f816f41604590fe77dc81030f9d342cc98ba69e/packages/.DS_Store -------------------------------------------------------------------------------- /packages/core/.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 = 4 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /packages/core/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .DS_Store 5 | *.log 6 | .vscode 7 | .idea 8 | *.iml 9 | dist 10 | compiled 11 | .awcache 12 | .rpt2_cache 13 | docs 14 | .watchmanconfig 15 | -------------------------------------------------------------------------------- /packages/core/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | branches: 3 | only: 4 | - master 5 | - /^greenkeeper/.*$/ 6 | cache: 7 | yarn: true 8 | directories: 9 | - node_modules 10 | notifications: 11 | email: false 12 | node_js: 13 | - node 14 | script: 15 | - npm run test:prod && npm run build 16 | after_success: 17 | - npm run report-coverage 18 | - npm run deploy-docs 19 | - npm run semantic-release 20 | -------------------------------------------------------------------------------- /packages/core/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/core/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 <> 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /packages/core/README.md: -------------------------------------------------------------------------------- 1 | # mitter-core 2 | 3 | **Authors** 4 | 5 | Vineeth George (vineeth@mitter.io) 6 | Rohan Prabhu (rohan@mitter.io) 7 | 8 | The base functionality of mitter used across all js-like platforms. 9 | -------------------------------------------------------------------------------- /packages/core/code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at alexjovermorales@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /packages/core/rollup.config.ts: -------------------------------------------------------------------------------- 1 | import resolve from 'rollup-plugin-node-resolve' 2 | import commonjs from 'rollup-plugin-commonjs' 3 | import sourceMaps from 'rollup-plugin-sourcemaps' 4 | import camelCase from 'lodash.camelcase' 5 | import typescript from 'rollup-plugin-typescript2' 6 | import json from 'rollup-plugin-json' 7 | import builtins from 'rollup-plugin-node-builtins' 8 | import globals from 'rollup-plugin-node-globals' 9 | 10 | const pkg = require('./package.json') 11 | 12 | const libraryName = 'mitter-core' 13 | 14 | export default { 15 | input: `src/${libraryName}.ts`, 16 | output: [ 17 | { file: pkg.main, name: camelCase(libraryName), format: 'umd', sourcemap: true }, 18 | { file: pkg.module, format: 'es', sourcemap: true }, 19 | ], 20 | // Indicate here external modules you don't wanna include in your bundle (i.e.: 'lodash') 21 | external: [ 22 | 'websocket', 23 | 'axios', 24 | 'sockjs-client', 25 | 'query-string', 26 | 'nanoid' 27 | ], 28 | watch: { 29 | include: ['src/**', 'node_modules'] 30 | }, 31 | plugins: [ 32 | // Allow json resolution 33 | json(), 34 | commonjs({ 35 | ignoreGlobals: true 36 | }), 37 | globals(), 38 | builtins(), 39 | // Allow node_modules resolution, so you can use 'external' to control 40 | // Compile TypeScript files 41 | typescript({ useTsconfigDeclarationDir: true }), 42 | // Allow bundling cjs modules (unlike webpack, rollup doesn't understand cjs) 43 | resolve(), 44 | // which external modules to include in the bundle 45 | // https://github.com/rollup/rollup-plugin-node-resolve#usage 46 | 47 | // Resolve source maps to the original source 48 | sourceMaps(), 49 | ], 50 | } 51 | -------------------------------------------------------------------------------- /packages/core/src/MitterApiConfiguration.ts: -------------------------------------------------------------------------------- 1 | import { AxiosInstance } from 'axios' 2 | import { GenericInterceptor } from './auth/interceptors-base' 3 | 4 | export class MitterApiConfiguration { 5 | constructor( 6 | public genericInterceptor: GenericInterceptor, 7 | public mitterApiBaseUrl: string, 8 | /* Should pass a generic interceptor, clients should not know the interceptor being used */ 9 | public enableAxiosInterceptor: (axiosInstance: AxiosInstance) => void, 10 | public disableAxiosInterceptor?: (axiosInstance: AxiosInstance) => void 11 | ) {} 12 | } 13 | -------------------------------------------------------------------------------- /packages/core/src/MitterClientSet.ts: -------------------------------------------------------------------------------- 1 | import { MitterApiConfiguration } from './MitterApiConfiguration' 2 | import { PlatformImplementedFeatures } from './models/platformImplementedFeatures' 3 | import { ChannelsClient, MessagesClient, UsersClient } from './services' 4 | import { UserTokensClient } from './services/UserTokensClient' 5 | 6 | export class MitterClientSet { 7 | private cachedClients: { [clientName: string]: any } = {} 8 | private client = (clientConstructor: { 9 | new ( 10 | mitterApiConfiguration: MitterApiConfiguration, 11 | platformImplementedFeatures: PlatformImplementedFeatures 12 | ): T 13 | }): T => { 14 | if (!(clientConstructor.name in this.cachedClients)) { 15 | this.cachedClients[clientConstructor.name] = new clientConstructor( 16 | this.mitterApiConfiguration, 17 | this.platformImplementedFeatures 18 | ) 19 | } 20 | 21 | return this.cachedClients[clientConstructor.name] as T 22 | } 23 | 24 | constructor( 25 | private mitterApiConfiguration: MitterApiConfiguration, 26 | private platformImplementedFeatures: PlatformImplementedFeatures 27 | ) {} 28 | 29 | channels() { 30 | return this.client(ChannelsClient) 31 | } 32 | 33 | messages() { 34 | return this.client(MessagesClient) 35 | } 36 | 37 | users() { 38 | return this.client(UsersClient) 39 | } 40 | 41 | userAuth() { 42 | return this.client(UserTokensClient) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /packages/core/src/auth/interceptors-base.ts: -------------------------------------------------------------------------------- 1 | export interface GenericRequestParameters { 2 | data: any 3 | headers: { [headers: string]: string } 4 | method: string 5 | path: string 6 | } 7 | 8 | export interface GenericInterceptor { 9 | (requestParameters: GenericRequestParameters): void 10 | } 11 | -------------------------------------------------------------------------------- /packages/core/src/auth/user-interceptors.ts: -------------------------------------------------------------------------------- 1 | import { GenericInterceptor } from './interceptors-base' 2 | import { StandardHeaders } from '../models/named-entities' 3 | 4 | export class UserAuthorizationInterceptor { 5 | constructor( 6 | private readonly userAuthorizationFetcher: () => string | undefined, 7 | private readonly applicationId: string | undefined = undefined 8 | ) {} 9 | 10 | getInterceptor(): GenericInterceptor { 11 | return requestParams => { 12 | if (!(StandardHeaders.UserAuthorizationHeader in requestParams.headers)) { 13 | const userAuthorization = this.userAuthorizationFetcher() 14 | 15 | if (userAuthorization !== undefined) { 16 | requestParams.headers[ 17 | StandardHeaders.UserAuthorizationHeader 18 | ] = userAuthorization 19 | } 20 | 21 | if (this.applicationId !== undefined) { 22 | requestParams.headers[StandardHeaders.ApplicationIdHeader] = this.applicationId 23 | } 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/core/src/config.ts: -------------------------------------------------------------------------------- 1 | import {PickedPartial, WiredMessageResolutionSubscription} from "@mitter-io/models"; 2 | import {OperatingDeliveryTargets} from "./mitter-core"; 3 | 4 | export type TokenExpireFunction = () => void 5 | export type MessagingPipelineConnectCb = (initSubscribedChannelIds: Array, operatingDeliveryTarget?: OperatingDeliveryTargets, initialSubscription?: WiredMessageResolutionSubscription) => void 6 | export type MitterCoreConfig = { 7 | applicationId: string 8 | weaverUrl:string, 9 | mitterApiBaseUrl: string , 10 | initMessagingPipelineSubscriptions: Array, 11 | disableXHRCaching: boolean, 12 | } 13 | 14 | export type MitterUserCbs = { 15 | onTokenExpire: TokenExpireFunction[], 16 | onMessagingPipelineConnectCbs: MessagingPipelineConnectCb[], 17 | mitterInstanceReady: () => void 18 | } 19 | 20 | export type MitterUserConfig = PickedPartial 23 | -------------------------------------------------------------------------------- /packages/core/src/constants.ts: -------------------------------------------------------------------------------- 1 | export const MAX_CHANNEL_LIST_LENGTH = 45 2 | export const MAX_MESSAGE_LIST_LENGTH = 45 3 | export const CONTENT_TYPE_TEXT = 'text/plain' 4 | export const CONTENT_ENCODING_IDENTITY = 'identity' 5 | export const MULTIPART_MESSAGE_NAME_KEY = 'io.mitter.wire.requestbody' 6 | export const MULTIPART_MESSAGE_FILE_NAME = 'params.json' 7 | -------------------------------------------------------------------------------- /packages/core/src/custom_typings/index.d.ts: -------------------------------------------------------------------------------- 1 | declare module 'query-string' { 2 | const stringify: any; 3 | export default stringify; 4 | } 5 | -------------------------------------------------------------------------------- /packages/core/src/mitter-core.ts: -------------------------------------------------------------------------------- 1 | export * from './Mitter' 2 | export * from './specs/MessagingPipelineDriver' 3 | export * from './services/constants' 4 | export * from './MitterApiGateway' 5 | export * from './auth/interceptors-base' 6 | export * from './models/auth/credentials-base' 7 | export * from './models/named-entities' 8 | export * from './services' 9 | export * from './utils' 10 | export * from './models/type-matchers/pipeline-payloads' 11 | export * from './models/platformImplementedFeatures' 12 | export * from './utils/profileBuilder/ChannelProfileBuilder' 13 | export * from './utils/profileBuilder/UserProfileBuilder' 14 | export * from './constants' 15 | export * from './MitterApiConfiguration' 16 | export * from './utils/pagination/ChannelPaginationManager' 17 | export * from './utils/pagination/MessagePaginationManager' 18 | export * from './utils/pagination/ParticipatedChannelsPaginationManager' 19 | export * from './utils/pagination/PaginationInterface' 20 | export * from './utils/presenceBuilder/StandardUserPresenceTypes' 21 | export * from './utils/presenceBuilder/UserPresenceBuilder' 22 | export * from './config' 23 | 24 | export { default as MessagingPipelineDriver } from './specs/MessagingPipelineDriver' 25 | export { PlatformMitter } from './Mitter' 26 | 27 | export interface KvStore { 28 | getItem(key: string): Promise 29 | setItem(key: string, value: T): Promise 30 | clearAll?(): Promise 31 | } 32 | -------------------------------------------------------------------------------- /packages/core/src/models/auth/credentials-base.ts: -------------------------------------------------------------------------------- 1 | export interface MitterAccessCredentials {} 2 | -------------------------------------------------------------------------------- /packages/core/src/models/auth/user-credentials.ts: -------------------------------------------------------------------------------- 1 | import { MitterAccessCredentials } from './credentials-base' 2 | 3 | export interface UserCredentials extends MitterAccessCredentials { 4 | readonly userId: string 5 | } 6 | 7 | export class UserAuthorizationCredentials implements UserCredentials { 8 | constructor(public readonly userAuthorization: string, public readonly userId: string) {} 9 | } 10 | -------------------------------------------------------------------------------- /packages/core/src/models/base-types.ts: -------------------------------------------------------------------------------- 1 | export interface Identifiable { 2 | identifier: string 3 | } 4 | -------------------------------------------------------------------------------- /packages/core/src/models/named-entities.ts: -------------------------------------------------------------------------------- 1 | export const StandardHeaders = { 2 | UserAuthorizationHeader: 'X-Issued-Mitter-User-Authorization', 3 | SudoUserAuthorizationHeader: 'X-Mitter-Sudo-User-Id', 4 | ApplicationIdHeader: 'X-Mitter-Application-Id', 5 | AccessKeyHeader: 'X-Mitter-Application-Access-Key', 6 | AccessKeyAuthorizationHeader: 'Authorization' 7 | } 8 | 9 | export const RequestTimeStamp = 'requestTimeStamp' 10 | -------------------------------------------------------------------------------- /packages/core/src/models/platformImplementedFeatures.ts: -------------------------------------------------------------------------------- 1 | import { Message, ChannelReferencingMessage } from '@mitter-io/models' 2 | import { GenericRequestParameters } from '../auth/interceptors-base' 3 | import { BlobConfig, UriConfig } from '../services/MessagesClient' 4 | 5 | export interface PlatformImplementedFeatures { 6 | processMultipartRequest?: 7 | | (( 8 | requestParams: GenericRequestParameters, 9 | channelId: string, 10 | message: Message, 11 | fileObject: T 12 | ) => Promise | Error) 13 | base64Decoder?: ((encodedString: string) => string), 14 | randomIdGenerator?: () => string 15 | } 16 | -------------------------------------------------------------------------------- /packages/core/src/models/type-matchers/pipeline-payloads.ts: -------------------------------------------------------------------------------- 1 | import { 2 | NewMessagePayload, 3 | NewChannelTimelineEventPayload, 4 | ParticipationChangedEventPayload, 5 | NewChannelPayload, 6 | NewMessageTimelineEventPayload 7 | } from '@mitter-io/models' 8 | 9 | function generatePipelinePayloadMatcher(payloadType: string): (input: any) => input is T { 10 | return (input: any): input is T => { 11 | return input['@type'] !== undefined && input['@type'] === payloadType 12 | } 13 | } 14 | 15 | export const isNewMessagePayload = generatePipelinePayloadMatcher( 16 | 'new-message-payload' 17 | ) 18 | export const isNewChannelPayload = generatePipelinePayloadMatcher( 19 | 'new-channel-payload' 20 | ) 21 | 22 | export const isNewMessageTimelineEventPayload = generatePipelinePayloadMatcher< 23 | NewMessageTimelineEventPayload 24 | >('new-message-timeline-event-payload') 25 | export const isNewChannelTimelineEventPayload = generatePipelinePayloadMatcher< 26 | NewChannelTimelineEventPayload 27 | >('new-channel-timeline-event-payload') 28 | 29 | export const isParticipantChangedEventPayload = generatePipelinePayloadMatcher< 30 | ParticipationChangedEventPayload 31 | >('participation-changed-event-payload') 32 | 33 | export const isChannelStreamData = generatePipelinePayloadMatcher('stream-data') 34 | 35 | export const isPipelineControlPayload = generatePipelinePayloadMatcher('pipeline-control-payload') 36 | -------------------------------------------------------------------------------- /packages/core/src/objects/ParticipatedChannel.ts: -------------------------------------------------------------------------------- 1 | import { MitterObject } from './mitter-objects' 2 | import { ParticipatedChannel } from '@mitter-io/models' 3 | 4 | /* 5 | export default class MitterParticipatedChannel extends MitterObject< 6 | MitterParticipatedChannel, 7 | ParticipatedChannel 8 | > { 9 | get channelId() { 10 | return super.proxy('channelId') 11 | } 12 | 13 | get defaultRuleSet() { 14 | return super.proxy('defaultRuleSet') 15 | } 16 | 17 | get timelineEvents() { 18 | return super.proxy('timelineEvents') 19 | } 20 | 21 | get participation() { 22 | return super.proxy('participation') 23 | } 24 | 25 | get systemChannel() { 26 | return super.proxy('systemChannel') 27 | } 28 | 29 | get entityMetadata() { 30 | return super.proxy('entityMetadata') 31 | } 32 | 33 | get entityProfile() { 34 | return super.proxy('entityProfile') 35 | } 36 | 37 | get identifier() { 38 | return super.proxy('identifier') 39 | } 40 | } 41 | */ 42 | -------------------------------------------------------------------------------- /packages/core/src/objects/Users.ts: -------------------------------------------------------------------------------- 1 | import { User, UserLocator, AttachedProfile, EntityMetadata, AuditInfo } from '@mitter-io/models' 2 | import { TypedAxiosInstance } from 'restyped-axios' 3 | import { Mitter } from '../Mitter' 4 | import { ChannelsApi, channelsClientGenerator, UsersApi, usersClientGenerator } from '../services' 5 | import { MitterObject } from './mitter-objects' 6 | 7 | export default class MitterUser extends MitterObject { 8 | private readonly _userId: string 9 | private readonly usersClient: TypedAxiosInstance 10 | private readonly channelsClient: TypedAxiosInstance 11 | 12 | constructor(private readonly mitter: Mitter, userId: string | undefined = undefined) { 13 | super() 14 | 15 | if (userId === undefined) { 16 | this._userId = 'me' 17 | } else { 18 | this._userId = userId 19 | } 20 | 21 | this.usersClient = usersClientGenerator(this.mitter.mitterApiConfigurationProvider()) 22 | this.channelsClient = channelsClientGenerator(this.mitter.mitterApiConfigurationProvider()) 23 | 24 | super.init(() => { 25 | return this.usersClient 26 | .get<'/v1/users/:userId'>(`/v1/users/${this._userId}`) 27 | .then(x => x.data) 28 | }) 29 | } 30 | 31 | get userId(): Promise { 32 | return super.proxy('userId') 33 | } 34 | 35 | get systemUser(): Promise { 36 | return super.proxy('systemUser') 37 | } 38 | 39 | get synthetic(): Promise { 40 | return super.proxy('synthetic') 41 | } 42 | 43 | get screenName(): Promise<{ screenName: string }> { 44 | return super.proxy('screenName') 45 | } 46 | 47 | get identifier(): Promise<() => string> { 48 | return super.proxy('identifier') 49 | } 50 | 51 | get userLocators(): Promise { 52 | return super.proxy('userLocators') 53 | } 54 | 55 | get entityProfile(): Promise { 56 | return super.proxy('entityProfile') 57 | } 58 | 59 | get entityMetadata(): Promise { 60 | return super.proxy('entityMetadata') 61 | } 62 | 63 | channels() { 64 | this.channelsClient 65 | .get<'/v1/users/:userId/channels'>(`/v1/users/${this._userId}/channels`) 66 | .then(x => x.data) 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /packages/core/src/objects/mitter-objects.ts: -------------------------------------------------------------------------------- 1 | type Promsified = { [P in keyof T]: Promise } 2 | 3 | export enum FetchMode { 4 | Lazy, 5 | Eager 6 | } 7 | 8 | export abstract class MitterObject, U> { 9 | protected _ref: U | undefined 10 | private fetchCall: (() => Promise) | undefined 11 | private mode: FetchMode = FetchMode.Lazy 12 | 13 | protected init(fetchCall: () => Promise, mode: FetchMode = FetchMode.Lazy) { 14 | this.fetchCall = fetchCall 15 | this.mode = mode 16 | 17 | if (mode === FetchMode.Eager) { 18 | fetchCall().then(ref => { 19 | this._ref = ref 20 | }) 21 | } 22 | } 23 | 24 | public sync(): Promise { 25 | return this.fetchCall!().then(it => { 26 | this.setRef(it) 27 | return it 28 | }) 29 | } 30 | 31 | public setRef(ref: U) { 32 | this._ref = ref 33 | } 34 | 35 | protected proxy(key: K): Promise { 36 | if (this._ref !== undefined) { 37 | return Promise.resolve(this._ref[key]) 38 | } else { 39 | return ( 40 | this.sync() 41 | // TODO. we probably need some deadlock prevention mechanism, this can ideally 42 | // keep on going on forever 43 | .then(it => { 44 | this._ref = it 45 | return this._ref[key] 46 | }) 47 | ) 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /packages/core/src/services/UserTokensClient.ts: -------------------------------------------------------------------------------- 1 | import { IssuedUserToken } from '@mitter-io/models' 2 | import { TypedAxiosInstance } from 'restyped-axios' 3 | import { MitterApiConfiguration } from '../MitterApiConfiguration' 4 | import { PlatformImplementedFeatures } from '../models/platformImplementedFeatures' 5 | import { clientGenerator } from './common' 6 | import { MitterConstants } from './constants' 7 | 8 | const base = `${MitterConstants.Api.VersionPrefix}/users/:userId/tokens` 9 | 10 | export const UserTokensPaths = { 11 | GetMe: `${base}/me`, 12 | GetUser: `${base}/:userId`, 13 | GetMyScreenName: `${base}/me/screenname`, 14 | GetUsersScreenName: `${base}/:userIds/screenname` 15 | } 16 | 17 | export interface UserTokensApi { 18 | '/v1/users/:userId/tokens': { 19 | POST: { 20 | params: { 21 | userId: string 22 | } 23 | 24 | response: IssuedUserToken 25 | } 26 | } 27 | } 28 | 29 | export const userTokensClientGenerator = clientGenerator() 30 | 31 | export class UserTokensClient { 32 | private userTokensAxiosClient: TypedAxiosInstance 33 | 34 | constructor( 35 | private mitterApiConfiguration: MitterApiConfiguration, 36 | private platformImplementedFeatures: PlatformImplementedFeatures 37 | ) { 38 | this.userTokensAxiosClient = userTokensClientGenerator(mitterApiConfiguration) 39 | } 40 | 41 | getUserToken(userId: string): Promise { 42 | return this.userTokensAxiosClient 43 | .post<'/v1/users/:userId/tokens'>(`/v1/users/${userId}/tokens`) 44 | .then(x => x.data) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /packages/core/src/services/common.ts: -------------------------------------------------------------------------------- 1 | import { AxiosInstance } from 'axios' 2 | import axios from 'restyped-axios' 3 | import { MitterApiConfiguration } from '../MitterApiConfiguration' 4 | 5 | export function clientGenerator() { 6 | return (mitterApiConfiguration: MitterApiConfiguration) => { 7 | const client = axios.create({ 8 | baseURL: mitterApiConfiguration.mitterApiBaseUrl 9 | }) 10 | 11 | mitterApiConfiguration.enableAxiosInterceptor(client as AxiosInstance) 12 | 13 | return client 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/core/src/services/constants.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:variable-name 2 | export let MitterConstants = { 3 | // MitterApiUrl: 'https://api.mitter.io', 4 | MitterApiUrl: 'https://api.mitter.io', 5 | WeaverUrl: 'wss://weaver.mitter.io/', 6 | MitterApiStagingUrl: 'https://api.staging.mitter.io', 7 | 8 | Api: { 9 | VersionPrefix: '/v1' 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/core/src/services/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ChannelsClient' 2 | export * from './MessagesClient' 3 | export * from './UsersClient' 4 | -------------------------------------------------------------------------------- /packages/core/src/specs/MessagingPipelineDriver.ts: -------------------------------------------------------------------------------- 1 | import { Mitter } from './../mitter-core' 2 | import { 3 | AttributeDef, 4 | DeliveryEndpoint, 5 | EntityProfile, 6 | EntityProfileAttribute, 7 | Presence, 8 | User, 9 | UserLocator, 10 | AttachedEntityMetadata, 11 | EntityMetadata, 12 | QueriableMetadata, 13 | WiredPresence, 14 | DeliveryTarget, 15 | WiredDeliveryTarget, 16 | RegisteredDeliveryTarget, 17 | MessagingPipelinePayload 18 | } from '@mitter-io/models' 19 | export interface PipelineDriverSpec { 20 | name: string 21 | } 22 | 23 | export enum PipelineStatus { 24 | Connected, 25 | Unavailable, 26 | Disrupted, 27 | ConnectionInProgress 28 | } 29 | 30 | export interface PipelineDriverInitialization { 31 | pipelineDriverSpec: PipelineDriverSpec 32 | initialized: Promise 33 | } 34 | 35 | export interface BasePipelineSink { 36 | received(payload: MessagingPipelinePayload): void 37 | } 38 | 39 | export interface PipelineSink extends BasePipelineSink { 40 | deliveryTargetInvalidated(deliveryTarget: DeliveryTarget): void 41 | authorizedUserUnavailable(): void 42 | statusUpdate(newStatus: PipelineStatus): void 43 | } 44 | 45 | export default interface MessagingPipelineDriver { 46 | initialize(mitter: Mitter): PipelineDriverInitialization 47 | 48 | getDeliveryTarget(): Promise 49 | 50 | deliveryTargetRegistered(pipelineSink: PipelineSink, userDeliveryTarget: DeliveryTarget): void 51 | 52 | pipelineSinkChanged?(pipelineSink: BasePipelineSink): void 53 | 54 | halt(): void 55 | } 56 | 57 | export type OperatingDeliveryTargets = { 58 | [driverName: string]: DeliveryTarget 59 | } 60 | -------------------------------------------------------------------------------- /packages/core/src/utils/StatefulPromise.ts: -------------------------------------------------------------------------------- 1 | export interface StatefulPromise extends Promise { 2 | resolve(t?: T): void 3 | reject(e: any): void 4 | connect(promise: Promise): void 5 | } 6 | 7 | export function statefulPromise() { 8 | let _resolve: ((t?: T) => void) | undefined = undefined 9 | let _reject: ((e: any) => void) | undefined = undefined 10 | 11 | const promise = new Promise((resolve, reject) => { 12 | _resolve = resolve 13 | _reject = reject 14 | }) as StatefulPromise 15 | 16 | promise.resolve = _resolve!! 17 | promise.reject = _reject!! 18 | promise.connect = (outer: Promise) => { 19 | outer.then((t: T) => _resolve!!(t)).catch((e: any) => _reject!!(e)) 20 | } 21 | 22 | return promise 23 | } 24 | -------------------------------------------------------------------------------- /packages/core/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:no-empty 2 | export const noOp = () => {} 3 | export * from './response-utils' 4 | export * from './StatefulPromise' 5 | -------------------------------------------------------------------------------- /packages/core/src/utils/pagination/ChannelPaginationManager.ts: -------------------------------------------------------------------------------- 1 | import { Channel } from '@mitter-io/models' 2 | import { Pagination } from './PaginationInterface' 3 | 4 | export class ChannelListPaginationManager implements Pagination { 5 | before: string | undefined 6 | after: string | undefined 7 | countOffset: number | undefined 8 | 9 | constructor( 10 | private getChannelFn: (before: string | undefined, after: string | undefined, countOffset: number | undefined) => Promise, 11 | public limit: number, 12 | private paginateUsingCountOffset?: boolean, 13 | private initCountOffset?: number 14 | ) 15 | { 16 | if(this.paginateUsingCountOffset) { 17 | this.countOffset = this.initCountOffset || 0 18 | } 19 | } 20 | 21 | private updatePageDetails(channelList: Channel[], order: 'next' | 'prev') { 22 | if (channelList.length > 0) { 23 | if(!this.paginateUsingCountOffset) { 24 | if(order === 'prev') { 25 | this.before = channelList[channelList.length - 1].channelId! 26 | this.after = channelList[0].channelId! 27 | } 28 | else { 29 | this.before = channelList[0].channelId! 30 | this.after = channelList[channelList.length - 1].channelId! 31 | } 32 | } 33 | else { 34 | this.countOffset = this.countOffset! + channelList.length 35 | } 36 | 37 | } 38 | } 39 | 40 | async nextPage(): Promise { 41 | const channelList = await (this.getChannelFn( 42 | undefined, 43 | this.after, 44 | this.countOffset 45 | ) as Promise) 46 | this.updatePageDetails(channelList, 'next') 47 | return channelList 48 | } 49 | 50 | async prevPage(): Promise { 51 | let countOffset = undefined 52 | if(this.paginateUsingCountOffset) { 53 | countOffset = this.countOffset! - this.limit 54 | countOffset = countOffset < 0 ? 0 : countOffset 55 | } 56 | const channelList = await (this.getChannelFn( 57 | this.before, 58 | undefined, 59 | countOffset 60 | ) as Promise) 61 | this.updatePageDetails(channelList, 'prev') 62 | return channelList 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /packages/core/src/utils/pagination/MessagePaginationManager.ts: -------------------------------------------------------------------------------- 1 | import { Pagination } from './PaginationInterface' 2 | import { Channel, ChannelReferencingMessage } from '@mitter-io/models' 3 | 4 | export class MessagePaginationManager implements Pagination { 5 | before: string | undefined 6 | after: string | undefined 7 | 8 | constructor( 9 | private getMessages: (before: string | undefined, after: string | undefined) => Promise 10 | ) {} 11 | 12 | private updatePageDetails(messageList: ChannelReferencingMessage[], order: 'next' | 'prev') { 13 | if (messageList.length > 0) { 14 | if(order === 'prev') { 15 | this.before = messageList[messageList.length - 1].messageId 16 | this.after = messageList[0].messageId 17 | } 18 | else { 19 | this.before = messageList[0].messageId 20 | this.after = messageList[messageList.length - 1].messageId 21 | } 22 | } 23 | } 24 | 25 | async nextPage(): Promise { 26 | const messageList = await (this.getMessages( 27 | undefined, 28 | this.after, 29 | ) as Promise) 30 | this.updatePageDetails(messageList, 'next') 31 | return messageList 32 | } 33 | 34 | async prevPage(): Promise { 35 | const messageList = await (this.getMessages( 36 | this.before, 37 | undefined, 38 | ) as Promise) 39 | this.updatePageDetails(messageList, 'prev') 40 | return messageList 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /packages/core/src/utils/pagination/PaginationInterface.ts: -------------------------------------------------------------------------------- 1 | export interface Pagination { 2 | before: string | undefined 3 | after: string | undefined 4 | limit?: number | undefined 5 | nextPage(): Promise 6 | prevPage(): Promise 7 | } 8 | -------------------------------------------------------------------------------- /packages/core/src/utils/pagination/ParticipatedChannelsPaginationManager.ts: -------------------------------------------------------------------------------- 1 | import { Pagination } from './PaginationInterface' 2 | import {ParticipatedChannel} from "@mitter-io/models"; 3 | 4 | 5 | export class ParticipatedChannelsPaginationManager implements Pagination { 6 | before: string | undefined 7 | after: string | undefined 8 | countOffset: number | undefined 9 | 10 | constructor( private getChannelFn: (before: string | undefined, after: string | undefined, countOffset: number | undefined) => Promise, 11 | public limit: number, 12 | private paginateUsingCountOffset?: boolean, 13 | private initCountOffset?: number 14 | ) { 15 | if(this.paginateUsingCountOffset) { 16 | this.countOffset = this.initCountOffset || 0 17 | } 18 | } 19 | 20 | private updatePageDetails(participatedChannelList: ParticipatedChannel[], order: 'next' | 'prev') { 21 | if (participatedChannelList.length > 0) { 22 | if(!this.paginateUsingCountOffset) { 23 | if(order === 'prev') { 24 | this.before = participatedChannelList[participatedChannelList.length - 1].channel.channelId! 25 | this.after = participatedChannelList[0].channel.channelId! 26 | } 27 | else { 28 | this.before = participatedChannelList[0].channel.channelId! 29 | this.after = participatedChannelList[participatedChannelList.length - 1].channel.channelId! 30 | } 31 | } 32 | else { 33 | this.countOffset = this.countOffset! + participatedChannelList.length 34 | } 35 | } 36 | } 37 | 38 | async nextPage(): Promise { 39 | const channelList = await (this.getChannelFn( 40 | undefined, 41 | this.after, 42 | this.countOffset 43 | ) as Promise) 44 | this.updatePageDetails(channelList, 'next') 45 | return channelList 46 | } 47 | 48 | async prevPage(): Promise { 49 | let countOffset = undefined 50 | if(this.paginateUsingCountOffset) { 51 | countOffset = this.countOffset! - this.limit 52 | countOffset = countOffset < 0 ? 0 : countOffset 53 | } 54 | const channelList = await (this.getChannelFn( 55 | this.before, 56 | undefined, 57 | countOffset 58 | ) as Promise) 59 | this.updatePageDetails(channelList,'prev') 60 | return channelList 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /packages/core/src/utils/presenceBuilder/StandardUserPresenceTypes.ts: -------------------------------------------------------------------------------- 1 | import {Presence, StandardUserPresenceTypeNames} from "@mitter-io/models"; 2 | 3 | export const StandardUserPresenceTypes = { 4 | online(timeToLive: number = 0): Presence { 5 | return new Presence( 6 | StandardUserPresenceTypeNames.Online, 7 | timeToLive 8 | ) 9 | }, 10 | 11 | sleeping(timeToLive: number = 0): Presence { 12 | return new Presence( 13 | StandardUserPresenceTypeNames.Sleeping, 14 | timeToLive 15 | ) 16 | }, 17 | 18 | away(timeToLive: number = 0): Presence { 19 | return new Presence( 20 | StandardUserPresenceTypeNames.Away, 21 | timeToLive 22 | ) 23 | }, 24 | 25 | missing(timeToLive: number = 0): Presence { 26 | return new Presence( 27 | StandardUserPresenceTypeNames.Missing, 28 | timeToLive 29 | ) 30 | }, 31 | 32 | offline(timeToLive: number = 0): Presence { 33 | return new Presence( 34 | StandardUserPresenceTypeNames.Offline, 35 | timeToLive 36 | ) 37 | }, 38 | } 39 | 40 | -------------------------------------------------------------------------------- /packages/core/src/utils/presenceBuilder/UserPresenceBuilder.ts: -------------------------------------------------------------------------------- 1 | import {Presence} from "@mitter-io/models"; 2 | 3 | export class UserPresenceBuilder { 4 | private presenceList: Array = [] 5 | 6 | startWith(presence: Presence): UserPresenceBuilder { 7 | this.then(presence) 8 | return this 9 | } 10 | 11 | then(presence: Presence): UserPresenceBuilder { 12 | this.presenceList.push(presence) 13 | return this 14 | } 15 | 16 | build(): Presence { 17 | return this.presenceList.reduceRight((presence,reducedPresence) => { 18 | const copyOfReducedPresence = {...reducedPresence} 19 | const copyOfPresence = {...presence} 20 | copyOfReducedPresence.expiresTo = copyOfPresence 21 | return copyOfReducedPresence 22 | 23 | }) 24 | } 25 | } 26 | 27 | -------------------------------------------------------------------------------- /packages/core/src/utils/profileBuilder/ChannelProfileBuilder.ts: -------------------------------------------------------------------------------- 1 | import { 2 | EntityProfileAttribute, 3 | StandardChannelProfileAttributes, 4 | standardChannelProfileAttributes 5 | } from '@mitter-io/models' 6 | 7 | import ProfileBaseBuilder from './ProfileBaseBuilder' 8 | 9 | export class ChannelProfileBuilder extends ProfileBaseBuilder { 10 | private attributes: { 11 | [P in keyof StandardChannelProfileAttributes]: EntityProfileAttribute | undefined 12 | } = { 13 | displayName: undefined, 14 | description: undefined, 15 | channelIconURL: undefined, 16 | purpose: undefined 17 | } 18 | 19 | constructor() { 20 | super() 21 | } 22 | 23 | withDisplayName(displayName: string): ChannelProfileBuilder { 24 | this.attributes.displayName = this.addAttribute( 25 | standardChannelProfileAttributes.displayName, 26 | displayName 27 | ) 28 | return this 29 | } 30 | 31 | withDescription(description: string): ChannelProfileBuilder { 32 | this.attributes.description = this.addAttribute( 33 | standardChannelProfileAttributes.description, 34 | description 35 | ) 36 | return this 37 | } 38 | 39 | withChannelIconURL(channelIconURL: string): ChannelProfileBuilder { 40 | this.attributes.channelIconURL = this.addAttribute( 41 | standardChannelProfileAttributes.channelIconURL, 42 | channelIconURL 43 | ) 44 | return this 45 | } 46 | 47 | withPurpose(purpose: string): ChannelProfileBuilder { 48 | this.attributes.purpose = this.addAttribute( 49 | standardChannelProfileAttributes.purpose, 50 | purpose 51 | ) 52 | return this 53 | } 54 | 55 | buildProfile(): EntityProfileAttribute[] { 56 | for (const key in this.attributes) { 57 | if (this.attributes[key as keyof StandardChannelProfileAttributes] === undefined) { 58 | delete this.attributes[key as keyof StandardChannelProfileAttributes] 59 | } 60 | } 61 | 62 | return this.build(this.attributes) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /packages/core/src/utils/profileBuilder/ProfileBaseBuilder.ts: -------------------------------------------------------------------------------- 1 | import { EntityProfileAttribute } from '@mitter-io/models' 2 | import { CONTENT_ENCODING_IDENTITY, CONTENT_TYPE_TEXT } from '../../constants' 3 | 4 | export default abstract class ProfileBaseBuilder { 5 | public baseEntityProfile: EntityProfileAttribute 6 | 7 | protected constructor() { 8 | this.baseEntityProfile = { 9 | key: '', 10 | contentType: CONTENT_TYPE_TEXT, 11 | contentEncoding: CONTENT_ENCODING_IDENTITY, 12 | value: '' 13 | } 14 | } 15 | 16 | addAttribute(key: string, value: string): EntityProfileAttribute { 17 | return Object.assign({}, this.baseEntityProfile, { 18 | key: key, 19 | value: value 20 | }) 21 | } 22 | 23 | build(attributes: { [P in keyof T]?: EntityProfileAttribute }): EntityProfileAttribute[] { 24 | return Object.values(attributes) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /packages/core/src/utils/response-utils.ts: -------------------------------------------------------------------------------- 1 | interface ResponseError extends Error { 2 | response: Response 3 | } 4 | 5 | export function checkStatus(response: Response): Response { 6 | if (response.status >= 200 && response.status < 300) { 7 | return response 8 | } 9 | 10 | const error: Error = new Error(response.statusText) 11 | const errorResponse = { response: response } 12 | const returnErrorResponse: ResponseError = { ...error, ...errorResponse } 13 | throw returnErrorResponse 14 | } 15 | 16 | export const parseJSON = (response: Response) => response.json() 17 | -------------------------------------------------------------------------------- /packages/core/src/utils/ui/ui-utils.ts: -------------------------------------------------------------------------------- 1 | import { Message } from '@mitter-io/models' 2 | 3 | export function payloadTypeMatcher(payloadType: string): (message: Message) => number { 4 | return (message: Message): number => { 5 | if (message.payloadType === payloadType) { 6 | return 1 7 | } else { 8 | return -1 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/core/test/mitter-core.test.ts: -------------------------------------------------------------------------------- 1 | import DummyClass from "../src/mitter-core" 2 | 3 | /** 4 | * Dummy test 5 | */ 6 | describe("Dummy test", () => { 7 | it("works if true is truthy", () => { 8 | expect(true).toBeTruthy() 9 | }) 10 | 11 | it("DummyClass is instantiable", () => { 12 | expect(new DummyClass()).toBeInstanceOf(DummyClass) 13 | }) 14 | }) 15 | -------------------------------------------------------------------------------- /packages/core/tools/gh-pages-publish.ts: -------------------------------------------------------------------------------- 1 | const { cd, exec, echo, touch } = require("shelljs") 2 | const { readFileSync } = require("fs") 3 | const url = require("url") 4 | 5 | let repoUrl 6 | let pkg = JSON.parse(readFileSync("package.json") as any) 7 | if (typeof pkg.repository === "object") { 8 | if (!pkg.repository.hasOwnProperty("url")) { 9 | throw new Error("URL does not exist in repository section") 10 | } 11 | repoUrl = pkg.repository.url 12 | } else { 13 | repoUrl = pkg.repository 14 | } 15 | 16 | let parsedUrl = url.parse(repoUrl) 17 | let repository = (parsedUrl.host || "") + (parsedUrl.path || "") 18 | let ghToken = process.env.GH_TOKEN 19 | 20 | echo("Deploying docs!!!") 21 | cd("docs") 22 | touch(".nojekyll") 23 | exec("git init") 24 | exec("git add .") 25 | exec('git config user.name ""') 26 | exec('git config user.email ""') 27 | exec('git commit -m "docs(docs): update gh-pages"') 28 | exec( 29 | `git push --force --quiet "https://${ghToken}@${repository}" master:gh-pages` 30 | ) 31 | echo("Docs deployed!!") 32 | -------------------------------------------------------------------------------- /packages/core/tools/semantic-release-prepare.ts: -------------------------------------------------------------------------------- 1 | const path = require("path") 2 | const { fork } = require("child_process") 3 | const colors = require("colors") 4 | 5 | const { readFileSync, writeFileSync } = require("fs") 6 | const pkg = JSON.parse( 7 | readFileSync(path.resolve(__dirname, "..", "package.json")) 8 | ) 9 | 10 | pkg.scripts.prepush = "npm run test:prod && npm run build" 11 | pkg.scripts.commitmsg = "validate-commit-msg" 12 | 13 | writeFileSync( 14 | path.resolve(__dirname, "..", "package.json"), 15 | JSON.stringify(pkg, null, 2) 16 | ) 17 | 18 | // Call husky to set up the hooks 19 | fork(path.resolve(__dirname, "..", "node_modules", "husky", "bin", "install")) 20 | 21 | console.log() 22 | console.log(colors.green("Done!!")) 23 | console.log() 24 | 25 | if (pkg.repository.url.trim()) { 26 | console.log(colors.cyan("Now run:")) 27 | console.log(colors.cyan(" npm install -g semantic-release-cli")) 28 | console.log(colors.cyan(" semantic-release-cli setup")) 29 | console.log() 30 | console.log( 31 | colors.cyan('Important! Answer NO to "Generate travis.yml" question') 32 | ) 33 | console.log() 34 | console.log( 35 | colors.gray( 36 | 'Note: Make sure "repository.url" in your package.json is correct before' 37 | ) 38 | ) 39 | } else { 40 | console.log( 41 | colors.red( 42 | 'First you need to set the "repository.url" property in package.json' 43 | ) 44 | ) 45 | console.log(colors.cyan("Then run:")) 46 | console.log(colors.cyan(" npm install -g semantic-release-cli")) 47 | console.log(colors.cyan(" semantic-release-cli setup")) 48 | console.log() 49 | console.log( 50 | colors.cyan('Important! Answer NO to "Generate travis.yml" question') 51 | ) 52 | } 53 | 54 | console.log() 55 | -------------------------------------------------------------------------------- /packages/core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es5", 5 | "module":"es2015", 6 | "lib": ["es2015", "es2016", "es2017", "dom"], 7 | "strict": true, 8 | "sourceMap": true, 9 | "declaration": true, 10 | "allowSyntheticDefaultImports": true, 11 | "experimentalDecorators": true, 12 | "emitDecoratorMetadata": true, 13 | "declarationDir": "dist/types", 14 | "outDir": "dist/lib", 15 | "typeRoots": ["node_modules/@types", "custom_typings"] 16 | }, 17 | "include": [ 18 | "src", "../my-mitter-app/src/ChannelComponent.js" 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /packages/core/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint-config-standard", 4 | "tslint-config-prettier" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /packages/models/.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 = 4 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /packages/models/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .DS_Store 5 | *.log 6 | .vscode 7 | .idea 8 | dist 9 | compiled 10 | .awcache 11 | .rpt2_cache 12 | docs 13 | *.iml 14 | .watchmanconfig 15 | -------------------------------------------------------------------------------- /packages/models/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | branches: 3 | only: 4 | - master 5 | - /^greenkeeper/.*$/ 6 | cache: 7 | yarn: true 8 | directories: 9 | - node_modules 10 | notifications: 11 | email: false 12 | node_js: 13 | - node 14 | script: 15 | - npm run test:prod && npm run build 16 | after_success: 17 | - npm run report-coverage 18 | - npm run deploy-docs 19 | - npm run semantic-release 20 | -------------------------------------------------------------------------------- /packages/models/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/models/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 <> 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /packages/models/README.md: -------------------------------------------------------------------------------- 1 | # mitter-models 2 | 3 | Models for all mitter entities with typings for typescript. 4 | -------------------------------------------------------------------------------- /packages/models/code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at alexjovermorales@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /packages/models/rollup.config.ts: -------------------------------------------------------------------------------- 1 | import resolve from 'rollup-plugin-node-resolve' 2 | import commonjs from 'rollup-plugin-commonjs' 3 | import sourceMaps from 'rollup-plugin-sourcemaps' 4 | import camelCase from 'lodash.camelcase' 5 | import typescript from 'rollup-plugin-typescript2' 6 | import json from 'rollup-plugin-json' 7 | 8 | const pkg = require('./package.json') 9 | 10 | const libraryName = 'mitter-models' 11 | 12 | export default { 13 | input: `src/${libraryName}.ts`, 14 | output: [ 15 | { file: pkg.main, name: camelCase(libraryName), format: 'umd', sourcemap: true }, 16 | { file: pkg.module, format: 'es', sourcemap: true }, 17 | ], 18 | // Indicate here external modules you don't wanna include in your bundle (i.e.: 'lodash') 19 | external: [], 20 | watch: { 21 | include: 'src/**', 22 | }, 23 | plugins: [ 24 | // Allow json resolution 25 | json(), 26 | // Compile TypeScript files 27 | typescript({ useTsconfigDeclarationDir: true }), 28 | // Allow bundling cjs modules (unlike webpack, rollup doesn't understand cjs) 29 | commonjs(), 30 | // Allow node_modules resolution, so you can use 'external' to control 31 | // which external modules to include in the bundle 32 | // https://github.com/rollup/rollup-plugin-node-resolve#usage 33 | resolve(), 34 | 35 | // Resolve source maps to the original source 36 | sourceMaps(), 37 | ], 38 | } 39 | -------------------------------------------------------------------------------- /packages/models/src/accesscredential/AccessCredential.ts: -------------------------------------------------------------------------------- 1 | import { AccessKey } from './AccessKey' 2 | import { AccessSecret } from './AccessSecret' 3 | 4 | export class AccessCredential { 5 | constructor( 6 | public accessKey: AccessKey, 7 | public accessSecret: AccessSecret, 8 | public createdAt: number 9 | ) {} 10 | } 11 | -------------------------------------------------------------------------------- /packages/models/src/accesscredential/AccessCredentialStub.ts: -------------------------------------------------------------------------------- 1 | import { AccessKey } from './AccessKey' 2 | 3 | export class AccessCredentialStub { 4 | constructor( 5 | public accessKey: AccessKey, 6 | public lastUsed: number, 7 | public createdAt: number, 8 | public lastAction: string 9 | ) {} 10 | } 11 | -------------------------------------------------------------------------------- /packages/models/src/accesscredential/AccessKey.ts: -------------------------------------------------------------------------------- 1 | export class AccessKey { 2 | constructor(public key: string) {} 3 | } 4 | -------------------------------------------------------------------------------- /packages/models/src/accesscredential/AccessSecret.ts: -------------------------------------------------------------------------------- 1 | export class AccessSecret { 2 | constructor(public secret: string) {} 3 | } 4 | -------------------------------------------------------------------------------- /packages/models/src/acolyte/AppliedAclList.ts: -------------------------------------------------------------------------------- 1 | 2 | export interface AppliedAclList { 3 | plusAppliedAcls: string[] 4 | minusAppliedAcls: string[] 5 | } 6 | -------------------------------------------------------------------------------- /packages/models/src/annotations/Identifiable.ts: -------------------------------------------------------------------------------- 1 | interface Identifiable> { 2 | identifier(): string 3 | } 4 | 5 | export default Identifiable 6 | -------------------------------------------------------------------------------- /packages/models/src/annotations/IdentifiableEntity.ts: -------------------------------------------------------------------------------- 1 | import Identifiable from './Identifiable' 2 | 3 | interface IdentifiableEntity> extends Identifiable {} 4 | 5 | export default IdentifiableEntity 6 | -------------------------------------------------------------------------------- /packages/models/src/annotations/Identifier.ts: -------------------------------------------------------------------------------- 1 | export type Identifier = { 2 | identifier: string 3 | } 4 | -------------------------------------------------------------------------------- /packages/models/src/application/Application.ts: -------------------------------------------------------------------------------- 1 | import IdentifiableEntity from '../annotations/IdentifiableEntity' 2 | 3 | export class Application implements IdentifiableEntity { 4 | constructor(public applicationId: string, public name: string, public sandboxed: boolean) {} 5 | 6 | identifier() { 7 | return this.applicationId 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /packages/models/src/application/properties/ApplicationProperty.ts: -------------------------------------------------------------------------------- 1 | abstract class ApplicationProperty { 2 | public readonly isDefault: boolean = false 3 | 4 | // ? due to eventBusProperty 5 | protected constructor(public systemName?: string, public instanceName?: string) {} 6 | } 7 | 8 | export default ApplicationProperty 9 | -------------------------------------------------------------------------------- /packages/models/src/application/properties/StandardApplicationProperty.ts: -------------------------------------------------------------------------------- 1 | export enum StandardApplicationProperty { 2 | GoogleApiCredential = 'google-api-credential', 3 | GoogleOAuthCredential = 'google-oauth-credential', 4 | GoogleServiceAccountCredential = 'google-service-account-credential', 5 | AwsAccessCredentials = 'aws-access-credentials', 6 | ApnsProperties = 'apns-properties', 7 | FcmProperties = 'fcm-properties', 8 | OAuthIntegrationProperty = 'oauth-integration', 9 | TransactionalWebhookProperty = 'transactional-webhook', 10 | AwsSqsQueueProperty = 'aws-sqs-queue', 11 | AwsSnsTopicProperty = 'aws-sns-topic', 12 | AwsSqsEventBusProperty = 'aws-sqs-event-bus', 13 | AwsSnsEventBusProperty = 'aws-sns-event-bus', 14 | NonStandardProperty = '' 15 | } 16 | -------------------------------------------------------------------------------- /packages/models/src/application/properties/external/ServiceIntegrationProperty.ts: -------------------------------------------------------------------------------- 1 | import ApplicationProperty from '../ApplicationProperty' 2 | 3 | abstract class ServiceIntegrationProperty extends ApplicationProperty { 4 | protected constructor(public systemName: string, public instanceName: string) { 5 | super(systemName, instanceName) 6 | } 7 | } 8 | 9 | export default ServiceIntegrationProperty 10 | -------------------------------------------------------------------------------- /packages/models/src/application/properties/external/aws/AwsAccessCredentials.ts: -------------------------------------------------------------------------------- 1 | export class AwsAccessCredentials { 2 | constructor( 3 | public awsAccessKey: string, 4 | public awsAccessSecret: string | null, 5 | public awsRegion: string 6 | ) {} 7 | } 8 | -------------------------------------------------------------------------------- /packages/models/src/application/properties/external/aws/AwsServiceIntegrationProperty.ts: -------------------------------------------------------------------------------- 1 | import { AwsAccessCredentials } from './AwsAccessCredentials' 2 | 3 | export class AwsServiceIntegrationProperty { 4 | constructor(public region: string, public awsAccessCredentials: AwsAccessCredentials) {} 5 | } 6 | -------------------------------------------------------------------------------- /packages/models/src/application/properties/external/aws/AwsSnsTopicProperty.ts: -------------------------------------------------------------------------------- 1 | import { AwsServiceIntegrationProperty } from './AwsServiceIntegrationProperty' 2 | import { AwsAccessCredentials } from './AwsAccessCredentials' 3 | 4 | export class AwsSnsTopicProperty extends AwsServiceIntegrationProperty { 5 | constructor( 6 | public topicName: string, 7 | public region: string, 8 | public awsAccessCredentials: AwsAccessCredentials 9 | ) { 10 | super(region, awsAccessCredentials) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/models/src/application/properties/external/aws/AwsSqsQueueProperty.ts: -------------------------------------------------------------------------------- 1 | import { AwsServiceIntegrationProperty } from './AwsServiceIntegrationProperty' 2 | import { AwsAccessCredentials } from './AwsAccessCredentials' 3 | 4 | export class AwsSqsQueueProperty extends AwsServiceIntegrationProperty { 5 | constructor( 6 | public queueName: string, 7 | public region: string, 8 | public awsAccessCredentials: AwsAccessCredentials 9 | ) { 10 | super(region, awsAccessCredentials) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/models/src/application/properties/external/google/GoogleApiCredential.ts: -------------------------------------------------------------------------------- 1 | import GoogleCredential from './GoogleCredential' 2 | 3 | export class GoogleApiCredential extends GoogleCredential { 4 | constructor(public apiKey: string, systemName: string, instanceName: string) { 5 | super(systemName, instanceName) 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/models/src/application/properties/external/google/GoogleCredential.ts: -------------------------------------------------------------------------------- 1 | import ServiceIntegrationProperty from '../ServiceIntegrationProperty' 2 | 3 | abstract class GoogleCredential extends ServiceIntegrationProperty { 4 | public readonly projectNumber: string | undefined 5 | public readonly applicationName: string | undefined 6 | 7 | protected constructor( 8 | systemName: string, 9 | instanceName: string, 10 | projectNumber: string | undefined = undefined, 11 | applicationName: string | undefined = undefined 12 | ) { 13 | super(systemName, instanceName) 14 | } 15 | } 16 | 17 | export default GoogleCredential 18 | -------------------------------------------------------------------------------- /packages/models/src/application/properties/external/google/GoogleOAuthCredential.ts: -------------------------------------------------------------------------------- 1 | import GoogleCredential from './GoogleCredential' 2 | 3 | export class GoogleOAuthCredential extends GoogleCredential { 4 | constructor( 5 | public clientId: string, 6 | public clientSecret: string, 7 | systemName: string, 8 | instanceName: string 9 | ) { 10 | super(systemName, instanceName) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/models/src/application/properties/external/google/GoogleServiceAccountCredential.ts: -------------------------------------------------------------------------------- 1 | import GoogleCredential from './GoogleCredential' 2 | 3 | export class GoogleServiceAccountCredential extends GoogleCredential { 4 | constructor(public config: object, systemName: string, instanceName: string) { 5 | super(systemName, instanceName) 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/models/src/application/properties/external/messaging/MessagingProperty.ts: -------------------------------------------------------------------------------- 1 | import ApplicationProperty from '../../ApplicationProperty' 2 | 3 | export abstract class MessagingProperty extends ApplicationProperty { 4 | protected constructor(systemName: string, instanceName: string) { 5 | super(systemName, instanceName) 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/models/src/application/properties/external/messaging/mechanism/APNSProperties.ts: -------------------------------------------------------------------------------- 1 | import { MessagingMechanismProperty } from './MessagingMechanismProperty' 2 | 3 | export class APNSProperties extends MessagingMechanismProperty { 4 | constructor(public keyId: string, systemName: string, instanceName: string) { 5 | super(systemName, instanceName) 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/models/src/application/properties/external/messaging/mechanism/FCMProperties.ts: -------------------------------------------------------------------------------- 1 | import { MessagingMechanismProperty } from './MessagingMechanismProperty' 2 | 3 | export class FCMProperties extends MessagingMechanismProperty { 4 | constructor(public serverKey: string, systemName: string, instanceName: string) { 5 | super(systemName, instanceName) 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/models/src/application/properties/external/messaging/mechanism/MessagingMechanismProperty.ts: -------------------------------------------------------------------------------- 1 | import { MessagingProperty } from '../MessagingProperty' 2 | 3 | export class MessagingMechanismProperty extends MessagingProperty { 4 | constructor(systemName: string, instanceName: string) { 5 | super(systemName, instanceName) 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/models/src/application/properties/external/oauth/OAuthIntegrationProperty.ts: -------------------------------------------------------------------------------- 1 | import ServiceIntegrationProperty from '../ServiceIntegrationProperty' 2 | 3 | export class OAuthIntegrationProperty extends ServiceIntegrationProperty { 4 | /*/* in java it is extended but system and instance name are not passed*/ 5 | constructor( 6 | public oauthRedirectUrl: string, 7 | public requireStateSigning: boolean, 8 | systemName: string, 9 | instanceName: string 10 | ) { 11 | super(systemName, instanceName) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/models/src/application/properties/outflow/EventBusProperty.ts: -------------------------------------------------------------------------------- 1 | import ApplicationProperty from '../ApplicationProperty' 2 | import { AwsSqsQueueProperty } from '../external/aws/AwsSqsQueueProperty' 3 | import { AwsSnsTopicProperty } from '../external/aws/AwsSnsTopicProperty' 4 | 5 | class EventBusProperty extends ApplicationProperty { 6 | constructor(public active: boolean) { 7 | super() 8 | } 9 | } 10 | 11 | export class AwsSqsQueueEventBus extends EventBusProperty { 12 | constructor(public awsSqsQueueProperty: AwsSqsQueueProperty, active: boolean) { 13 | super(active) 14 | } 15 | } 16 | 17 | export class AwsSnsTopicEventBus extends EventBusProperty { 18 | constructor(public awsSnsTopicProperty: AwsSnsTopicProperty, active: boolean) { 19 | super(active) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/models/src/application/properties/outflow/TransactionalWebhookProperty.ts: -------------------------------------------------------------------------------- 1 | import ApplicationProperty from '../ApplicationProperty' 2 | 3 | export class TransactionalWebhookProperty extends ApplicationProperty { 4 | constructor(public webhookUri: string, public eventSubscriptions: Array = []) { 5 | super() 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/models/src/commons/common-models.ts: -------------------------------------------------------------------------------- 1 | export interface AuditInfo { 2 | createdAt?: number, 3 | updatedAt?: number 4 | } 5 | -------------------------------------------------------------------------------- /packages/models/src/counts/counts.ts: -------------------------------------------------------------------------------- 1 | export type WiredCount = { 2 | countClass: { 3 | name: string, 4 | subject: string 5 | }, 6 | count: number 7 | } 8 | 9 | export type WiredUserOnlineCountForChannel = { 10 | count: number 11 | } 12 | 13 | export type WiredUserOnlineCountForApplication = { 14 | count: number 15 | } 16 | -------------------------------------------------------------------------------- /packages/models/src/delman/chat/mardle-payloads.ts: -------------------------------------------------------------------------------- 1 | import { Channel, ParticipationStatus } from '../../messaging/Channels' 2 | import { TimelineEvent } from '../../messaging/TimelineEvents' 3 | import { ContextFreeMessage } from '../../messaging/ContextFreeMessage' 4 | import { MessagingPipelinePayload } from './payloads' 5 | import { Message } from '../../messaging/Messages' 6 | import { Identifier } from '../../annotations/Identifier' 7 | 8 | export enum StandardPipelinePayloadNames { 9 | NewChannelPayload = 'new-channel-payload', 10 | NewMessagePayload = 'new-message-payload', 11 | 12 | NewMessageTimelineEventPayload = 'new-message-timeline-event-payload', 13 | NewChannelTimelineEventPayload = 'new-channel-timeline-event-payload', 14 | 15 | ParticipationChangedEventPayload = 'participation-changed-event-payload', 16 | ChannelStreamData = 'stream-data', 17 | 18 | PipelineControlPayload = 'pipeline-control-payload' 19 | } 20 | 21 | export class NewChannelPayload extends MessagingPipelinePayload { 22 | constructor(public channel: Channel, globalPipelinePayloadId: string, type: string) { 23 | super(globalPipelinePayloadId, type) 24 | } 25 | } 26 | 27 | export class NewMessagePayload extends MessagingPipelinePayload { 28 | constructor( 29 | public message: Message, 30 | public channelId: Identifier, 31 | globalPipelinePayloadId: string, 32 | type: string 33 | ) { 34 | super(globalPipelinePayloadId, type) 35 | } 36 | } 37 | 38 | export class NewMessageTimelineEventPayload extends MessagingPipelinePayload { 39 | constructor( 40 | public timelineEvent: TimelineEvent, 41 | public messageId: Identifier, 42 | globalPipelinePayloadId: string, 43 | type: string 44 | ) { 45 | super(globalPipelinePayloadId, type) 46 | } 47 | } 48 | 49 | export class NewChannelTimelineEventPayload extends MessagingPipelinePayload { 50 | constructor( 51 | public timelineEvent: TimelineEvent, 52 | public channelId: string, 53 | globalPipelinePayloadId: string, 54 | type: string 55 | ) { 56 | super(globalPipelinePayloadId, type) 57 | } 58 | } 59 | 60 | export class ParticipationChangedEventPayload extends MessagingPipelinePayload { 61 | constructor( 62 | public oldStatus: ParticipationStatus, 63 | public newStatus: ParticipationStatus, 64 | public participantId: string, 65 | public channelId: Identifier, 66 | globalPipelinePayloadId: string, 67 | type: string 68 | ) { 69 | super(globalPipelinePayloadId, type) 70 | } 71 | } 72 | 73 | export class ChannelStreamData extends MessagingPipelinePayload { 74 | constructor( 75 | public channelId: string, 76 | public streamId: string, 77 | public streamData: ContextFreeMessage, 78 | globalPipelinePayloadId: string, 79 | type: string 80 | ) { 81 | super(globalPipelinePayloadId, type) 82 | } 83 | } 84 | 85 | export class PipelineControlPayload extends MessagingPipelinePayload { 86 | constructor( 87 | public errorBody: any = undefined, 88 | public allOk: boolean = false, 89 | globalPipelinePayloadId: string, 90 | type: string 91 | ) { 92 | super(globalPipelinePayloadId, type) 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /packages/models/src/delman/chat/payloads.ts: -------------------------------------------------------------------------------- 1 | export abstract class MessagingPipelinePayload { 2 | public '@type': string 3 | protected constructor(public globalPipelinePayloadId: string, type: string) { 4 | this['@type'] = type 5 | } 6 | } 7 | 8 | export class SerializedMessagePipelinePayload { 9 | constructor(public data: string) {} 10 | } 11 | -------------------------------------------------------------------------------- /packages/models/src/delman/delivery-endpoints.ts: -------------------------------------------------------------------------------- 1 | enum StandardEndpointTypes { 2 | FcmDeliveryEndpoint = 'fcm', 3 | TransactionalWebHook = 'twh', 4 | SseWebEndpoint = 'http+sse' 5 | } 6 | 7 | export abstract class DeliveryEndpoint { 8 | protected constructor( 9 | public serializedEndpoint: string, 10 | public endpointType: string, 11 | public autoExpireAt: number = Number.MAX_SAFE_INTEGER 12 | ) {} 13 | } 14 | 15 | export class FcmDeliveryEndpoint extends DeliveryEndpoint { 16 | constructor(public registrationToken: string) { 17 | super( 18 | `${StandardEndpointTypes.FcmDeliveryEndpoint}:${registrationToken}`, 19 | StandardEndpointTypes.FcmDeliveryEndpoint 20 | ) 21 | } 22 | } 23 | 24 | export class SseDeliveryEndpoint extends DeliveryEndpoint { 25 | constructor(public endpointToken: string | undefined = undefined) { 26 | super( 27 | `${StandardEndpointTypes.SseWebEndpoint}:${endpointToken}`, 28 | StandardEndpointTypes.SseWebEndpoint 29 | ) 30 | } 31 | } 32 | 33 | export class TransactionalWebHookEndPoint extends DeliveryEndpoint { 34 | constructor(public webHookUri: string) { 35 | super( 36 | `${StandardEndpointTypes.TransactionalWebHook}:${webHookUri}`, 37 | StandardEndpointTypes.TransactionalWebHook 38 | ) 39 | } 40 | } 41 | 42 | export class UserDeliveryEndPoint { 43 | constructor( 44 | public userId: string, 45 | public deliveryEndpoint: DeliveryEndpoint, 46 | public disabled: boolean = false 47 | ) {} 48 | } 49 | -------------------------------------------------------------------------------- /packages/models/src/delman/delman-models.ts: -------------------------------------------------------------------------------- 1 | enum DeliveryStatus { 2 | Success, 3 | PermanentFailure, 4 | RetryableFailure, 5 | Indeterminate 6 | } 7 | 8 | export class DeliveryResult { 9 | constructor(public deliveryStatus: DeliveryStatus) {} 10 | } 11 | -------------------------------------------------------------------------------- /packages/models/src/entity/EntityMetadata.ts: -------------------------------------------------------------------------------- 1 | export type EntityMetadata = { 2 | [key: string]: any 3 | } 4 | 5 | export type AttachedEntityMetadata = { 6 | key: string, 7 | value: { 8 | "@type": any, 9 | text: any 10 | } 11 | } 12 | 13 | export interface MetadataAttachable { 14 | entityMetadata: EntityMetadata 15 | } 16 | 17 | export type QueriableMetadata = { 18 | key: string, 19 | value: any, 20 | operator: 'Contains' | 'Equals' 21 | } 22 | -------------------------------------------------------------------------------- /packages/models/src/entity/EntityProfile.ts: -------------------------------------------------------------------------------- 1 | import { Identifier } from '../annotations/Identifier' 2 | 3 | export class EntityProfileAttribute { 4 | constructor( 5 | public key: string, 6 | public contentType: string, 7 | public contentEncoding: string, 8 | public value: string 9 | ) {} 10 | } 11 | 12 | export class EntityProfile { 13 | constructor(public entityId: Identifier, public attributes: Array) {} 14 | } 15 | 16 | export class AttachedProfile { 17 | constructor( 18 | public attributes: Array 19 | ) {} 20 | } 21 | -------------------------------------------------------------------------------- /packages/models/src/events/delivery-management.ts: -------------------------------------------------------------------------------- 1 | import { ApplicationEvent } from './central' 2 | import { DeliveryResult } from '../delman/delman-models' 3 | import Identifiable from '../annotations/Identifiable' 4 | import { User } from '../user/User' 5 | import { MessagingPipelinePayload } from '../delman/chat/payloads' 6 | 7 | export enum DeliveryManagementNames { 8 | PayloadDeliveryAttemptEvent = 'mitter.mpe.delivery.PayloadDeliveryAttempt', 9 | UserTargetDeliveryRequestedEvent = 'mitter.mpe.delivery.UserTargetDeliveryRequested', 10 | DeliveryEndpointRegisteredEvent = 'mitter.mpe.delivery.DeliveryEndpointRegistered', 11 | DeliveryEndpointUnregisteredEvent = 'mitter.mpe.delivery.DeliveryEndpointUnregistered', 12 | DeliveryEndpointTransferredEvent = 'mitter.mpe.delivery.DeliveryEndpointTransferred' 13 | } 14 | 15 | export class PayloadDeliveryAttemptEvent extends ApplicationEvent { 16 | constructor( 17 | public serializedDeliveryEndpoint: string, 18 | public deliveryResult: DeliveryResult, 19 | public payload: any, 20 | applicationId: string 21 | ) { 22 | super(applicationId) 23 | } 24 | } 25 | 26 | export class UserTargetDeliveryRequestedEvent extends ApplicationEvent { 27 | constructor( 28 | public user: Identifiable, 29 | public messagingPipelinePayload: MessagingPipelinePayload, 30 | applicationId: string 31 | ) { 32 | super(applicationId) 33 | } 34 | } 35 | 36 | export class DeliveryEndpointRegisteredEvent extends ApplicationEvent { 37 | constructor( 38 | public user: Identifiable, 39 | public deliveryEndpoint: string, 40 | applicationId: string 41 | ) { 42 | super(applicationId) 43 | } 44 | } 45 | 46 | export class DeliveryEndpointUnregisteredEvent extends ApplicationEvent { 47 | constructor( 48 | public user: Identifiable, 49 | public deliveryEndpoint: string, 50 | applicationId: string 51 | ) { 52 | super(applicationId) 53 | } 54 | } 55 | 56 | export class DeliveryEndpointTransferredEvent extends ApplicationEvent { 57 | constructor( 58 | public deliveryEndponintId: string, 59 | public oldOwner: Identifiable, 60 | public newOwner: Identifiable, 61 | applicationId: string 62 | ) { 63 | super(applicationId) 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /packages/models/src/events/mardle.ts: -------------------------------------------------------------------------------- 1 | import { Channel, ChannelParticipation } from '../messaging/Channels' 2 | import { TimelineEvent } from '../messaging/TimelineEvents' 3 | import { ApplicationEvent } from './central' 4 | import { Message } from '../messaging/Messages' 5 | 6 | abstract class ChannelEvent extends ApplicationEvent { 7 | constructor(public channelId: string, applicationId: string) { 8 | super(applicationId) 9 | } 10 | } 11 | 12 | export class NewChannelMessageEvent extends ChannelEvent { 13 | constructor(public message: Message, channelId: string, applicationId: string) { 14 | super(channelId, applicationId) 15 | } 16 | } 17 | 18 | export class ChannelMessageReadyEvent extends ChannelEvent { 19 | constructor(public message: Message, channelId: string, applicationId: string) { 20 | super(channelId, applicationId) 21 | } 22 | } 23 | 24 | export class NewChannelEvent extends ChannelEvent { 25 | constructor(public channel: Channel, channelId: string, applicationId: string) { 26 | super(channelId, applicationId) 27 | } 28 | } 29 | 30 | export class ChannelMessageDeletedEvent extends ChannelEvent { 31 | constructor(public deletedMessage: Message, channelId: string, applicationId: string) { 32 | super(channelId, applicationId) 33 | } 34 | } 35 | 36 | export class ChannelDeletedEvent extends ChannelEvent { 37 | constructor(public deletedChannel: Channel, channelId: string, applicationId: string) { 38 | super(channelId, applicationId) 39 | } 40 | } 41 | 42 | export class ChannelParticipatedAddedEvent extends ChannelEvent { 43 | constructor( 44 | public channelParticipation: ChannelParticipation, 45 | channelId: string, 46 | applicationId: string 47 | ) { 48 | super(channelId, applicationId) 49 | } 50 | } 51 | 52 | export class ChannelParticipationModifiedEvent extends ChannelEvent { 53 | constructor( 54 | public oldChannelParticipation: ChannelParticipation, 55 | public newChannelParticipation: ChannelParticipation, 56 | channelId: string, 57 | applicationId: string 58 | ) { 59 | super(channelId, applicationId) 60 | } 61 | } 62 | 63 | export class ChannelParticipantDeletedEvent extends ChannelEvent { 64 | constructor( 65 | public channelParticipation: ChannelParticipation, 66 | channelId: string, 67 | applicationId: string 68 | ) { 69 | super(channelId, applicationId) 70 | } 71 | } 72 | 73 | export class NewTimelineEventForMessageEvent extends ChannelEvent { 74 | constructor( 75 | public timeLineEvent: TimelineEvent, 76 | public messageId: string, 77 | channelId: string, 78 | applicationId: string 79 | ) { 80 | super(channelId, applicationId) 81 | } 82 | } 83 | 84 | export class NewTimelineEventForChannelEvent extends ChannelEvent { 85 | constructor(public timeLineEvent: TimelineEvent, channelId: string, applicationId: string) { 86 | super(channelId, applicationId) 87 | } 88 | } 89 | 90 | export class NewTimelineEventEvent extends ApplicationEvent { 91 | constructor(public timeLineEvent: TimelineEvent, applicationId: string) { 92 | super(applicationId) 93 | } 94 | } 95 | 96 | export class ChannelMessagesTruncatedEvent extends ChannelEvent { 97 | constructor(channelId: string, applicationId: string) { 98 | super(channelId, applicationId) 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /packages/models/src/events/media-management.ts: -------------------------------------------------------------------------------- 1 | import { ApplicationEvent } from './central' 2 | 3 | export enum MediaManagementEventNames { 4 | HostedBinaryAvailableEvent = 'mitter.mpe.media.HostedBinaryAvailable' 5 | } 6 | 7 | export class HostedBinaryAvailableEvent extends ApplicationEvent { 8 | constructor( 9 | public resourceUri: string, 10 | public mediaKey: string, 11 | public representation: string, 12 | public mimeType: string, 13 | public contentLength: number, 14 | public applicationId: string 15 | ) { 16 | super(applicationId) 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/models/src/fcm/fcm.ts: -------------------------------------------------------------------------------- 1 | import { MessagingPipelinePayload } from '../delman/chat/payloads' 2 | 3 | export enum PacketTypes { 4 | NEW_MESSAGE = 'new-message', 5 | NEW_CHAT = 'new-chat', 6 | NEW_RECEIPT = 'new-receipt' 7 | } 8 | 9 | export class FcmPacket { 10 | constructor( 11 | public payload: MessagingPipelinePayload, 12 | public type: string, 13 | public fcmDiscriminator: string 14 | ) {} 15 | } 16 | -------------------------------------------------------------------------------- /packages/models/src/messaging/ChannelProfile.ts: -------------------------------------------------------------------------------- 1 | export type StandardChannelProfileAttributes = { 2 | displayName: string 3 | description: string 4 | channelIconURL: string 5 | purpose: string 6 | } 7 | export const standardChannelProfileAttributes: StandardChannelProfileAttributes = { 8 | displayName: 'mitter.cpa.DisplayName', 9 | description: 'mitter.cpa.Description', 10 | channelIconURL: 'mitter.cpa.ChannelIconURL', 11 | purpose: 'mitter.cpa.Purpose' 12 | } 13 | -------------------------------------------------------------------------------- /packages/models/src/messaging/Channels.ts: -------------------------------------------------------------------------------- 1 | import IdentifiableEntity from '../annotations/IdentifiableEntity' 2 | import { AuditInfo } from '../commons/common-models' 3 | import { User } from '../user/User' 4 | import { Message } from './Messages' 5 | import { TimelineEvent } from './TimelineEvents' 6 | import { EntityMetadata } from '../entity/EntityMetadata' 7 | import { EntityProfile } from '../entity/EntityProfile' 8 | import { Identifier } from '../annotations/Identifier' 9 | import { PickedPartial } from '../utils/ts-types' 10 | import { AppliedAclList } from '../acolyte/AppliedAclList' 11 | 12 | export enum StandardRuleSetNames { 13 | DirectMessage = 'io.mitter.ruleset.chats.DirectMessage', 14 | GroupChat = 'io.mitter.ruleset.chats.GroupChat', 15 | SystemChannel = 'io.mitter.ruleset.chats.SystemChannel', 16 | SingleParticipantChannel = 'io.mitter.ruleset.chats.SingleParticipantChannel' 17 | } 18 | 19 | export enum ParticipationStatus { 20 | Active = 'Active', 21 | ReadOnly = 'ReadOnly', 22 | Disabled = 'Disabled' 23 | } 24 | 25 | export class Channel implements IdentifiableEntity { 26 | constructor( 27 | public defaultRuleSet: string, 28 | public participation: Array, 29 | public entityProfile: EntityProfile, 30 | public channelId: string | null = null, 31 | public timelineEvents: Array = [], 32 | public appliedAcls: AppliedAclList = { plusAppliedAcls: [], minusAppliedAcls: [] }, 33 | public systemChannel: boolean = false, 34 | public entityMetadata: EntityMetadata = {}, 35 | public auditInfo?: AuditInfo 36 | ) {} 37 | 38 | identifier(): string { 39 | return this.channelId! 40 | } 41 | } 42 | 43 | type RequiredChannelParams = 'defaultRuleSet' | 'participation' 44 | export type RequestChannel = PickedPartial 45 | 46 | export class ChannelParticipation { 47 | constructor( 48 | public participantId: Identifier | string, 49 | public participationStatus: ParticipationStatus = ParticipationStatus.Active, 50 | public channelId: Identifier | string, 51 | public participant: User, 52 | public auditInfo?: AuditInfo 53 | ) {} 54 | } 55 | 56 | export class ParticipatedChannel { 57 | constructor(public participationStatus: ParticipationStatus, public channel: Channel) {} 58 | } 59 | 60 | export class ChannelSummary { 61 | constructor( 62 | public channelId: Identifier | string, 63 | public messages: Array, 64 | public unreadMessageCount: number 65 | ){} 66 | } 67 | -------------------------------------------------------------------------------- /packages/models/src/messaging/Commons.ts: -------------------------------------------------------------------------------- 1 | export class AuditFields { 2 | constructor(public creationTimeMs: number) {} 3 | } 4 | -------------------------------------------------------------------------------- /packages/models/src/messaging/ContextFreeMessage.ts: -------------------------------------------------------------------------------- 1 | export class ContextFreeMessage { 2 | constructor( 3 | public contextType: string, 4 | public context: string, 5 | public senderId: string, 6 | public data: object 7 | ) {} 8 | } 9 | -------------------------------------------------------------------------------- /packages/models/src/messaging/Messages.ts: -------------------------------------------------------------------------------- 1 | import { AuditInfo } from '../commons/common-models' 2 | import { User } from '../user/User' 3 | import {TimelineEvent} from './TimelineEvents' 4 | import {EntityMetadata, MetadataAttachable} from '../entity/EntityMetadata' 5 | import {AppliedAclList} from '../acolyte/AppliedAclList' 6 | import {Identifier} from '../annotations/Identifier' 7 | import {PickedPartial} from '../utils/ts-types' 8 | import {Channel} from "./Channels"; 9 | 10 | export enum StandardPayloadTypeNames { 11 | TextMessage = 'mitter.mt.Text', 12 | FormattedTextMessage = 'mitter.mt.FormattedText', 13 | LinkInsetTextMessage = 'mitter.mt.LinkInsetText', 14 | ImageMessage = 'mitter.mt.Image', 15 | EmptyMessage = 'mitter.mt.Empty', 16 | FileMessage = 'mitter.mt.File' 17 | } 18 | 19 | export enum StandardMessageType { 20 | Standard = 'Standard', 21 | Notification = 'Notification', 22 | OutOfBand = 'OutOfBand' 23 | } 24 | 25 | export class MessageDatum { 26 | constructor( 27 | public dataType: string, 28 | public data: { 29 | [key: string]: any 30 | } 31 | ) { 32 | } 33 | } 34 | 35 | export class Message implements MetadataAttachable { 36 | constructor( 37 | public senderId: Identifier | string, 38 | public textPayload: string, 39 | public timelineEvents: Array, 40 | public messageData: Array = [], 41 | public appliedAcls: AppliedAclList, 42 | public payloadType: string = StandardPayloadTypeNames.TextMessage, 43 | public messageId: string | null = null, 44 | public messageType: StandardMessageType = StandardMessageType.Standard, 45 | public entityMetadata: EntityMetadata = {}, 46 | public auditInfo?: AuditInfo, 47 | public sender?: User, 48 | public channel?: Channel 49 | ) { 50 | } 51 | } 52 | 53 | type RequiredMessageParams = 'senderId' | 'textPayload' | 'timelineEvents' 54 | export type RequestMessage = PickedPartial 55 | 56 | 57 | export class ChannelReferencingMessage implements MetadataAttachable { 58 | constructor( 59 | public channelId: Identifier, 60 | public messageId: string, 61 | public messageType: StandardMessageType = StandardMessageType.Standard, 62 | public payloadType: string = StandardPayloadTypeNames.TextMessage, 63 | public senderId: Identifier, 64 | public textPayload: string, 65 | public messageData: Array = [], 66 | public timelineEvents: Array, 67 | public entityMetadata: EntityMetadata, 68 | public auditInfo?: AuditInfo, 69 | public sender?: User, 70 | public channel?: Channel 71 | ) { 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /packages/models/src/messaging/ReservedMessageKeys.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:variable-name 2 | export const ReservedMessageKeys = { 3 | ImageMessage: { 4 | ImageLink: 'link', 5 | ImageRepresentations: 'repr' 6 | }, 7 | 8 | FileMessage: { 9 | FileLink: 'link', 10 | FileName: 'name' 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /packages/models/src/messaging/Streams.ts: -------------------------------------------------------------------------------- 1 | import IdentifiableEntity from '../annotations/IdentifiableEntity' 2 | 3 | export class Stream implements IdentifiableEntity { 4 | constructor( 5 | public streamId: string, 6 | public type: string, 7 | public supportedContentTypes: Array 8 | ) {} 9 | 10 | identifier(): string { 11 | return this.streamId 12 | } 13 | } 14 | 15 | export class ChannelStream { 16 | constructor(public channelId: string, public stream: ChannelStream) {} 17 | } 18 | -------------------------------------------------------------------------------- /packages/models/src/messaging/TimelineEvents.ts: -------------------------------------------------------------------------------- 1 | import IdentifiableEntity from '../annotations/IdentifiableEntity' 2 | import { Identifier } from '../annotations/Identifier' 3 | 4 | // tslint:disable-next-line:variable-name 5 | export const StandardTimeLineEventTypeNames = { 6 | CreationTime: 'io.mitter.types.timeline.CreationTime', 7 | messages: { 8 | SentTime: 'mitter.mtet.SentTime', 9 | ReceivedTime: 'mitter.mtet.ReceivedTime', 10 | DeliveredTime: 'mitter.mtet.DeliveredTime', 11 | ReadTime: 'mitter.mtet.ReadTime', 12 | DeletedTime: 'mitter.mtet.DeletedTime' 13 | } 14 | } 15 | 16 | export class TimelineEvent implements IdentifiableEntity { 17 | constructor( 18 | public type: string, 19 | public eventTimeMs: number, 20 | public subject: Identifier, 21 | public eventId: string | null = null 22 | ) {} 23 | 24 | identifier(): string { 25 | return this.eventId! 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/models/src/mitter-models.ts: -------------------------------------------------------------------------------- 1 | export * from './accesscredential/AccessCredential' 2 | export * from './accesscredential/AccessCredentialStub' 3 | export * from './accesscredential/AccessKey' 4 | export * from './accesscredential/AccessSecret' 5 | 6 | export * from './application/Application' 7 | export * from './application/properties/StandardApplicationProperty' 8 | export * from './application/properties/external/aws/AwsAccessCredentials' 9 | export * from './application/properties/external/aws/AwsServiceIntegrationProperty' 10 | export * from './application/properties/external/aws/AwsSnsTopicProperty' 11 | export * from './application/properties/external/google/GoogleApiCredential' 12 | export * from './application/properties/external/google/GoogleOAuthCredential' 13 | export * from './application/properties/external/google/GoogleServiceAccountCredential' 14 | export * from './application/properties/external/messaging/mechanism/APNSProperties' 15 | export * from './application/properties/external/messaging/mechanism/FCMProperties' 16 | export * from './application/properties/external/messaging/mechanism/MessagingMechanismProperty' 17 | export * from './application/properties/external/oauth/OAuthIntegrationProperty' 18 | export * from './application/properties/outflow/EventBusProperty' 19 | export * from './application/properties/outflow/TransactionalWebhookProperty' 20 | 21 | export * from './events/central' 22 | 23 | export * from './events/delivery-management' 24 | 25 | export * from './delman/chat/mardle-payloads' 26 | export * from './delman/chat/payloads' 27 | export * from './delman/delivery-endpoints' 28 | export * from './delman/delman-models' 29 | 30 | export * from './events/mardle' 31 | 32 | export * from './fcm/fcm' 33 | 34 | export * from './events/media-management' 35 | 36 | export * from './messaging/Channels' 37 | export * from './messaging/ChannelProfile' 38 | export * from './messaging/Commons' 39 | export * from './messaging/ContextFreeMessage' 40 | export * from './messaging/Messages' 41 | export * from './messaging/ReservedMessageKeys' 42 | export * from './messaging/Streams' 43 | export * from './messaging/TimelineEvents' 44 | 45 | export * from './entity/EntityMetadata' 46 | export * from './entity/EntityProfile' 47 | 48 | export * from './nerif/event-annotation' 49 | 50 | export * from './subscriber/Subscriber' 51 | 52 | export * from './user/locators/UserLocator' 53 | export * from './user/locators/EmailLocator' 54 | export * from './user/locators/MobileNumberLocator' 55 | export * from './user/Presence' 56 | export * from './user/Profile' 57 | export * from './user/User' 58 | export * from './user/VerificationStatus' 59 | 60 | export * from './web/objects/GoogleOAuthConfig' 61 | export * from './web/objects/PayloadUri' 62 | 63 | export * from './wire/MessageWireObjects' 64 | export * from './wire/TimelineEventWireObjects' 65 | 66 | export * from './requests/IssuedTokens' 67 | 68 | export * from './utils/model-types' 69 | export * from './utils/ts-types' 70 | 71 | export * from './annotations/Identifier' 72 | 73 | export * from './commons/common-models' 74 | 75 | export * from './counts/counts' 76 | 77 | export * from './weaver/DeliveryTarget/DeliveryTarget' 78 | export * from './weaver/DeliveryTarget/RegisteredSubscription' 79 | export * from './weaver/DeliveryTarget/RegisteredDeliveryTarget' 80 | export * from './weaver/DeliveryTarget/StandardDeliveryTargetType' 81 | 82 | export * from './weaver/Subscriptions/MessageResolutionSubscription' 83 | export * from './weaver/Subscriptions/Subscriptions' 84 | export * from './weaver/Subscriptions/UserResolutionSubscription' 85 | -------------------------------------------------------------------------------- /packages/models/src/nerif/event-annotation.ts: -------------------------------------------------------------------------------- 1 | export interface BaseEvent {} 2 | 3 | enum EventLevel { 4 | Action, 5 | Atomic 6 | } 7 | 8 | export class NerifEvent { 9 | constructor(public eventName: string, public eventLevel: EventLevel) {} 10 | } 11 | -------------------------------------------------------------------------------- /packages/models/src/requests/IssuedTokens.ts: -------------------------------------------------------------------------------- 1 | export class IssuedUserToken { 2 | constructor( 3 | public userToken: { 4 | signedToken: string 5 | supportedHeaders: string[] 6 | supportedCookies: string[] 7 | tokenId: string 8 | } 9 | ) {} 10 | } 11 | -------------------------------------------------------------------------------- /packages/models/src/subscriber/Subscriber.ts: -------------------------------------------------------------------------------- 1 | import IdentifiableEntity from '../annotations/IdentifiableEntity' 2 | export class Subscriber implements IdentifiableEntity { 3 | constructor( 4 | public subscriberId: string, 5 | public userName: string, 6 | public firstName: string, 7 | public lastName: string, 8 | public email: string, 9 | public mobile: string 10 | ) {} 11 | 12 | public identifier(): string { 13 | return this.subscriberId 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/models/src/user/Presence.ts: -------------------------------------------------------------------------------- 1 | import {Identifier} from "../annotations/Identifier"; 2 | 3 | export enum StandardUserPresenceTypeNames { 4 | Online = 'mitter.up.Online', 5 | Sleeping = 'mitter.up.Sleeping', 6 | Away = 'mitter.up.Away', 7 | Missing = 'mitter.up.Missing', 8 | Offline = 'mitter.up.Offline' 9 | } 10 | 11 | export class Presence { 12 | constructor(public type: string, public timeToLive: number, public expiresTo?: Presence) {} 13 | } 14 | 15 | export type ImpressedPresence = { 16 | presence?: Presence, 17 | setTimeMs: number 18 | } 19 | 20 | export type WiredPresence = { 21 | userId: Identifier, 22 | presence: ImpressedPresence 23 | } 24 | -------------------------------------------------------------------------------- /packages/models/src/user/Profile.ts: -------------------------------------------------------------------------------- 1 | export type StandardUserProfileAttributes = { 2 | firstName: string 3 | lastName: string 4 | avatarURL: string 5 | mobile: string 6 | dob: string 7 | bio: string 8 | gender: string 9 | email: string 10 | street: string 11 | city: string 12 | state: string 13 | zip: string 14 | country: string 15 | } 16 | export const standardUserProfileAttributes: StandardUserProfileAttributes = { 17 | firstName: 'mitter.user.profile.attribute.FirstName', 18 | lastName: 'mitter.user.profile.attribute.LastName', 19 | avatarURL: 'mitter.upa.AvatarURL', 20 | mobile: 'mitter.upa.Mobile', 21 | dob: 'mitter.upa.DOB', 22 | bio: 'mitter.upa.Bio', 23 | gender: 'mitter.upa.Gender', 24 | email: 'mitter.upa.Email', 25 | street: 'mitter.upa.address.Street', 26 | city: 'mitter.upa.address.City', 27 | state: 'mitter.upa.address.State', 28 | zip: 'mitter.upa.address.Zip', 29 | country: 'mitter.upa.address.Country' 30 | } 31 | 32 | export class AttributeDef { 33 | constructor( 34 | public key: string, 35 | public allowedContentTypes: Array, 36 | public allowedContentEncodings: Array, 37 | public canBeEmpty: boolean, 38 | public entityType: string // users or channels 39 | ) {} 40 | } 41 | 42 | class Attribute { 43 | constructor( 44 | public key: string, 45 | public contentType: string, 46 | public contentEncoding: string, 47 | public value: string 48 | ) {} 49 | } 50 | 51 | export class UserProfile { 52 | constructor(public userId: string, public attributes: Array) {} 53 | } 54 | -------------------------------------------------------------------------------- /packages/models/src/user/User.ts: -------------------------------------------------------------------------------- 1 | import IdentifiableEntity from '../annotations/IdentifiableEntity' 2 | import { AuditInfo } from '../commons/common-models' 3 | import { EntityMetadata } from '../entity/EntityMetadata' 4 | import { AttachedProfile } from '../entity/EntityProfile' 5 | import {UserLocator} from './locators/UserLocator'; 6 | 7 | export class User implements IdentifiableEntity { 8 | constructor( 9 | public userId: string, 10 | public userLocators: Array, 11 | public screenName: { 12 | screenName: string 13 | }, 14 | public systemUser: boolean = false, 15 | public synthetic: boolean = false, 16 | public entityProfile: AttachedProfile | null = null, 17 | public entityMetadata: EntityMetadata = {}, 18 | public auditInfo?: AuditInfo 19 | ) {} 20 | 21 | public identifier(): string { 22 | return this.userId 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /packages/models/src/user/VerificationStatus.ts: -------------------------------------------------------------------------------- 1 | export enum VerificationStatus { 2 | Verified, 3 | Unverified, 4 | StatusNotProvided, 5 | VerificationPending, 6 | VerificationApplicable 7 | } 8 | -------------------------------------------------------------------------------- /packages/models/src/user/locators/EmailLocator.ts: -------------------------------------------------------------------------------- 1 | import {LOCATOR_SERIALIZED_PREFIX, LocatorsType, UserLocator} from "./UserLocator" 2 | 3 | export class EmailUserLocator extends UserLocator { 4 | 5 | constructor(public email: string, userLocatorId?: string) { 6 | super( 7 | LocatorsType.Email, 8 | LOCATOR_SERIALIZED_PREFIX.Email, 9 | email, 10 | userLocatorId, 11 | 12 | ) 13 | 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/models/src/user/locators/MobileNumberLocator.ts: -------------------------------------------------------------------------------- 1 | import {LOCATOR_SERIALIZED_PREFIX, LocatorsType, UserLocator} from "./UserLocator"; 2 | 3 | export class MobileNumberLocator extends UserLocator { 4 | 5 | constructor(public phoneNumber: string, userLocatorId: string) { 6 | super( 7 | LocatorsType.PhoneNumber, 8 | LOCATOR_SERIALIZED_PREFIX.PhoneNumber, 9 | phoneNumber, 10 | userLocatorId 11 | ) 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /packages/models/src/user/locators/UserLocator.ts: -------------------------------------------------------------------------------- 1 | import { VerificationStatus } from '../VerificationStatus' 2 | 3 | export enum LocatorsType { 4 | Email = 'email', 5 | PhoneNumber = 'tele' 6 | } 7 | 8 | export enum LOCATOR_SERIALIZED_PREFIX { 9 | Email = 'email', 10 | PhoneNumber = 'tele' 11 | } 12 | 13 | export abstract class UserLocator { 14 | public verificationStatus: VerificationStatus 15 | public identifier: string | undefined 16 | public locator: string 17 | protected constructor( 18 | type: LocatorsType, 19 | public locatorSerializationPrefix: string, 20 | serializedLocator: string, 21 | public userLocatorId?: string, 22 | ) { 23 | (this)['@type'] = type 24 | this.locatorSerializationPrefix = locatorSerializationPrefix 25 | this.verificationStatus = VerificationStatus.StatusNotProvided 26 | this.locator = `${this.locatorSerializationPrefix}:${serializedLocator}` 27 | this.identifier = this.userLocatorId 28 | } 29 | } 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /packages/models/src/utils/ts-types.ts: -------------------------------------------------------------------------------- 1 | export type PickedPartial

= Partial

& Pick 2 | 3 | // type Exclude = T extends U ? never : T 4 | 5 | /*in the latets TS version Omit is part of the library itself */ 6 | /** for omitting a certain key(s)*/ 7 | export type Omit = Pick> 8 | 9 | /** for making a certain key(s) partial 10 | * uses omit to exclude the key , the adds the key as a partial 11 | * */ 12 | export type MakeKeyPartial = Omit & {[P in K]? : T[K]} 13 | -------------------------------------------------------------------------------- /packages/models/src/weaver/DeliveryTarget/DeliveryTarget.ts: -------------------------------------------------------------------------------- 1 | import {StandardDeliveryTargetType} from "./StandardDeliveryTargetType"; 2 | import {Identifier} from "../../annotations/Identifier"; 3 | 4 | export class DeliveryTarget { 5 | constructor(public deliveryTargetId: string, 6 | public targetType: StandardDeliveryTargetType, 7 | public mechanismSpecification: string, 8 | public validity?: number 9 | ) {} 10 | } 11 | 12 | export type WiredDeliveryTarget = DeliveryTarget & Identifier 13 | -------------------------------------------------------------------------------- /packages/models/src/weaver/DeliveryTarget/RegisteredDeliveryTarget.ts: -------------------------------------------------------------------------------- 1 | import {Identifier} from "../../annotations/Identifier"; 2 | import {RegisteredSubscription} from "./RegisteredSubscription"; 3 | 4 | 5 | export type RegisteredDeliveryTarget = { 6 | deliveryTargetId: Identifier, 7 | autoSubscriptions: RegisteredSubscription 8 | } 9 | 10 | /** 11 | * Delivery targets with mapped user id: { 12 | "deliveryTargetId": { 13 | "identifier": "deliveryTargetId" 14 | }, 15 | "autoSubscriptions": [ 16 | { 17 | "tag": "user-target", 18 | "descriptor": "/users/me", 19 | "subscriptionId": "FYZpZ-0Vi5O-FIGDL-Plbjf" 20 | } 21 | ] 22 | } 23 | Delivery targets for anonymous user: 24 | { 25 | "deliveryTargetId": { 26 | "identifier": "deliveryTargetId" 27 | }, 28 | "autoSubscriptions": [] 29 | } 30 | 31 | taken from https://git.mitter.io/mitter-io/mitter-io-central/wikis/Delivery-targets-&-subscription-models 32 | */ 33 | -------------------------------------------------------------------------------- /packages/models/src/weaver/DeliveryTarget/RegisteredSubscription.ts: -------------------------------------------------------------------------------- 1 | export type RegisteredSubscription = { 2 | tag: string, 3 | descriptor: string, 4 | subscriptionId: string 5 | } 6 | -------------------------------------------------------------------------------- /packages/models/src/weaver/DeliveryTarget/StandardDeliveryTargetType.ts: -------------------------------------------------------------------------------- 1 | export enum StandardDeliveryTargetType { 2 | Fcm = "fcm", 3 | WebSockets = "ws", 4 | TransactionalWebhook = "twh" 5 | } 6 | -------------------------------------------------------------------------------- /packages/models/src/weaver/Subscriptions/MessageResolutionSubscription.ts: -------------------------------------------------------------------------------- 1 | import {Subscriptions} from "./Subscriptions"; 2 | import {Identifier} from "../../annotations/Identifier"; 3 | 4 | export class MessageResolutionSubscription extends Subscriptions{ 5 | constructor( 6 | subscriptionId: string, 7 | public channelIds: Array 8 | ) { 9 | super(subscriptionId, 'message-resolution-subscription') 10 | } 11 | } 12 | 13 | export type WiredMessageResolutionSubscription = { 14 | '@subscriptionType': 'message-resolution-subscription', 15 | 'subscriptionId': string, 16 | 'channelIds': Array 17 | } & Identifier 18 | 19 | /** 20 | * MessageResolutionSubscriptionResponse 21 | * { 22 | "@subscriptionType": "message-resolution-subscription", 23 | "subscriptionId": "subscriptionId", 24 | "channelIds": [ 25 | { 26 | "identifier": "channelId" 27 | } 28 | ], 29 | "identifier": "subscriptionId" 30 | } 31 | 32 | */ 33 | -------------------------------------------------------------------------------- /packages/models/src/weaver/Subscriptions/Subscriptions.ts: -------------------------------------------------------------------------------- 1 | export abstract class Subscriptions { 2 | constructor( 3 | public subscriptionId: string, 4 | subscriptionType: string 5 | ) { 6 | (this as any)['@subscriptionType'] = subscriptionType 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /packages/models/src/weaver/Subscriptions/UserResolutionSubscription.ts: -------------------------------------------------------------------------------- 1 | import {Subscriptions} from "./Subscriptions"; 2 | import {Identifier} from "../../annotations/Identifier"; 3 | 4 | export class UserResolutionSubscription extends Subscriptions { 5 | constructor( 6 | subscriptionId: string, 7 | public target: Identifier 8 | ) { 9 | super(subscriptionId, 'user-resolution-subscription') 10 | } 11 | } 12 | 13 | 14 | export type WiredUserResolutionSubscription = { 15 | 'subscriptionType': 'user-resolution-subscription', 16 | 'subscriptionId': string, 17 | 'target': Identifier, 18 | } & Identifier 19 | -------------------------------------------------------------------------------- /packages/models/src/web/objects/GoogleOAuthConfig.ts: -------------------------------------------------------------------------------- 1 | import { PayloadUri } from './PayloadUri' 2 | 3 | export class GoogleOAuthConfig { 4 | constructor( 5 | public googleRedirectUriL: PayloadUri, 6 | public googleOAuthEndpoint: PayloadUri, 7 | public googleOAuthClientId: string, 8 | public oauthRedirectUri: PayloadUri, 9 | public serviceActive: boolean 10 | ) {} 11 | } 12 | -------------------------------------------------------------------------------- /packages/models/src/web/objects/PayloadUri.ts: -------------------------------------------------------------------------------- 1 | export class PayloadUri { 2 | constructor(public payloadUri: string, public uriContext: string) {} 3 | } 4 | -------------------------------------------------------------------------------- /packages/models/src/wire/MessageWireObjects.ts: -------------------------------------------------------------------------------- 1 | import Identifiable from '../annotations/Identifiable' 2 | import { Message } from '../messaging/Messages' 3 | 4 | enum SortOrder { 5 | Ascending, 6 | Descending, 7 | Implied 8 | } 9 | 10 | export class MessageQuery { 11 | /*AclAccessorSelector should be used instead of array*/ 12 | constructor( 13 | public channelId: string, 14 | public limit: number = 10, 15 | public withReadSelectors: Array, 16 | public beforeMessageId: string | null, 17 | public afterMessageId: string | null 18 | ) {} 19 | } 20 | 21 | export class AddableMessage { 22 | constructor(public message: Message) {} 23 | } 24 | 25 | export class ChannelMessageSet { 26 | constructor(public channelId: string, public messages: Array) {} 27 | } 28 | 29 | export class ChannelMessage { 30 | constructor(public channelId: string, public message: Message) {} 31 | } 32 | 33 | export class Paginated> { 34 | constructor(public data: Array, public estimatedTotalCount: number) {} 35 | } 36 | 37 | export class EntityQuery> { 38 | /* AclAccessorSelector should be used instead of array */ 39 | constructor( 40 | public beforeId: Identifiable | null, 41 | public afterId: Identifiable | null, 42 | public limit: number, 43 | public entityCountOffset: number, 44 | public sortOrder: SortOrder, 45 | public withReadSelectors: Array 46 | ) {} 47 | } 48 | -------------------------------------------------------------------------------- /packages/models/src/wire/TimelineEventWireObjects.ts: -------------------------------------------------------------------------------- 1 | import { TimelineEvent } from '../messaging/TimelineEvents' 2 | import { ChannelParticipation, ParticipationStatus } from '../messaging/Channels' 3 | 4 | export class MessageTimelineEvent { 5 | constructor( 6 | public messageId: string, 7 | public timelineEvent: TimelineEvent, 8 | public channelId: string | null 9 | ) {} 10 | } 11 | 12 | export class MessageTimelineEventSet { 13 | constructor( 14 | public messageId: string, 15 | public timelineEvents: Array, 16 | public channelId: string | null 17 | ) {} 18 | } 19 | 20 | export class ChannelTimelineEvent { 21 | constructor(public channelId: string, public timelineEvent: TimelineEvent) {} 22 | } 23 | 24 | export class ChannelTimelineEventSet { 25 | constructor(public channelId: string, public timelineEvents: Array) {} 26 | } 27 | 28 | export class PatchChannelParticipation { 29 | constructor(public newStatus: ParticipationStatus) {} 30 | } 31 | 32 | export class PatchChannelParticipationResult { 33 | constructor( 34 | public oldChannelParticipation: ChannelParticipation, 35 | public newChannelParticipation: ChannelParticipation 36 | ) {} 37 | } 38 | -------------------------------------------------------------------------------- /packages/models/src/wire/errors.ts: -------------------------------------------------------------------------------- 1 | export enum MitterErrorCodes { 2 | ClaimRejected = 'claim_rejected', 3 | EntityNotFound = 'entity_not_found', 4 | AuthorizationException = 'authorization_exception', 5 | MissingPrivilege = 'missing_privilege', 6 | MissingContext = 'missing_context' 7 | } 8 | 9 | export type MitterErrorPreamble = { 10 | errorCode: string 11 | } 12 | 13 | export type EntityNotFoundError = MitterErrorPreamble & { 14 | diagnostics: { 15 | entityType: string 16 | entityLocator: string 17 | } 18 | } 19 | 20 | export type AuthorizationException = MitterErrorPreamble & {} 21 | 22 | export type MissingPrivilegeError = MitterErrorPreamble & { 23 | diagnostics: { 24 | missingPrivileges: Array 25 | actingEntity: string 26 | actor?: string 27 | } 28 | } 29 | 30 | export type MissingContextError = MitterErrorPreamble & { 31 | diagnostics: { 32 | missingContext: string 33 | } 34 | } 35 | 36 | export type ClaimRejectedError = MitterErrorPreamble & { 37 | diagnostics: { 38 | claimType: string 39 | claimOn: string 40 | claimRejectionType: string 41 | } 42 | } 43 | 44 | export type MitterError = MitterErrorPreamble & 45 | (EntityNotFoundError | AuthorizationException | MissingContextError | MissingPrivilegeError) 46 | -------------------------------------------------------------------------------- /packages/models/test/mitter-models.test.ts: -------------------------------------------------------------------------------- 1 | import DummyClass from '../src/mitter-models' 2 | 3 | /** 4 | * Dummy test 5 | */ 6 | describe('Dummy test', () => { 7 | it('works if true is truthy', () => { 8 | expect(true).toBeTruthy() 9 | }) 10 | 11 | it('DummyClass is instantiable', () => { 12 | expect(new DummyClass()).toBeInstanceOf(DummyClass) 13 | }) 14 | }) 15 | -------------------------------------------------------------------------------- /packages/models/tools/gh-pages-publish.ts: -------------------------------------------------------------------------------- 1 | const { cd, exec, echo, touch } = require("shelljs") 2 | const { readFileSync } = require("fs") 3 | const url = require("url") 4 | 5 | let repoUrl 6 | let pkg = JSON.parse(readFileSync("package.json") as any) 7 | if (typeof pkg.repository === "object") { 8 | if (!pkg.repository.hasOwnProperty("url")) { 9 | throw new Error("URL does not exist in repository section") 10 | } 11 | repoUrl = pkg.repository.url 12 | } else { 13 | repoUrl = pkg.repository 14 | } 15 | 16 | let parsedUrl = url.parse(repoUrl) 17 | let repository = (parsedUrl.host || "") + (parsedUrl.path || "") 18 | let ghToken = process.env.GH_TOKEN 19 | 20 | echo("Deploying docs!!!") 21 | cd("docs") 22 | touch(".nojekyll") 23 | exec("git init") 24 | exec("git add .") 25 | exec('git config user.name ""') 26 | exec('git config user.email ""') 27 | exec('git commit -m "docs(docs): update gh-pages"') 28 | exec( 29 | `git push --force --quiet "https://${ghToken}@${repository}" master:gh-pages` 30 | ) 31 | echo("Docs deployed!!") 32 | -------------------------------------------------------------------------------- /packages/models/tools/semantic-release-prepare.ts: -------------------------------------------------------------------------------- 1 | const path = require("path") 2 | const { fork } = require("child_process") 3 | const colors = require("colors") 4 | 5 | const { readFileSync, writeFileSync } = require("fs") 6 | const pkg = JSON.parse( 7 | readFileSync(path.resolve(__dirname, "..", "package.json")) 8 | ) 9 | 10 | pkg.scripts.prepush = "npm run test:prod && npm run build" 11 | pkg.scripts.commitmsg = "validate-commit-msg" 12 | 13 | writeFileSync( 14 | path.resolve(__dirname, "..", "package.json"), 15 | JSON.stringify(pkg, null, 2) 16 | ) 17 | 18 | // Call husky to set up the hooks 19 | fork(path.resolve(__dirname, "..", "node_modules", "husky", "bin", "install")) 20 | 21 | console.log() 22 | console.log(colors.green("Done!!")) 23 | console.log() 24 | 25 | if (pkg.repository.url.trim()) { 26 | console.log(colors.cyan("Now run:")) 27 | console.log(colors.cyan(" npm install -g semantic-release-cli")) 28 | console.log(colors.cyan(" semantic-release-cli setup")) 29 | console.log() 30 | console.log( 31 | colors.cyan('Important! Answer NO to "Generate travis.yml" question') 32 | ) 33 | console.log() 34 | console.log( 35 | colors.gray( 36 | 'Note: Make sure "repository.url" in your package.json is correct before' 37 | ) 38 | ) 39 | } else { 40 | console.log( 41 | colors.red( 42 | 'First you need to set the "repository.url" property in package.json' 43 | ) 44 | ) 45 | console.log(colors.cyan("Then run:")) 46 | console.log(colors.cyan(" npm install -g semantic-release-cli")) 47 | console.log(colors.cyan(" semantic-release-cli setup")) 48 | console.log() 49 | console.log( 50 | colors.cyan('Important! Answer NO to "Generate travis.yml" question') 51 | ) 52 | } 53 | 54 | console.log() 55 | -------------------------------------------------------------------------------- /packages/models/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es5", 5 | "module":"es2015", 6 | "lib": ["es2015", "es2016", "es2017", "dom"], 7 | "strict": true, 8 | "sourceMap": true, 9 | "declaration": true, 10 | "allowSyntheticDefaultImports": true, 11 | "experimentalDecorators": true, 12 | "emitDecoratorMetadata": true, 13 | "declarationDir": "dist/types", 14 | "outDir": "dist/lib", 15 | "typeRoots": [ 16 | "node_modules/@types" 17 | ] 18 | }, 19 | "include": [ 20 | "src" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /packages/models/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint-config-standard", 4 | "tslint-config-prettier" 5 | ] 6 | } -------------------------------------------------------------------------------- /packages/node/.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 = 4 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | -------------------------------------------------------------------------------- /packages/node/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .DS_Store 5 | *.log 6 | .vscode 7 | .idea 8 | dist 9 | compiled 10 | .awcache 11 | .rpt2_cache 12 | docs 13 | *.iml 14 | 15 | -------------------------------------------------------------------------------- /packages/node/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | branches: 3 | only: 4 | - master 5 | - /^greenkeeper/.*$/ 6 | cache: 7 | yarn: true 8 | directories: 9 | - node_modules 10 | notifications: 11 | email: false 12 | node_js: 13 | - node 14 | script: 15 | - npm run test:prod && npm run build 16 | after_success: 17 | - npm run report-coverage 18 | - npm run deploy-docs 19 | - npm run semantic-release 20 | -------------------------------------------------------------------------------- /packages/node/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/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Rohan Prabhu <> 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /packages/node/README.md: -------------------------------------------------------------------------------- 1 | # mitter-node 2 | 3 | Library for consuming mitter.io APIs for backend applications on node and node-like environments. 4 | -------------------------------------------------------------------------------- /packages/node/code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at alexjovermorales@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /packages/node/rollup.config.ts: -------------------------------------------------------------------------------- 1 | import resolve from 'rollup-plugin-node-resolve' 2 | import commonjs from 'rollup-plugin-commonjs' 3 | import sourceMaps from 'rollup-plugin-sourcemaps' 4 | import camelCase from 'lodash.camelcase' 5 | import typescript from 'rollup-plugin-typescript2' 6 | import json from 'rollup-plugin-json' 7 | import builtins from 'rollup-plugin-node-builtins' 8 | import globals from 'rollup-plugin-node-globals' 9 | 10 | const pkg = require('./package.json') 11 | 12 | const libraryName = 'mitter-node' 13 | 14 | export default { 15 | input: `src/${libraryName}.ts`, 16 | output: [ 17 | { 18 | file: pkg.main, 19 | name: camelCase(libraryName), 20 | format: 'cjs', 21 | sourcemap: true, 22 | outro: 'module.exports = Object.assign({}, module.exports, exports)' 23 | }, 24 | { file: pkg.module, format: 'es', sourcemap: true }, 25 | ], 26 | // Indicate here external modules you don't wanna include in your bundle (i.e.: 'lodash') 27 | external: [ 28 | 'websocket', 29 | 'sockjs-client', 30 | 'axios', 31 | 'crypto' 32 | ], 33 | watch: { 34 | include: [ 35 | 'src/**', 36 | './../mitter-ts-core/dist/**', 37 | './../mitter-ts-models/dist/**' 38 | ] 39 | }, 40 | plugins: [ 41 | globals(), 42 | resolve(), 43 | builtins(), 44 | // Allow json resolution 45 | // Compile TypeScript files 46 | typescript({ useTsconfigDeclarationDir: true }), 47 | // Allow bundling cjs modules (unlike webpack, rollup doesn't understand cjs) 48 | commonjs(), 49 | 50 | json(), 51 | // Allow node_modules resolution, so you can use 'external' to control 52 | // which external modules to include in the bundle 53 | // https://github.com/rollup/rollup-plugin-node-resolve#usage 54 | 55 | // Resolve source maps to the original source 56 | sourceMaps() 57 | ], 58 | } 59 | -------------------------------------------------------------------------------- /packages/node/src/auth/AccessKeySigner.ts: -------------------------------------------------------------------------------- 1 | import { DigestParts, DigestGenerationArtifacts } from './digest-objects' 2 | import randomstring from 'randomstring' 3 | import crypto from 'crypto' 4 | 5 | export default class AccessKeySigner { 6 | constructor(public readonly accessKey: string, private readonly accessSecret: string) {} 7 | 8 | static Headers = { 9 | Nonce: 'Nonce', 10 | Date: 'Date', 11 | ContentMD5: 'Content-Md5', 12 | ContentType: 'Content-Type' 13 | } 14 | 15 | public signRequest(digestParts: DigestParts): DigestGenerationArtifacts { 16 | const date = this.getDate(digestParts) 17 | const contentType = this.getContentType(digestParts) 18 | const nonce = this.getNonce(digestParts) 19 | 20 | const computePayload = [ 21 | digestParts.method.toUpperCase(), 22 | contentType, 23 | digestParts.payloadMd5, 24 | date, 25 | digestParts.path, 26 | nonce 27 | ].join('\n') 28 | 29 | const digest = crypto 30 | .createHmac('SHA1', Buffer.from(this.accessSecret, 'base64')) 31 | .update(computePayload) 32 | .digest('base64') 33 | 34 | return new DigestGenerationArtifacts(nonce, date, `Auth ${this.accessKey}:${digest}`) 35 | } 36 | 37 | private getNonce(digestParts: DigestParts): string { 38 | if (digestParts.nonce !== undefined) { 39 | return digestParts.nonce 40 | } else { 41 | return randomstring.generate(32) 42 | } 43 | } 44 | 45 | private getContentType(digestParts: DigestParts): string { 46 | if (digestParts.contentType !== undefined) { 47 | return digestParts.contentType 48 | } else { 49 | return 'null' 50 | } 51 | } 52 | 53 | private getDate(digestParts: DigestParts): string { 54 | if (digestParts.date !== undefined) { 55 | return digestParts.date 56 | } else { 57 | return new Date().toUTCString() 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /packages/node/src/auth/access-key-interceptor.ts: -------------------------------------------------------------------------------- 1 | import { GenericInterceptor, StandardHeaders } from '@mitter-io/core' 2 | import AccessKeySigner from './AccessKeySigner' 3 | import { AccessKeyApplicationCredentials } from './application-credentials' 4 | import { DigestParts } from './digest-objects' 5 | import crypto from 'crypto' 6 | 7 | export class AccessKeySigningInterceptor { 8 | private readonly accessKeySigner: AccessKeySigner 9 | private static BodyContainingMethods = ['put', 'post', 'patch'] 10 | 11 | constructor(private readonly accessKeyCredentials: AccessKeyApplicationCredentials) { 12 | this.accessKeySigner = new AccessKeySigner( 13 | accessKeyCredentials.accessKey, 14 | accessKeyCredentials.accessSecret 15 | ) 16 | } 17 | 18 | getInterceptor(): GenericInterceptor { 19 | return requestParams => { 20 | const payload = 21 | requestParams.data === null || requestParams.data === undefined 22 | ? '' 23 | : requestParams.data 24 | 25 | const wirePayload = typeof payload === 'object' ? JSON.stringify(payload) : payload 26 | const contentType = 27 | payload == '' 28 | ? AccessKeySigningInterceptor.BodyContainingMethods.indexOf( 29 | requestParams.method 30 | ) === -1 31 | ? 'null' 32 | : 'application/json' 33 | : 'application/json' 34 | 35 | const payloadMd5 = crypto 36 | .createHash('md5') 37 | .update(wirePayload) 38 | .digest('base64') 39 | 40 | const digestParts = new DigestParts( 41 | requestParams.method, 42 | requestParams.path, 43 | payloadMd5, 44 | contentType 45 | ) 46 | 47 | const digest = this.accessKeySigner.signRequest(digestParts) 48 | 49 | requestParams.headers[StandardHeaders.AccessKeyHeader] = this.accessKeyCredentials.accessKey 50 | requestParams.headers[StandardHeaders.AccessKeyAuthorizationHeader] = digest.authorizationHeader 51 | requestParams.headers[AccessKeySigner.Headers.Date] = digest.date 52 | requestParams.headers[AccessKeySigner.Headers.Nonce] = digest.nonce 53 | requestParams.headers[AccessKeySigner.Headers.ContentMD5] = payloadMd5 54 | 55 | if (!(contentType === null || contentType === undefined || contentType === 'null')) { 56 | requestParams.headers[AccessKeySigner.Headers.ContentType] = contentType 57 | } 58 | 59 | requestParams.data = wirePayload 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /packages/node/src/auth/application-credentials.ts: -------------------------------------------------------------------------------- 1 | import { MitterAccessCredentials } from '@mitter-io/core' 2 | 3 | export interface MitterApplicationCredentials extends MitterAccessCredentials {} 4 | 5 | export class AccessKeyApplicationCredentials implements MitterApplicationCredentials { 6 | constructor(public readonly accessKey: string, public readonly accessSecret: string) {} 7 | } 8 | -------------------------------------------------------------------------------- /packages/node/src/auth/digest-objects.ts: -------------------------------------------------------------------------------- 1 | export class DigestParts { 2 | constructor( 3 | public readonly method: string, 4 | public readonly path: string, 5 | public readonly payloadMd5: string, 6 | public readonly contentType?: string | undefined, 7 | public readonly nonce?: string | undefined, 8 | public readonly date?: string | undefined 9 | ) {} 10 | } 11 | 12 | export class DigestGenerationArtifacts { 13 | constructor( 14 | public readonly nonce: string, 15 | public date: string, 16 | public authorizationHeader: string 17 | ) {} 18 | } 19 | -------------------------------------------------------------------------------- /packages/node/src/config.ts: -------------------------------------------------------------------------------- 1 | import {MitterCoreConfig, MitterUserCbs} from '@mitter-io/core' 2 | import {AccessKeyApplicationCredentials} from "./auth/application-credentials"; 3 | import {MakeKeyPartial} from "@mitter-io/models"; 4 | 5 | export type MitterNodeCoreConfig = {accessKey: AccessKeyApplicationCredentials} & Pick 7 | 8 | /** Making the mitterApiBaseUrl Id in the MitterNodeUserConfig a partial 9 | * as the user need not give mitterApiBaseUrl, it defaults to the mitter production url 10 | * */ 11 | export type MitterNodeUserConfig = MakeKeyPartial 12 | 13 | 14 | export type MitterNodeUserHooks = Pick 15 | -------------------------------------------------------------------------------- /packages/node/src/mitter-node.ts: -------------------------------------------------------------------------------- 1 | import { 2 | MitterBase, 3 | MitterAxiosApiInterceptor, 4 | PlatformImplementedFeatures, 5 | MitterApiConfiguration, 6 | MitterUserCbs, 7 | } from '@mitter-io/core' 8 | import { AxiosInstance } from 'axios' 9 | import { AccessKeySigningInterceptor } from './auth/access-key-interceptor' 10 | import {MitterNodeCoreConfig, MitterNodeUserConfig, MitterNodeUserHooks} from "./config"; 11 | import {getDefaultMitterUserCbs, getMitterNodeCoreConfig} from './utils'; 12 | 13 | export class MitterNode extends MitterBase { 14 | private accessKeySigningInterceptor: AccessKeySigningInterceptor 15 | 16 | constructor( 17 | public mitterNodeCoreConfig: MitterNodeCoreConfig, 18 | /*private applicationId: string, 19 | private accessKey: AccessKeyApplicationCredentials, 20 | public mitterApiBaseUrl: string,*/ 21 | mitterUserCbs: MitterUserCbs 22 | ) { 23 | super( 24 | mitterUserCbs, 25 | {} as PlatformImplementedFeatures 26 | ) 27 | this.accessKeySigningInterceptor = new AccessKeySigningInterceptor(mitterNodeCoreConfig.accessKey) 28 | } 29 | 30 | enableAxiosInterceptor(axiosInstance: AxiosInstance) { 31 | new MitterAxiosApiInterceptor( 32 | /* the application id */ 33 | this.mitterNodeCoreConfig.applicationId, 34 | 35 | /* the default signing interceptor to use */ 36 | this.accessKeySigningInterceptor.getInterceptor(), 37 | 38 | this.mitterNodeCoreConfig.mitterApiBaseUrl, 39 | false, 40 | // this.getMitterHooks 41 | ).enable(axiosInstance) 42 | } 43 | 44 | platformImplementedFeaturesProvider = () => { 45 | return {} as PlatformImplementedFeatures 46 | } 47 | 48 | mitterApiConfigurationProvider = () => { 49 | return new MitterApiConfiguration( 50 | this.accessKeySigningInterceptor.getInterceptor(), 51 | this.mitterNodeCoreConfig.mitterApiBaseUrl, 52 | this.enableAxiosInterceptor.bind(this) 53 | ) 54 | } 55 | } 56 | 57 | export const Mitter = { 58 | forNode: function( 59 | mitterNodeUserConfig: MitterNodeUserConfig, 60 | mitterNodeUserHooks?: MitterNodeUserHooks 61 | ): MitterNode { 62 | return new MitterNode( 63 | getMitterNodeCoreConfig(mitterNodeUserConfig), 64 | getDefaultMitterUserCbs(mitterNodeUserHooks) 65 | ) 66 | } 67 | } 68 | 69 | export * from './auth/application-credentials' 70 | -------------------------------------------------------------------------------- /packages/node/src/utils.ts: -------------------------------------------------------------------------------- 1 | import {MitterConstants, MitterUserCbs } from "@mitter-io/core"; 2 | import {MitterNodeCoreConfig, MitterNodeUserConfig, MitterNodeUserHooks} from "./config"; 3 | 4 | export const noOp = () => {} 5 | 6 | export function getMitterNodeCoreConfig(mitterNodeUserConfig: MitterNodeUserConfig): MitterNodeCoreConfig { 7 | return { 8 | mitterApiBaseUrl: MitterConstants.MitterApiUrl, 9 | ...mitterNodeUserConfig, 10 | } 11 | } 12 | 13 | 14 | export function getDefaultMitterUserCbs(hooks: Partial = {}): MitterUserCbs { 15 | return { 16 | mitterInstanceReady: () => {}, 17 | onTokenExpire: [noOp], 18 | onMessagingPipelineConnectCbs: [noOp], 19 | ...hooks 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/node/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es5", 5 | "module":"es2015", 6 | "lib": ["es2015", "es2016", "es2017", "dom"], 7 | "strict": true, 8 | "sourceMap": true, 9 | "declaration": true, 10 | "allowSyntheticDefaultImports": true, 11 | "experimentalDecorators": true, 12 | "emitDecoratorMetadata": true, 13 | "declarationDir": "dist/types", 14 | "outDir": "dist/lib", 15 | "typeRoots": [ 16 | "node_modules/@types" 17 | ] 18 | }, 19 | "include": [ 20 | "src" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /packages/node/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint-config-standard", 4 | "tslint-config-prettier" 5 | ] 6 | } -------------------------------------------------------------------------------- /packages/react-native/.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/react-native/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .DS_Store 5 | *.log 6 | .vscode 7 | .idea 8 | dist 9 | compiled 10 | .awcache 11 | .rpt2_cache 12 | docs 13 | .watchmanconfig 14 | -------------------------------------------------------------------------------- /packages/react-native/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | branches: 3 | only: 4 | - master 5 | - /^greenkeeper/.*$/ 6 | cache: 7 | yarn: true 8 | directories: 9 | - node_modules 10 | notifications: 11 | email: false 12 | node_js: 13 | - node 14 | script: 15 | - npm run test:prod && npm run build 16 | after_success: 17 | - npm run report-coverage 18 | - npm run deploy-docs 19 | - npm run semantic-release 20 | -------------------------------------------------------------------------------- /packages/react-native/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/react-native/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Vineeth George 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /packages/react-native/README.md: -------------------------------------------------------------------------------- 1 | # @mitter-io/react-native 2 | 3 | react-native SDK for working with mitter.io. 4 | -------------------------------------------------------------------------------- /packages/react-native/code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at alexjovermorales@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /packages/react-native/rollup.config.ts: -------------------------------------------------------------------------------- 1 | // import resolve from 'rollup-plugin-node-resolve' 2 | // import commonjs from 'rollup-plugin-commonjs' 3 | import sourceMaps from 'rollup-plugin-sourcemaps' 4 | import camelCase from 'lodash.camelcase' 5 | import typescript from 'rollup-plugin-typescript2' 6 | import json from 'rollup-plugin-json' 7 | // import builtins from 'rollup-plugin-node-builtins' 8 | // import globals from 'rollup-plugin-node-globals' 9 | import replace from 'rollup-plugin-replace' 10 | 11 | const pkg = require('./package.json') 12 | 13 | const libraryName = 'mitter-react-native' 14 | 15 | export default { 16 | input: `src/${libraryName}.ts`, 17 | output: [ 18 | { file: pkg.main, name: camelCase(libraryName), format: 'umd', sourcemap: true }, 19 | { file: pkg.module, format: 'es', sourcemap: true }, 20 | ], 21 | // Indicate here external modules you don't wanna include in your bundle (i.e.: 'lodash') 22 | external: ['realm', 'react-native-firebase', 'react-native', 'rn-fetch-blob', 'query-string','react-native-uuid'], 23 | watch: { 24 | include: ['src/**', './../mitter-ts-core/dist/**'], 25 | }, 26 | plugins: [ 27 | 28 | replace({ 29 | 'process.version.': '"v9.5.0".', 30 | delimiters: ['', ''] 31 | }), 32 | json(), 33 | typescript({ useTsconfigDeclarationDir: true }), 34 | // Resolve source maps to the original source 35 | sourceMaps() 36 | ], 37 | } 38 | -------------------------------------------------------------------------------- /packages/react-native/src/drivers/MitterFcmPipelineDriver.ts: -------------------------------------------------------------------------------- 1 | import { 2 | MessagingPipelineDriver, 3 | PipelineSink, 4 | PipelineDriverInitialization, 5 | Mitter 6 | } from '@mitter-io/core' 7 | 8 | import firebase from 'react-native-firebase' 9 | import { DeliveryTarget, StandardDeliveryTargetType } from '@mitter-io/models' 10 | import { noOp } from '../utils' 11 | import uuid from 'react-native-uuid' 12 | 13 | // tslint:disable-next-line:variable-name 14 | export const FcmDriverSpecName = 'io.mitter.drivers.fcm' 15 | 16 | export default class MitterFcmPipelineDriver implements MessagingPipelineDriver { 17 | private static DriverSpec = { 18 | name: FcmDriverSpecName 19 | } 20 | 21 | initialize(mitterContext: Mitter): PipelineDriverInitialization { 22 | return { 23 | pipelineDriverSpec: MitterFcmPipelineDriver.DriverSpec, 24 | initialized: firebase.messaging().requestPermission() 25 | } 26 | } 27 | 28 | async getDeliveryTarget(): Promise { 29 | return firebase 30 | .messaging() 31 | .getToken() 32 | .then(fcmToken => { 33 | // return new FcmDeliveryEndpoint(fcmToken) 34 | return new DeliveryTarget(uuid.v4(), StandardDeliveryTargetType.Fcm, fcmToken) 35 | }) 36 | } 37 | 38 | deliveryTargetRegistered(pipelineSink: PipelineSink, deliveryTarget: DeliveryTarget): void { 39 | registerFirebaseListener(pipelineSink, deliveryTarget) 40 | } 41 | 42 | halt() { 43 | noOp() 44 | } 45 | } 46 | 47 | function registerFirebaseListener( 48 | pipelineSink: PipelineSink, 49 | _deliveryTarget: DeliveryTarget 50 | ): void { 51 | console.log('registering firebase listener') 52 | firebase.messaging().onMessage(message => { 53 | try { 54 | console.info('message recevied', message) 55 | const payload = JSON.parse(message._data.data) 56 | pipelineSink.received(payload) 57 | } catch (e) { 58 | console.warn(e) 59 | } 60 | }) 61 | 62 | firebase.notifications().onNotification(notification => { 63 | // Process your notification as required 64 | try { 65 | console.log('notification from fcm recevied', notification) 66 | const payload = JSON.parse((notification as any)._data.data) 67 | pipelineSink.received(payload) 68 | return Promise.resolve() 69 | } catch (e) { 70 | console.warn(e) 71 | return Promise.resolve() 72 | } 73 | }) 74 | } 75 | -------------------------------------------------------------------------------- /packages/react-native/src/kv-store/kvStore.ts: -------------------------------------------------------------------------------- 1 | import { AsyncStorage } from 'react-native' 2 | import { KvStore as MitterKvStore } from '@mitter-io/core' 3 | 4 | export default class KvStore implements MitterKvStore { 5 | async getItem(key: string): Promise { 6 | let item = await AsyncStorage.getItem(key) 7 | 8 | if (item === null) { 9 | return undefined 10 | } 11 | 12 | return JSON.parse(item) as T 13 | } 14 | 15 | async setItem(key: string, value: T): Promise { 16 | AsyncStorage.setItem(key, JSON.stringify(value)) 17 | } 18 | 19 | async removeItem(key: string): Promise { 20 | AsyncStorage.removeItem(key) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /packages/react-native/src/mitter-react-native.ts: -------------------------------------------------------------------------------- 1 | import { Mitter as MitterCore, MitterUserConfig, MitterUserCbs } from '@mitter-io/core' 2 | import base64 from 'base-64' 3 | import MitterFcmPipelineDriver from './drivers/MitterFcmPipelineDriver' 4 | import NativeKvStore from './kv-store/kvStore' 5 | import { nativeFileUploader } from './nativeSpecificImplementations/nativeFileUploader' 6 | import { getDefaultMitterUserCbs, getMitterCoreConfig } from './utils' 7 | import uuid from 'react-native-uuid' 8 | 9 | export { NativeKvStore } 10 | 11 | export const Mitter = { 12 | forReactNative: function( 13 | mitterUserConfig: MitterUserConfig, 14 | mitterUserCbs?: Partial 15 | ): MitterCore { 16 | return new MitterCore( 17 | getMitterCoreConfig(mitterUserConfig), 18 | getDefaultMitterUserCbs(mitterUserCbs), 19 | new NativeKvStore(), 20 | new MitterFcmPipelineDriver(), 21 | global, 22 | { 23 | processMultipartRequest: nativeFileUploader, 24 | base64Decoder: base64.decode, 25 | randomIdGenerator: uuid.v4 26 | } 27 | ) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /packages/react-native/src/nativeSpecificImplementations/nativeFileUploader.ts: -------------------------------------------------------------------------------- 1 | import { 2 | GenericRequestParameters, 3 | UriConfig, 4 | BlobConfig, 5 | MULTIPART_MESSAGE_NAME_KEY, 6 | MULTIPART_MESSAGE_FILE_NAME 7 | } from '@mitter-io/core' 8 | import { Message, ChannelReferencingMessage } from '@mitter-io/models' 9 | import base64 from 'base-64' 10 | import RNFetchBlob, { FetchBlobResponse } from 'rn-fetch-blob' 11 | import { base64ValidationRegex } from '../utils' 12 | 13 | export function nativeFileUploader( 14 | requestParams: GenericRequestParameters, 15 | channelId: string, 16 | message: Message, 17 | fileObject: T 18 | ): Error | Promise { 19 | const data = RNFetchBlob.wrap((fileObject as UriConfig).uri) 20 | 21 | /** type is set to as any because the type is Methods in fetchblob and string in mitter core 22 | * but it assumed that it will always have the correct HTTP method from mitter core 23 | * */ 24 | return RNFetchBlob.fetch(requestParams.method as any, requestParams.path, requestParams.headers, [ 25 | { 26 | name: fileObject.filename, 27 | filename: fileObject.filename, 28 | type: fileObject.type, 29 | data: data 30 | }, 31 | { 32 | name: MULTIPART_MESSAGE_NAME_KEY, 33 | filename: MULTIPART_MESSAGE_FILE_NAME, 34 | type: 'application/json', 35 | data: base64.encode(JSON.stringify(message)) 36 | } 37 | ]).then((res: FetchBlobResponse) => { 38 | const { status } = res.respInfo 39 | 40 | if ([400, 401, 403, 413].indexOf(status) > -1) { 41 | throw res.data 42 | } 43 | return res.data as Promise 44 | }) 45 | } 46 | -------------------------------------------------------------------------------- /packages/react-native/src/utils.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:no-empty 2 | import { MitterConstants, MitterCoreConfig, MitterUserConfig, MitterUserCbs } from '@mitter-io/core' 3 | 4 | export const noOp = () => {} 5 | 6 | export const base64ValidationRegex = new RegExp( 7 | /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)?$/ 8 | ) 9 | 10 | export function getMitterCoreConfig(mitterUserConfig: MitterUserConfig): MitterCoreConfig { 11 | return { 12 | weaverUrl: '', 13 | mitterApiBaseUrl: MitterConstants.MitterApiUrl, 14 | initMessagingPipelineSubscriptions: [], 15 | disableXHRCaching: true, 16 | ...mitterUserConfig 17 | } 18 | } 19 | 20 | export function getDefaultMitterUserCbs(hooks: Partial = {}): MitterUserCbs { 21 | return { 22 | mitterInstanceReady: () => {}, 23 | onTokenExpire: [noOp], 24 | onMessagingPipelineConnectCbs: [noOp], 25 | ...hooks 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /packages/react-native/test/mitter-react-native.test.ts: -------------------------------------------------------------------------------- 1 | import DummyClass from "../src/mitter-react-native" 2 | 3 | /** 4 | * Dummy test 5 | */ 6 | describe("Dummy test", () => { 7 | it("works if true is truthy", () => { 8 | expect(true).toBeTruthy() 9 | }) 10 | 11 | it("DummyClass is instantiable", () => { 12 | expect(new DummyClass()).toBeInstanceOf(DummyClass) 13 | }) 14 | }) 15 | -------------------------------------------------------------------------------- /packages/react-native/tools/gh-pages-publish.ts: -------------------------------------------------------------------------------- 1 | const { cd, exec, echo, touch } = require("shelljs") 2 | const { readFileSync } = require("fs") 3 | const url = require("url") 4 | 5 | let repoUrl 6 | let pkg = JSON.parse(readFileSync("package.json") as any) 7 | if (typeof pkg.repository === "object") { 8 | if (!pkg.repository.hasOwnProperty("url")) { 9 | throw new Error("URL does not exist in repository section") 10 | } 11 | repoUrl = pkg.repository.url 12 | } else { 13 | repoUrl = pkg.repository 14 | } 15 | 16 | let parsedUrl = url.parse(repoUrl) 17 | let repository = (parsedUrl.host || "") + (parsedUrl.path || "") 18 | let ghToken = process.env.GH_TOKEN 19 | 20 | echo("Deploying docs!!!") 21 | cd("docs") 22 | touch(".nojekyll") 23 | exec("git init") 24 | exec("git add .") 25 | exec('git config user.name "Vineeth George"') 26 | exec('git config user.email "vineeth@mitter.io"') 27 | exec('git commit -m "docs(docs): update gh-pages"') 28 | exec( 29 | `git push --force --quiet "https://${ghToken}@${repository}" master:gh-pages` 30 | ) 31 | echo("Docs deployed!!") 32 | -------------------------------------------------------------------------------- /packages/react-native/tools/semantic-release-prepare.ts: -------------------------------------------------------------------------------- 1 | const path = require("path") 2 | const { fork } = require("child_process") 3 | const colors = require("colors") 4 | 5 | const { readFileSync, writeFileSync } = require("fs") 6 | const pkg = JSON.parse( 7 | readFileSync(path.resolve(__dirname, "..", "package.json")) 8 | ) 9 | 10 | pkg.scripts.prepush = "npm run test:prod && npm run build" 11 | pkg.scripts.commitmsg = "commitlint -E GIT_PARAMS" 12 | 13 | writeFileSync( 14 | path.resolve(__dirname, "..", "package.json"), 15 | JSON.stringify(pkg, null, 2) 16 | ) 17 | 18 | // Call husky to set up the hooks 19 | fork(path.resolve(__dirname, "..", "node_modules", "husky", "bin", "install")) 20 | 21 | console.log() 22 | console.log(colors.green("Done!!")) 23 | console.log() 24 | 25 | if (pkg.repository.url.trim()) { 26 | console.log(colors.cyan("Now run:")) 27 | console.log(colors.cyan(" npm install -g semantic-release-cli")) 28 | console.log(colors.cyan(" semantic-release-cli setup")) 29 | console.log() 30 | console.log( 31 | colors.cyan('Important! Answer NO to "Generate travis.yml" question') 32 | ) 33 | console.log() 34 | console.log( 35 | colors.gray( 36 | 'Note: Make sure "repository.url" in your package.json is correct before' 37 | ) 38 | ) 39 | } else { 40 | console.log( 41 | colors.red( 42 | 'First you need to set the "repository.url" property in package.json' 43 | ) 44 | ) 45 | console.log(colors.cyan("Then run:")) 46 | console.log(colors.cyan(" npm install -g semantic-release-cli")) 47 | console.log(colors.cyan(" semantic-release-cli setup")) 48 | console.log() 49 | console.log( 50 | colors.cyan('Important! Answer NO to "Generate travis.yml" question') 51 | ) 52 | } 53 | 54 | console.log() 55 | -------------------------------------------------------------------------------- /packages/react-native/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es5", 5 | "module":"es2015", 6 | "lib": ["es2015", "es2016", "es2017"], 7 | "strict": true, 8 | "sourceMap": true, 9 | "declaration": true, 10 | "allowSyntheticDefaultImports": true, 11 | "experimentalDecorators": true, 12 | "emitDecoratorMetadata": true, 13 | "declarationDir": "dist/types", 14 | "outDir": "dist/lib", 15 | "skipLibCheck": true, 16 | "typeRoots": ["node_modules/@types"] 17 | }, 18 | "include": [ 19 | "src" 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /packages/react-native/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint-config-standard", 4 | "tslint-config-prettier" 5 | ] 6 | } -------------------------------------------------------------------------------- /packages/react-scl/.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/react-scl/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .DS_Store 5 | *.log 6 | .vscode 7 | .idea 8 | dist 9 | compiled 10 | .awcache 11 | .rpt2_cache 12 | docs 13 | -------------------------------------------------------------------------------- /packages/react-scl/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | branches: 3 | only: 4 | - master 5 | - /^greenkeeper/.*$/ 6 | cache: 7 | yarn: true 8 | directories: 9 | - node_modules 10 | notifications: 11 | email: false 12 | node_js: 13 | - node 14 | script: 15 | - npm run test:prod && npm run build 16 | after_success: 17 | - npm run report-coverage 18 | - npm run deploy-docs 19 | - npm run semantic-release 20 | -------------------------------------------------------------------------------- /packages/react-scl/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/react-scl/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Vineeth George 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /packages/react-scl/backup/src/!!ProducerInterface.ts: -------------------------------------------------------------------------------- 1 | import { ReactElement } from 'react' 2 | 3 | export interface ProducerInterfaceConstructor { 4 | new(condition: (item: T) => boolean, view : ReactElement): ProducerInterface 5 | } 6 | 7 | export interface ProducerInterface { 8 | /*producerObj: { 9 | condition: (item: T) => boolean, 10 | view: ReactElement 11 | }*/ 12 | canProduceView: (item: T) => boolean 13 | produceView: () => ReactElement 14 | } 15 | 16 | -------------------------------------------------------------------------------- /packages/react-scl/backup/src/List.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ListInterface from './ListInterface' 3 | 4 | 5 | class List extends React.Component implements ListInterface { 6 | 7 | constructor(props: any) { 8 | super(props) 9 | } 10 | 11 | getInt() { 12 | return 123 13 | console.log('hello') 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/react-scl/backup/src/ListInterface.ts: -------------------------------------------------------------------------------- 1 | export default abstract class ListInterface { 2 | 3 | abstract getInt: () => void 4 | 5 | } 6 | -------------------------------------------------------------------------------- /packages/react-scl/backup/src/MessageListManager.tsx: -------------------------------------------------------------------------------- 1 | import React, { ReactElement } from 'react' 2 | import { ChannelReferencingMessage } from '@mitter-io/models' 3 | import MessageList from './MessageList' 4 | import { Producer } from './Producer/Producer' 5 | import { getViewFromProducer } from './ViewProducers/utils' 6 | 7 | interface MessageListManagerProps { 8 | messages: ChannelReferencingMessage[] 9 | onComponentMount?: () => void 10 | onComponentUpdate?: (currentProps: object, prevProps: object) => void 11 | producers: Producer[] | undefined 12 | defaultView: (item: ChannelReferencingMessage) => ReactElement 13 | onEndCallback: () => void 14 | loader: () => ReactElement 15 | isLoading: boolean 16 | } 17 | 18 | 19 | interface MessageListManagerState { 20 | 21 | } 22 | 23 | export class MessageListManager extends React.Component { 24 | 25 | private scrollToIndex: number = 0 26 | constructor(props: MessageListManagerProps) { 27 | super(props) 28 | this.getViewFromProducer = this.getViewFromProducer.bind(this) 29 | } 30 | 31 | componentWillUpdate(nextProps:MessageListManagerProps) { 32 | this.scrollToIndex = nextProps.messages.length - this.props.messages.length 33 | console.log('%c scroll to index'+ this.scrollToIndex, 'color:pink') 34 | 35 | } 36 | 37 | /*getSnapshotBeforeUpdate(prevProps: MessageListManagerProps) { 38 | this.scrollToIndex = this.props.messages.length - prevProps.messages.length 39 | console.log('%c scroll to index'+ this.scrollToIndex, 'color:pink') 40 | }*/ 41 | 42 | componentDidMount() { 43 | if(typeof this.props.onComponentMount === 'function'){ 44 | this.props.onComponentMount() 45 | } 46 | } 47 | 48 | componentDidUpdate(prevProps: MessageListManagerProps) { 49 | if(typeof this.props.onComponentUpdate === 'function'){ 50 | this.props.onComponentUpdate(this.props, prevProps) 51 | } 52 | } 53 | 54 | getViewFromProducer(item: ChannelReferencingMessage) { 55 | return getViewFromProducer(this.props.producers,item,this.props.defaultView) 56 | } 57 | 58 | render() { 59 | return ( 60 | 67 | ) 68 | } 69 | } 70 | 71 | -------------------------------------------------------------------------------- /packages/react-scl/backup/src/Producer/Producer.ts: -------------------------------------------------------------------------------- 1 | import { ReactElement } from 'react' 2 | 3 | export type ProducerConfigs = { 4 | condition: (item: C) => boolean, 5 | view: (item: C) => ReactElement 6 | } 7 | 8 | 9 | export class Producer { 10 | 11 | private condition: ProducerConfigs['condition'] 12 | private view: ProducerConfigs['view'] 13 | constructor(condition: ProducerConfigs['condition'], view: ProducerConfigs['view']) { 14 | this.condition = condition 15 | this.view = view 16 | 17 | } 18 | 19 | canProduceView(item: T){ 20 | return this.condition(item) || false 21 | } 22 | 23 | produceView(item: T) { 24 | return this.view(item) 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /packages/react-scl/backup/src/ViewProducers/channelViewProducer.ts: -------------------------------------------------------------------------------- 1 | import { Producer, ProducerConfigs } from '../Producer/Producer' 2 | import {Channel} from '@mitter-io/models' 3 | 4 | export function createChannelViewProducer( 5 | condition: ProducerConfigs['condition'], 6 | view: ProducerConfigs['view'] 7 | ) { 8 | return new Producer(condition,view) 9 | } 10 | -------------------------------------------------------------------------------- /packages/react-scl/backup/src/ViewProducers/messageViewProducer.ts: -------------------------------------------------------------------------------- 1 | import { ChannelReferencingMessage } from '@mitter-io/models' 2 | import { Producer, ProducerConfigs } from '../Producer/Producer' 3 | 4 | export function createMessageViewProducer( 5 | condition: ProducerConfigs['condition'], 6 | view: ProducerConfigs['view'] 7 | ) 8 | { 9 | return new Producer(condition,view) 10 | } 11 | -------------------------------------------------------------------------------- /packages/react-scl/backup/src/ViewProducers/utils.ts: -------------------------------------------------------------------------------- 1 | import { ReactElement } from 'react' 2 | import { Producer } from '../Producer/Producer' 3 | 4 | 5 | export function getViewFromProducer(producers: Producer[] | undefined, 6 | item: T, 7 | defaultView: (item: T) => ReactElement): ReactElement { 8 | const producedView = defaultView 9 | if(producers !== undefined) { 10 | const viewProducingProducers = producers.filter(producer => { 11 | return ( producer.canProduceView(item) === true ) 12 | }) 13 | 14 | if (viewProducingProducers.length === 0) { 15 | return producedView(item) 16 | } 17 | return viewProducingProducers[0].produceView(item) 18 | } 19 | return producedView(item) 20 | } 21 | -------------------------------------------------------------------------------- /packages/react-scl/backup/src/mitter-react-component-library.ts: -------------------------------------------------------------------------------- 1 | // Import here Polyfills if needed. Recommended core-js (npm i -D core-js) 2 | // import "core-js/fn/array.find" 3 | // ... 4 | export * from './ViewProducers/channelViewProducer' 5 | export * from './ViewProducers/messageViewProducer' 6 | export * from './MessageListManager' 7 | 8 | -------------------------------------------------------------------------------- /packages/react-scl/backup/statefulSrc/src/!!ProducerInterface.ts: -------------------------------------------------------------------------------- 1 | import { ReactElement } from 'react' 2 | 3 | export interface ProducerInterfaceConstructor { 4 | new(condition: (item: T) => boolean, view : ReactElement): ProducerInterface 5 | } 6 | 7 | export interface ProducerInterface { 8 | /*producerObj: { 9 | condition: (item: T) => boolean, 10 | view: ReactElement 11 | }*/ 12 | canProduceView: (item: T) => boolean 13 | produceView: () => ReactElement 14 | } 15 | 16 | -------------------------------------------------------------------------------- /packages/react-scl/backup/statefulSrc/src/List.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ListInterface from './ListInterface' 3 | 4 | 5 | class List extends React.Component implements ListInterface { 6 | 7 | constructor(props: any) { 8 | super(props) 9 | } 10 | 11 | getInt() { 12 | return 123 13 | console.log('hello') 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /packages/react-scl/backup/statefulSrc/src/ListInterface.ts: -------------------------------------------------------------------------------- 1 | export default abstract class ListInterface { 2 | 3 | abstract getInt: () => void 4 | 5 | } 6 | -------------------------------------------------------------------------------- /packages/react-scl/backup/statefulSrc/src/MessageListManager.tsx: -------------------------------------------------------------------------------- 1 | import React, { ReactElement } from 'react' 2 | import { ChannelReferencingMessage } from '@mitter-io/models' 3 | import MessageList from './MessageList' 4 | import { Producer } from './Producer/Producer' 5 | import { getViewFromProducer } from './ViewProducers/utils' 6 | 7 | interface MessageListManagerProps { 8 | messages: any[] 9 | onComponentMount?: () => void 10 | onComponentUpdate?: (currentProps: object, prevProps: object) => void 11 | producers: Producer[] | undefined 12 | defaultView: (item: ChannelReferencingMessage) => ReactElement 13 | onEndCallback: () => void 14 | loader: () => ReactElement 15 | isLoading: boolean 16 | } 17 | 18 | 19 | interface MessageListManagerState { 20 | 21 | } 22 | 23 | export class MessageListManager extends React.Component { 24 | 25 | private scrollToIndex: number = -1 26 | constructor(props: MessageListManagerProps) { 27 | super(props) 28 | this.getViewFromProducer = this.getViewFromProducer.bind(this) 29 | } 30 | 31 | componentWillUpdate(nextProps:MessageListManagerProps) { 32 | this.scrollToIndex = nextProps.messages.length - this.props.messages.length 33 | console.log('%c scroll to index'+ this.scrollToIndex, 'color:pink') 34 | 35 | } 36 | 37 | /*getSnapshotBeforeUpdate(prevProps: MessageListManagerProps) { 38 | this.scrollToIndex = this.props.messages.length - prevProps.messages.length 39 | console.log('%c scroll to index'+ this.scrollToIndex, 'color:pink') 40 | }*/ 41 | 42 | componentDidMount() { 43 | if(typeof this.props.onComponentMount === 'function'){ 44 | this.props.onComponentMount() 45 | } 46 | } 47 | 48 | componentDidUpdate(prevProps: MessageListManagerProps) { 49 | if(typeof this.props.onComponentUpdate === 'function'){ 50 | this.props.onComponentUpdate(this.props, prevProps) 51 | } 52 | } 53 | 54 | getViewFromProducer(item: ChannelReferencingMessage) { 55 | return getViewFromProducer(this.props.producers,item,this.props.defaultView) 56 | } 57 | 58 | render() { 59 | const messages = this.props.messages.slice() 60 | messages.push('loading') 61 | return ( 62 | 68 | ) 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /packages/react-scl/backup/statefulSrc/src/Producer/Producer.ts: -------------------------------------------------------------------------------- 1 | import { ReactElement } from 'react' 2 | 3 | export type ProducerConfigs = { 4 | condition: (item: C) => boolean, 5 | view: (item: C) => ReactElement 6 | } 7 | 8 | 9 | export class Producer { 10 | 11 | private condition: ProducerConfigs['condition'] 12 | private view: ProducerConfigs['view'] 13 | constructor(condition: ProducerConfigs['condition'], view: ProducerConfigs['view']) { 14 | this.condition = condition 15 | this.view = view 16 | 17 | } 18 | 19 | canProduceView(item: T){ 20 | return this.condition(item) || false 21 | } 22 | 23 | produceView(item: T) { 24 | return this.view(item) 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /packages/react-scl/backup/statefulSrc/src/ViewProducers/channelViewProducer.ts: -------------------------------------------------------------------------------- 1 | import { Producer, ProducerConfigs } from '../Producer/Producer' 2 | import {Channel} from '@mitter-io/models' 3 | 4 | export function createChannelViewProducer( 5 | condition: ProducerConfigs['condition'], 6 | view: ProducerConfigs['view'] 7 | ) { 8 | return new Producer(condition,view) 9 | } 10 | -------------------------------------------------------------------------------- /packages/react-scl/backup/statefulSrc/src/ViewProducers/messageViewProducer.ts: -------------------------------------------------------------------------------- 1 | import { ChannelReferencingMessage } from '@mitter-io/models' 2 | import { Producer, ProducerConfigs } from '../Producer/Producer' 3 | 4 | export function createMessageViewProducer( 5 | condition: ProducerConfigs['condition'], 6 | view: ProducerConfigs['view'] 7 | ) 8 | { 9 | return new Producer(condition,view) 10 | } 11 | -------------------------------------------------------------------------------- /packages/react-scl/backup/statefulSrc/src/ViewProducers/utils.ts: -------------------------------------------------------------------------------- 1 | import { ReactElement } from 'react' 2 | import { Producer } from '../Producer/Producer' 3 | 4 | 5 | export function getViewFromProducer(producers: Producer[] | undefined, 6 | item: T, 7 | defaultView: (item: T) => ReactElement): ReactElement { 8 | const producedView = defaultView 9 | if(producers !== undefined) { 10 | const viewProducingProducers = producers.filter(producer => { 11 | return ( producer.canProduceView(item) === true ) 12 | }) 13 | 14 | if (viewProducingProducers.length === 0) { 15 | return producedView(item) 16 | } 17 | return viewProducingProducers[0].produceView(item) 18 | } 19 | return producedView(item) 20 | } 21 | -------------------------------------------------------------------------------- /packages/react-scl/backup/statefulSrc/src/mitter-react-component-library.ts: -------------------------------------------------------------------------------- 1 | // Import here Polyfills if needed. Recommended core-js (npm i -D core-js) 2 | // import "core-js/fn/array.find" 3 | // ... 4 | export * from './ViewProducers/channelViewProducer' 5 | export * from './ViewProducers/messageViewProducer' 6 | export * from './MessageListManager' 7 | 8 | -------------------------------------------------------------------------------- /packages/react-scl/code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at alexjovermorales@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /packages/react-scl/rollup.config.ts: -------------------------------------------------------------------------------- 1 | import resolve from 'rollup-plugin-node-resolve' 2 | import commonjs from 'rollup-plugin-commonjs' 3 | import sourceMaps from 'rollup-plugin-sourcemaps' 4 | import camelCase from 'lodash.camelcase' 5 | import typescript from 'rollup-plugin-typescript2' 6 | import json from 'rollup-plugin-json' 7 | import builtins from 'rollup-plugin-node-builtins' 8 | import globals from 'rollup-plugin-node-globals' 9 | 10 | const pkg = require('./package.json') 11 | 12 | const libraryName = 'mitter-react-component-library' 13 | 14 | export default { 15 | input: `src/${libraryName}.ts`, 16 | output: [ 17 | { file: pkg.main, name: camelCase(libraryName), format: 'umd', sourcemap: true }, 18 | { file: pkg.module, format: 'es', sourcemap: true }, 19 | ], 20 | // Indicate here external modules you don't wanna include in your bundle (i.e.: 'lodash') 21 | external: ['react', 'react-dom'], 22 | watch: { 23 | include: ['src/**', 'node_modules'] 24 | }, 25 | globals: { 26 | 'react': 'React', 27 | 'react-dom': 'ReactDOM' 28 | }, 29 | plugins: [ 30 | // Allow json resolution 31 | json(), 32 | // Allow node_modules resolution, so you can use 'external' to control 33 | // Compile TypeScript files 34 | typescript({ useTsconfigDeclarationDir: true }), 35 | // Allow bundling cjs modules (unlike webpack, rollup doesn't understand cjs) 36 | 37 | // which external modules to include in the bundle 38 | // https://github.com/rollup/rollup-plugin-node-resolve#usage 39 | 40 | // Resolve source maps to the original source 41 | sourceMaps(), 42 | ], 43 | } 44 | -------------------------------------------------------------------------------- /packages/react-scl/src/!!ProducerInterface.ts: -------------------------------------------------------------------------------- 1 | import { ReactElement } from 'react' 2 | 3 | export interface ProducerInterfaceConstructor { 4 | new (condition: (item: T) => boolean, view: ReactElement): ProducerInterface 5 | } 6 | export interface ProducerInterface { 7 | /*producerObj: { 8 | condition: (item: T) => boolean, 9 | view: ReactElement 10 | }*/ 11 | canProduceView: (item: T) => boolean 12 | produceView: () => ReactElement 13 | } 14 | -------------------------------------------------------------------------------- /packages/react-scl/src/List.tsx: -------------------------------------------------------------------------------- 1 | import React from 'react' 2 | import ListInterface from './ListInterface' 3 | 4 | class List extends React.Component implements ListInterface { 5 | 6 | constructor(props: any) { 7 | super(props) 8 | } 9 | 10 | getInt() { 11 | return 123 12 | console.log('hello') 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/react-scl/src/ListInterface.ts: -------------------------------------------------------------------------------- 1 | export default abstract class ListInterface { 2 | abstract getInt: () => void 3 | } 4 | -------------------------------------------------------------------------------- /packages/react-scl/src/MessageListManager.tsx: -------------------------------------------------------------------------------- 1 | import React, { ReactElement } from 'react' 2 | import { ChannelReferencingMessage } from '@mitter-io/models' 3 | import MessageList from './MessageList' 4 | import { Producer } from './Producer/Producer' 5 | import { getViewFromProducer } from './ViewProducers/utils' 6 | 7 | interface MessageListManagerProps { 8 | messages: ChannelReferencingMessage[] 9 | onComponentMount?: () => void 10 | onComponentUpdate?: (currentProps: object, prevProps: object) => void 11 | producers: Producer[] | undefined 12 | defaultView: (item: ChannelReferencingMessage) => ReactElement 13 | onEndCallback: () => void 14 | loader: () => ReactElement 15 | isLoading: boolean 16 | scrollToIndex?: number 17 | } 18 | 19 | 20 | interface MessageListManagerState { 21 | 22 | } 23 | 24 | export class MessageListManager extends React.PureComponent { 25 | private scrollToIndex: number = -1 26 | private _internalMessageList: React.RefObject 27 | 28 | constructor(props: MessageListManagerProps) { 29 | super(props) 30 | this.getViewFromProducer = this.getViewFromProducer.bind(this) 31 | this._internalMessageList = React.createRef() 32 | } 33 | 34 | scrollToBottom() { 35 | if (this._internalMessageList.current) { 36 | this._internalMessageList.current.scrollToBottom() 37 | } 38 | } 39 | 40 | componentWillUpdate(nextProps:MessageListManagerProps) { 41 | this.scrollToIndex = nextProps.messages.length - this.props.messages.length - 1 42 | console.log('%c scroll to index'+ this.scrollToIndex, 'color:pink') 43 | 44 | } 45 | 46 | /* getSnapshotBeforeUpdate(prevProps: MessageListManagerProps) { 47 | this.scrollToIndex = this.props.messages.length - prevProps.messages.length 48 | console.log('%c scroll to index'+ this.scrollToIndex, 'color:pink') 49 | } */ 50 | 51 | componentDidMount() { 52 | if(typeof this.props.onComponentMount === 'function'){ 53 | this.props.onComponentMount() 54 | } 55 | } 56 | 57 | componentDidUpdate(prevProps: MessageListManagerProps) { 58 | if(typeof this.props.onComponentUpdate === 'function'){ 59 | this.props.onComponentUpdate(this.props, prevProps) 60 | } 61 | } 62 | 63 | getViewFromProducer(item: ChannelReferencingMessage) { 64 | return getViewFromProducer(this.props.producers,item,this.props.defaultView) 65 | } 66 | 67 | render() { 68 | return ( 69 | 78 | ) 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /packages/react-scl/src/Producer/Producer.ts: -------------------------------------------------------------------------------- 1 | import { ReactElement } from 'react' 2 | 3 | export type ProducerConfigs = { 4 | condition: (item: C) => boolean 5 | view: (item: C) => ReactElement 6 | } 7 | 8 | export class Producer { 9 | private condition: ProducerConfigs['condition'] 10 | private view: ProducerConfigs['view'] 11 | constructor(condition: ProducerConfigs['condition'], view: ProducerConfigs['view']) { 12 | this.condition = condition 13 | this.view = view 14 | } 15 | 16 | canProduceView(item: T) { 17 | return this.condition(item) || false 18 | } 19 | 20 | produceView(item: T) { 21 | return this.view(item) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/react-scl/src/ViewProducers/channelViewProducer.ts: -------------------------------------------------------------------------------- 1 | import { Producer, ProducerConfigs } from '../Producer/Producer' 2 | import { Channel } from '@mitter-io/models' 3 | 4 | export function createChannelViewProducer( 5 | condition: ProducerConfigs['condition'], 6 | view: ProducerConfigs['view'] 7 | ) { 8 | return new Producer(condition, view) 9 | } 10 | -------------------------------------------------------------------------------- /packages/react-scl/src/ViewProducers/messageViewProducer.ts: -------------------------------------------------------------------------------- 1 | import { ChannelReferencingMessage } from '@mitter-io/models' 2 | import { Producer, ProducerConfigs } from '../Producer/Producer' 3 | 4 | export function createMessageViewProducer( 5 | condition: ProducerConfigs['condition'], 6 | view: ProducerConfigs['view'] 7 | ) { 8 | return new Producer(condition, view) 9 | } 10 | -------------------------------------------------------------------------------- /packages/react-scl/src/ViewProducers/utils.ts: -------------------------------------------------------------------------------- 1 | import { ReactElement } from 'react' 2 | import { Producer } from '../Producer/Producer' 3 | 4 | export function getViewFromProducer( 5 | producers: Producer[] | undefined, 6 | item: T, 7 | defaultView: (item: T) => ReactElement 8 | ): ReactElement { 9 | const producedView = defaultView 10 | if (producers !== undefined) { 11 | const viewProducingProducers = producers.filter(producer => { 12 | return producer.canProduceView(item) === true 13 | }) 14 | 15 | if (viewProducingProducers.length === 0) { 16 | return producedView(item) 17 | } 18 | return viewProducingProducers[0].produceView(item) 19 | } 20 | return producedView(item) 21 | } 22 | -------------------------------------------------------------------------------- /packages/react-scl/src/mitter-react-component-library.ts: -------------------------------------------------------------------------------- 1 | // Import here Polyfills if needed. Recommended core-js (npm i -D core-js) 2 | // import "core-js/fn/array.find" 3 | // ... 4 | export * from './ViewProducers/channelViewProducer' 5 | export * from './ViewProducers/messageViewProducer' 6 | export * from './MessageListManager' 7 | export * from './MessageWindow' 8 | export * from './MessageWindowManager' 9 | -------------------------------------------------------------------------------- /packages/react-scl/src/utils.ts: -------------------------------------------------------------------------------- 1 | import {Message} from "@mitter-io/models"; 2 | import {Identifier, ChannelReferencingMessage} from "@mitter-io/models"; 3 | 4 | function getRandomInt(max: number) { 5 | return Math.floor(Math.random() * Math.floor(max)); 6 | } 7 | 8 | export function getChannelReferencingMessage(channelId:string, message: Message): ChannelReferencingMessage { 9 | return new ChannelReferencingMessage( 10 | {identifier: channelId}, 11 | message.messageId as string, 12 | message.messageType, 13 | message.payloadType, 14 | message.senderId as Identifier, 15 | message.textPayload, 16 | message.messageData, 17 | message.timelineEvents, 18 | message.entityMetadata, 19 | message.auditInfo, 20 | message.sender 21 | ) 22 | } 23 | -------------------------------------------------------------------------------- /packages/react-scl/test/mitter-react-component-library.test.ts: -------------------------------------------------------------------------------- 1 | import DummyClass from '../src/mitter-react-component-library' 2 | 3 | /** 4 | * Dummy test 5 | */ 6 | describe('Dummy test', () => { 7 | it('works if true is truthy', () => { 8 | expect(true).toBeTruthy() 9 | }) 10 | 11 | it('DummyClass is instantiable', () => { 12 | expect(new DummyClass()).toBeInstanceOf(DummyClass) 13 | }) 14 | }) 15 | -------------------------------------------------------------------------------- /packages/react-scl/tools/gh-pages-publish.ts: -------------------------------------------------------------------------------- 1 | const { cd, exec, echo, touch } = require("shelljs") 2 | const { readFileSync } = require("fs") 3 | const url = require("url") 4 | 5 | let repoUrl 6 | let pkg = JSON.parse(readFileSync("package.json") as any) 7 | if (typeof pkg.repository === "object") { 8 | if (!pkg.repository.hasOwnProperty("url")) { 9 | throw new Error("URL does not exist in repository section") 10 | } 11 | repoUrl = pkg.repository.url 12 | } else { 13 | repoUrl = pkg.repository 14 | } 15 | 16 | let parsedUrl = url.parse(repoUrl) 17 | let repository = (parsedUrl.host || "") + (parsedUrl.path || "") 18 | let ghToken = process.env.GH_TOKEN 19 | 20 | echo("Deploying docs!!!") 21 | cd("docs") 22 | touch(".nojekyll") 23 | exec("git init") 24 | exec("git add .") 25 | exec('git config user.name "Vineeth George"') 26 | exec('git config user.email "vineeth@mitter.io"') 27 | exec('git commit -m "docs(docs): update gh-pages"') 28 | exec( 29 | `git push --force --quiet "https://${ghToken}@${repository}" master:gh-pages` 30 | ) 31 | echo("Docs deployed!!") 32 | -------------------------------------------------------------------------------- /packages/react-scl/tools/semantic-release-prepare.ts: -------------------------------------------------------------------------------- 1 | const path = require("path") 2 | const { fork } = require("child_process") 3 | const colors = require("colors") 4 | 5 | const { readFileSync, writeFileSync } = require("fs") 6 | const pkg = JSON.parse( 7 | readFileSync(path.resolve(__dirname, "..", "package.json")) 8 | ) 9 | 10 | pkg.scripts.prepush = "npm run test:prod && npm run build" 11 | pkg.scripts.commitmsg = "commitlint -E GIT_PARAMS" 12 | 13 | writeFileSync( 14 | path.resolve(__dirname, "..", "package.json"), 15 | JSON.stringify(pkg, null, 2) 16 | ) 17 | 18 | // Call husky to set up the hooks 19 | fork(path.resolve(__dirname, "..", "node_modules", "husky", "bin", "install")) 20 | 21 | console.log() 22 | console.log(colors.green("Done!!")) 23 | console.log() 24 | 25 | if (pkg.repository.url.trim()) { 26 | console.log(colors.cyan("Now run:")) 27 | console.log(colors.cyan(" npm install -g semantic-release-cli")) 28 | console.log(colors.cyan(" semantic-release-cli setup")) 29 | console.log() 30 | console.log( 31 | colors.cyan('Important! Answer NO to "Generate travis.yml" question') 32 | ) 33 | console.log() 34 | console.log( 35 | colors.gray( 36 | 'Note: Make sure "repository.url" in your package.json is correct before' 37 | ) 38 | ) 39 | } else { 40 | console.log( 41 | colors.red( 42 | 'First you need to set the "repository.url" property in package.json' 43 | ) 44 | ) 45 | console.log(colors.cyan("Then run:")) 46 | console.log(colors.cyan(" npm install -g semantic-release-cli")) 47 | console.log(colors.cyan(" semantic-release-cli setup")) 48 | console.log() 49 | console.log( 50 | colors.cyan('Important! Answer NO to "Generate travis.yml" question') 51 | ) 52 | } 53 | 54 | console.log() 55 | -------------------------------------------------------------------------------- /packages/react-scl/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es5", 5 | "module":"es2015", 6 | "lib": ["es2015", "es2016", "es2017", "dom"], 7 | "strict": true, 8 | "sourceMap": true, 9 | "declaration": true, 10 | "jsx": "react", 11 | "allowSyntheticDefaultImports": true, 12 | "experimentalDecorators": true, 13 | "emitDecoratorMetadata": true, 14 | "declarationDir": "dist/types", 15 | "outDir": "dist/lib", 16 | "typeRoots": [ 17 | "node_modules/@types" 18 | ] 19 | }, 20 | "include": [ 21 | "src" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/react-scl/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint-config-standard", 4 | "tslint-config-prettier" 5 | ] 6 | } -------------------------------------------------------------------------------- /packages/web/.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/web/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | .nyc_output 4 | .DS_Store 5 | *.log 6 | .vscode 7 | .idea 8 | dist 9 | compiled 10 | .awcache 11 | .rpt2_cache 12 | docs 13 | -------------------------------------------------------------------------------- /packages/web/.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | branches: 3 | only: 4 | - master 5 | - /^greenkeeper/.*$/ 6 | cache: 7 | yarn: true 8 | directories: 9 | - node_modules 10 | notifications: 11 | email: false 12 | node_js: 13 | - node 14 | script: 15 | - npm run test:prod && npm run build 16 | after_success: 17 | - npm run report-coverage 18 | - npm run deploy-docs 19 | - npm run semantic-release 20 | -------------------------------------------------------------------------------- /packages/web/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/web/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2017 Rohan Prabhu <> 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /packages/web/README.md: -------------------------------------------------------------------------------- 1 | # @mitter-io/web 2 | 3 | Web SDK for working with mitter.io. 4 | -------------------------------------------------------------------------------- /packages/web/code-of-conduct.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, gender identity and expression, level of experience, 9 | nationality, personal appearance, race, religion, or sexual identity and 10 | orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at alexjovermorales@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at [http://contributor-covenant.org/version/1/4][version] 72 | 73 | [homepage]: http://contributor-covenant.org 74 | [version]: http://contributor-covenant.org/version/1/4/ 75 | -------------------------------------------------------------------------------- /packages/web/mitter-web.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /packages/web/rollup.config.ts: -------------------------------------------------------------------------------- 1 | import resolve from 'rollup-plugin-node-resolve' 2 | import commonjs from 'rollup-plugin-commonjs' 3 | import sourceMaps from 'rollup-plugin-sourcemaps' 4 | import camelCase from 'lodash.camelcase' 5 | import typescript from 'rollup-plugin-typescript2' 6 | import json from 'rollup-plugin-json' 7 | import builtins from 'rollup-plugin-node-builtins' 8 | import globals from 'rollup-plugin-node-globals' 9 | import replace from 'rollup-plugin-replace' 10 | 11 | const pkg = require('./package.json') 12 | 13 | const libraryName = 'mitter-web' 14 | 15 | export default { 16 | input: `src/${libraryName}.ts`, 17 | output: [ 18 | { file: pkg.main, name: camelCase(libraryName), format: 'umd', sourcemap: true }, 19 | { file: pkg.module, format: 'es', sourcemap: true }, 20 | ], 21 | // Indicate here external modules you don't wanna include in your bundle (i.e.: 'lodash') 22 | external: [ 23 | 'websocket', 24 | 'query-string', 25 | 'nanoid' 26 | ], 27 | watch: { 28 | include: ['src/**', './../mitter-ts-core/dist/**'] 29 | }, 30 | plugins: [ 31 | replace({ 32 | 'process.version.': '"v9.5.0".', 33 | delimiters: ['', ''] 34 | }), 35 | 36 | 37 | resolve({ 38 | browser: true, 39 | jsnext: true 40 | }), 41 | 42 | commonjs(), 43 | 44 | globals(), 45 | json(), 46 | 47 | builtins(), 48 | 49 | typescript({ useTsconfigDeclarationDir: true }), 50 | 51 | // Resolve source maps to the original source 52 | sourceMaps() 53 | ] 54 | } 55 | -------------------------------------------------------------------------------- /packages/web/src/drivers/WebSocketConstants.ts: -------------------------------------------------------------------------------- 1 | export const heartbeatIncomingMs = 5000 2 | export const heartbearOutgoingMs = 5000 3 | export const reconnect_delay = 300 4 | export const webSocketInitSubscriptionsPrefix = '/channels/open/' 5 | -------------------------------------------------------------------------------- /packages/web/src/drivers/WebSocketStandardHeaders.ts: -------------------------------------------------------------------------------- 1 | export default { 2 | MitterUserAuthorization: 'user-authorization', 3 | MitterApplicationId: 'application-id', 4 | DeliveryTargetId: 'delivery-target-id', 5 | InitSubscriptions: 'init-subscriptions', 6 | Receipt: 'receipt', 7 | ReceiptFromServer: 'receipt-id' 8 | } 9 | 10 | -------------------------------------------------------------------------------- /packages/web/src/kv-store/KvStore.tsx: -------------------------------------------------------------------------------- 1 | import { KvStore as MitterKvStore } from '@mitter-io/core' 2 | 3 | declare var localStorage: any 4 | 5 | export default class KvStore implements MitterKvStore { 6 | async getItem(key: string): Promise { 7 | let item = localStorage.getItem(key) 8 | 9 | if (item === null) { 10 | return undefined 11 | } 12 | 13 | return JSON.parse(item) as T 14 | } 15 | 16 | async setItem(key: string, value: T): Promise { 17 | localStorage.setItem(key, JSON.stringify(value)) 18 | } 19 | 20 | async removeItem(key: string): Promise { 21 | localStorage.removeItem(key) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/web/src/mitter-web.ts: -------------------------------------------------------------------------------- 1 | import { Mitter as MitterCore, MitterConstants, PlatformImplementedFeatures, MitterCoreConfig, MitterUserConfig, MitterUserCbs } from '@mitter-io/core' 2 | import WebKvStore from './kv-store/KvStore' 3 | import WebSocketPipelineDriver from './drivers/WebSocketMessagingPipelineDriver' 4 | import {getDefaultMitterUserCbs, getMitterCoreConfig} from './utils'; 5 | import nanoid from 'nanoid' 6 | 7 | export const Mitter = { 8 | forWeb: function( 9 | mitterUserConfig: MitterUserConfig, 10 | mitterUserCbs?: Partial 11 | ): MitterCore { 12 | return new MitterCore( 13 | getMitterCoreConfig(mitterUserConfig), 14 | getDefaultMitterUserCbs(mitterUserCbs), 15 | new WebKvStore(), 16 | new WebSocketPipelineDriver(), 17 | window, 18 | { 19 | randomIdGenerator: nanoid 20 | } as PlatformImplementedFeatures 21 | ) 22 | } 23 | } 24 | 25 | -------------------------------------------------------------------------------- /packages/web/src/utils.ts: -------------------------------------------------------------------------------- 1 | // tslint:disable-next-line:no-empty 2 | import {MitterConstants, MitterCoreConfig, MitterUserConfig, MitterUserCbs } from "@mitter-io/core"; 3 | 4 | export const noOp = () => {} 5 | 6 | export function getMitterCoreConfig(mitterUserConfig: MitterUserConfig): MitterCoreConfig { 7 | return { 8 | weaverUrl: MitterConstants.WeaverUrl, 9 | mitterApiBaseUrl: MitterConstants.MitterApiUrl, 10 | initMessagingPipelineSubscriptions: [], 11 | disableXHRCaching: true, 12 | ...mitterUserConfig, 13 | } 14 | } 15 | 16 | 17 | export function getDefaultMitterUserCbs(hooks: Partial = {}): MitterUserCbs { 18 | return { 19 | mitterInstanceReady: () => {}, 20 | onTokenExpire: [noOp], 21 | onMessagingPipelineConnectCbs: [noOp], 22 | ...hooks 23 | } 24 | } 25 | 26 | -------------------------------------------------------------------------------- /packages/web/test/mitter-web.test.ts: -------------------------------------------------------------------------------- 1 | import DummyClass from '../src/mitter-web' 2 | 3 | /** 4 | * Dummy test 5 | */ 6 | describe('Dummy test', () => { 7 | it('works if true is truthy', () => { 8 | expect(true).toBeTruthy() 9 | }) 10 | 11 | it('DummyClass is instantiable', () => { 12 | expect(new DummyClass()).toBeInstanceOf(DummyClass) 13 | }) 14 | }) 15 | -------------------------------------------------------------------------------- /packages/web/tools/gh-pages-publish.ts: -------------------------------------------------------------------------------- 1 | const { cd, exec, echo, touch } = require("shelljs") 2 | const { readFileSync } = require("fs") 3 | const url = require("url") 4 | 5 | let repoUrl 6 | let pkg = JSON.parse(readFileSync("package.json") as any) 7 | if (typeof pkg.repository === "object") { 8 | if (!pkg.repository.hasOwnProperty("url")) { 9 | throw new Error("URL does not exist in repository section") 10 | } 11 | repoUrl = pkg.repository.url 12 | } else { 13 | repoUrl = pkg.repository 14 | } 15 | 16 | let parsedUrl = url.parse(repoUrl) 17 | let repository = (parsedUrl.host || "") + (parsedUrl.path || "") 18 | let ghToken = process.env.GH_TOKEN 19 | 20 | echo("Deploying docs!!!") 21 | cd("docs") 22 | touch(".nojekyll") 23 | exec("git init") 24 | exec("git add .") 25 | exec('git config user.name "Rohan Prabhu"') 26 | exec('git config user.email ""') 27 | exec('git commit -m "docs(docs): update gh-pages"') 28 | exec( 29 | `git push --force --quiet "https://${ghToken}@${repository}" master:gh-pages` 30 | ) 31 | echo("Docs deployed!!") 32 | -------------------------------------------------------------------------------- /packages/web/tools/semantic-release-prepare.ts: -------------------------------------------------------------------------------- 1 | const path = require("path") 2 | const { fork } = require("child_process") 3 | const colors = require("colors") 4 | 5 | const { readFileSync, writeFileSync } = require("fs") 6 | const pkg = JSON.parse( 7 | readFileSync(path.resolve(__dirname, "..", "package.json")) 8 | ) 9 | 10 | pkg.scripts.prepush = "npm run test:prod && npm run build" 11 | pkg.scripts.commitmsg = "validate-commit-msg" 12 | 13 | writeFileSync( 14 | path.resolve(__dirname, "..", "package.json"), 15 | JSON.stringify(pkg, null, 2) 16 | ) 17 | 18 | // Call husky to set up the hooks 19 | fork(path.resolve(__dirname, "..", "node_modules", "husky", "bin", "install")) 20 | 21 | console.log() 22 | console.log(colors.green("Done!!")) 23 | console.log() 24 | 25 | if (pkg.repository.url.trim()) { 26 | console.log(colors.cyan("Now run:")) 27 | console.log(colors.cyan(" npm install -g semantic-release-cli")) 28 | console.log(colors.cyan(" semantic-release-cli setup")) 29 | console.log() 30 | console.log( 31 | colors.cyan('Important! Answer NO to "Generate travis.yml" question') 32 | ) 33 | console.log() 34 | console.log( 35 | colors.gray( 36 | 'Note: Make sure "repository.url" in your package.json is correct before' 37 | ) 38 | ) 39 | } else { 40 | console.log( 41 | colors.red( 42 | 'First you need to set the "repository.url" property in package.json' 43 | ) 44 | ) 45 | console.log(colors.cyan("Then run:")) 46 | console.log(colors.cyan(" npm install -g semantic-release-cli")) 47 | console.log(colors.cyan(" semantic-release-cli setup")) 48 | console.log() 49 | console.log( 50 | colors.cyan('Important! Answer NO to "Generate travis.yml" question') 51 | ) 52 | } 53 | 54 | console.log() 55 | -------------------------------------------------------------------------------- /packages/web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "moduleResolution": "node", 4 | "target": "es5", 5 | "module":"es2015", 6 | "lib": ["es2015", "es2016", "es2017", "dom"], 7 | "jsx": "react", 8 | "strict": true, 9 | "sourceMap": true, 10 | "declaration": true, 11 | "allowSyntheticDefaultImports": true, 12 | "experimentalDecorators": true, 13 | "emitDecoratorMetadata": true, 14 | "declarationDir": "dist/types", 15 | "outDir": "dist/lib", 16 | "typeRoots": [ 17 | "node_modules/@types" 18 | ] 19 | }, 20 | "include": [ 21 | "src" 22 | ] 23 | } 24 | -------------------------------------------------------------------------------- /packages/web/tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "tslint-config-standard", 4 | "tslint-config-prettier" 5 | ] 6 | } 7 | --------------------------------------------------------------------------------