{"_id":"@airtame/dove","_rev":"1-0d43848344034161deef334ad74930a3","name":"@airtame/dove","dist-tags":{"latest":"3.35.4"},"versions":{"3.35.3":{"name":"@airtame/dove","version":"3.35.3","description":"Message definitions and utilities for entities in the arc project.","main":"dist/cjs/index.js","module":"dist/esm/index.js","types":"./dist/esm/index.d.ts","scripts":{"build:cjs":"tsc --project tsconfig.cjs.json","build:esm":"tsc --project tsconfig.esm.json","build":"npm run clean && NODE_ENV=production && npm run build:cjs && npm run build:esm","clean":"rimraf ./dist","lint:fix":"eslint --fix","prettier:fix":"prettier -w ./src/**/*","test":"vitest run","release:prepare":"./scripts/prepare_release.sh $npm_config_argv"},"devDependencies":{"@typescript-eslint/eslint-plugin":"5.15.0","@typescript-eslint/parser":"5.15.0","eslint":"8.11.0","eslint-config-prettier":"8.5.0","eslint-plugin-import":"2.25.4","eslint-plugin-prettier":"4.0.0","events":"3.3.0","prettier":"2.6.0","prettier-eslint":"13.0.0","rimraf":"3.0.2","typescript":"4.6.2","vitest":"^0.31.1"},"peerDependencies":{"events":">=3.3.0"},"engines":{"node":">=16.9.0","npm":">=7.21.0"},"gitHead":"fe7c7f09d085880cedfb2fc35d91648738028f03","_id":"@airtame/dove@3.35.3","_nodeVersion":"20.4.0","_npmVersion":"9.7.2","dist":{"integrity":"sha512-ZqUS1OVwvcXsd+yWswGZ6fQu/8E6mtrCbJT790wI+oa8d+GjO2HoXfrYhCLAGWQzhxl4rx0yBnESf79B4B9Ywg==","shasum":"709172f52064e1d970d1399aa9f955df4974552c","tarball":"https://registry.npmjs.org/@airtame/dove/-/dove-3.35.3.tgz","fileCount":82,"unpackedSize":132324,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEQCIHe6Bhpb+0BGH2wltbRCdmi+KSGD2UaGlsLTQ+YOJvTJAiADA9f6vIL7KCZ5Byq2RiIJXN12VXEcnSReM4F75u7q3w=="}]},"_npmUser":{"name":"airtame-ops","email":"devops@airtame.com"},"directories":{},"maintainers":[{"name":"rene-airtame","email":"rene.hansen@airtame.com"},{"name":"airtame-ops","email":"devops@airtame.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/dove_3.35.3_1711023933476_0.5357815732059596"},"_hasShrinkwrap":false},"3.35.4":{"name":"@airtame/dove","version":"3.35.4","description":"Message definitions and utilities for entities in the arc project.","main":"dist/cjs/index.js","module":"dist/esm/index.js","types":"./dist/esm/index.d.ts","scripts":{"build:cjs":"tsc --project tsconfig.cjs.json","build:esm":"tsc --project tsconfig.esm.json","build":"npm run clean && NODE_ENV=production && npm run build:cjs && npm run build:esm","clean":"rimraf ./dist","lint:fix":"eslint --fix","prettier:fix":"prettier -w ./src/**/*","test":"vitest run","release:prepare":"./scripts/prepare_release.sh $npm_config_argv"},"devDependencies":{"@typescript-eslint/eslint-plugin":"5.15.0","@typescript-eslint/parser":"5.15.0","eslint":"8.11.0","eslint-config-prettier":"8.5.0","eslint-plugin-import":"2.25.4","eslint-plugin-prettier":"4.0.0","events":"3.3.0","prettier":"2.6.0","prettier-eslint":"13.0.0","rimraf":"3.0.2","typescript":"4.6.2","vitest":"^0.31.1"},"peerDependencies":{"events":">=3.3.0"},"engines":{"node":">=16.9.0","npm":">=7.21.0"},"gitHead":"03f25ffbfa9d0cd0016f5aa2e46ad6065d5a4475","_id":"@airtame/dove@3.35.4","_nodeVersion":"16.11.0","_npmVersion":"8.0.0","dist":{"integrity":"sha512-c5pwlHTOBD2YhRytVv10V9xWXBBtqXW8V2sVVac9eFmOw0vRhgf/ovlnyL4K1hMkZpDgU92k8YFMU0KFfb+nIw==","shasum":"0f1d6e28bdbb3df8f56f9100f7e5e2df6839ebdd","tarball":"https://registry.npmjs.org/@airtame/dove/-/dove-3.35.4.tgz","fileCount":82,"unpackedSize":132324,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIQCa7CUDBOExeSQfdvetbOLqsdDLdsT+xfRXyWkb+nDe+gIgZzTuNuZNPpJUEV3qZvfaJ7gV9SJPp6ba2cGwaVgduwM="}]},"_npmUser":{"name":"airtame-ops","email":"devops@airtame.com"},"directories":{},"maintainers":[{"name":"rene-airtame","email":"rene.hansen@airtame.com"},{"name":"airtame-ops","email":"devops@airtame.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/dove_3.35.4_1711024513472_0.1809138183426342"},"_hasShrinkwrap":false}},"time":{"created":"2024-03-21T12:25:33.377Z","3.35.3":"2024-03-21T12:25:33.676Z","modified":"2024-03-21T12:35:14.079Z","3.35.4":"2024-03-21T12:35:13.637Z"},"maintainers":[{"name":"rene-airtame","email":"rene.hansen@airtame.com"},{"name":"airtame-ops","email":"devops@airtame.com"}],"description":"Message definitions and utilities for entities in the arc project.","readme":"# [Dove](https://gitlab.com/airtame/arc/dove/-/raw/master/README.md)\n\n<!--\n> Genesis 8:6-12\n> 6 After forty days Noah opened a window he had made in the ark 7 and sent out\n> a raven, and it kept flying back and forth until the water had dried up from\n> the earth. 8 Then he sent out a dove to see if the water had receded from the\n> surface of the ground. 9 But the dove could find nowhere to perch because\n> there was water over all the surface of the earth; so it returned to Noah in\n> the ark. He reached out his hand and took the dove and brought it back to\n> himself in the ark. 10 He waited seven more days and again sent out the dove\n> from the ark. 11 When the dove returned to him in the evening, there in its\n> beak was a freshly plucked olive leaf! Then Noah knew that the water had\n> receded from the earth. 12 He waited seven more days and sent the dove out\n> again, but this time it did not return to him.\n-->\n\nThis package contains message definitions for the different entitites in the [ARC]\nproject.\n\nIt serves as both a contract, definition and implementation for the\ncommunication between\n[arc-control](https://gitlab.com/airtame/arc/arc/-/tree/master/src/arc-control) and the Desktop\nApplication, as well as between\n[arc-screen](https://gitlab.com/airtame/arc/arc/-/tree/master/src/arc-screen) and the\nDisplayManager.\n\n## Usage\n\n### In your project\n\nTo start, make sure that your project is setup to use Airtame's private NPM repository:\n\n```bash\necho @airtame:registry=https://gitlab.com/api/v4/packages/npm/ >> .npmrc\n```\n\nAnd the you can simply install the library:\n\n```bash\nnpm install --save @airtame/dove\n```\n\n**Note:**\n\nYou will need to set up your NPM config to log onto our Gitlab instance:\n\n```bash\nnpm config set '//gitlab.com/api/v4/packages/npm/:_authToken' \"<your token>\"\n```\n\nBut you should replace `your token` with a token that you generate here:\nhttps://gitlab.com/profile/personal_access_tokens.\n\nYour token should have `read_api` and `read_repository` rights to work.\n\n### API\n\nFour core **Messenger** classes are available, which serves, in pairs, to\nprovide means of message passing between the different entitites in [ARC].\nThe messages between messengers are passed by using [`postMessage()`] on a\n[Window](https://developer.mozilla.org/en-US/docs/Web/API/Window)-like object.\n\nPredefined typed messages can be passed between the classes as shown below. The available message types are specified in\n[Messages.ts](./src/Messages.ts).\n\n`DisplayManagerMessenger` ↔︎ `ScreenMessenger`\n\n`DesktopAppMessenger` ↔︎ `ControlMessenger`\n\n`ZoomScreenMessenger` ↔︎ `ZoomIframeMessenger`\n\nAll **Messenger** classes provides the same core api.\n\n#### `addRequestListener(listener: (msg: ReceiveRequestType, next: NextFunction) => Promise<SendRequestType>): void`\n\nAdds a handler for the request.\n\nThe handler _must_ return a `Promise` which is resolved when the request is successfully handled, rejected if an error occurs or call `next()` if the message received is not handled by this current handler.\n\n#### `removeRequestListener(listener: (msg: ReceiveRequestType, next: NextFunction) => Promise<SendRequestType>): void`\n\nRemoves the listener from the list.\n\n#### `addNotificationListener(listener: (msg: ReceiveNotificationType) => void): void`\n\nAdds a listener for notifications. This will be called for each notifications.\n\n#### `removeNotificationListener(listener: (msg: ReceiveNotificationType) => void): void`\n\nRemoves the listener.\n\n#### `sendRequest( msg: SendMessageType, timeout = DEFAULT_REQUEST_TIMEOUT): Promise<SendMessageType>`\n\nSends a request to a receiving messenger, and returns a promise which either\nresolves or rejects, depending on whether the receiver handled the message or not.\n\nIf the call times out, it means that the request was either not handled, or took too long to be processed.\n\n#### `sendNotification(msg: SendNotificationType): void`\n\nDispatches a message without waiting for a confirmation of receival.\n\n### Examples\n\n#### Create 2 messengers and send/handle/reply a message\n\nThis example will be demonstrated with the (display-manager-utils)[https://gitlab.com/airtame/device/display-manager-utils] library but it could be replaced by anything else.\n\n```ts\n/***********************/\n/* DESKTOP APPLICATION */\n/***********************/\nimport {\n  DesktopAppMessage,\n  DesktopAppMessenger,\n  ControlMessage,\n  ControlMessageName,\n  DesktopAppMessageName,\n} from '@airtame/dove';\nimport {\n  AutoReadyMessagingProxy,\n  PageEndpoint,\n  ProxyEnvelope,\n  Sender,\n} from '@airtame/display-manager-utils';\n\nconst dmEndpoint = new PageEndpoint<\n  ProxyEnvelope<DesktopAppMessage, ControlMessage>\n>({\n  sendWindow: window,\n  receiveWindow: window,\n  name: Sender.ContentScript,\n  peerName: Sender.Page,\n});\nconst proxy = new AutoReadyMessagingProxy<DesktopAppMessage, ControlMessage>({\n  endpoint: dmEndpoint,\n});\nconst desktopMessenger = new DesktopAppMessenger(proxy);\n\ntry {\n  const message = await desktopMessenger.sendRequest({\n    name: DesktopAppMessageName.CALL_INFO_REQUEST,\n  });\n\n  if (message.name === ControlMessageName.CALL_INFO_RESPONSE) {\n    if (message.isInCall) {\n      await this.leaveCall();\n    } else {\n      await this.endCall();\n    }\n  }\n} catch (err) {\n  logger.error('Failed to get call info', { err });\n} finally {\n  this.stop();\n}\n\n/***********/\n/* CONTROL */\n/***********/\nimport {\n  ControlMessenger,\n  ControlMessage,\n  DesktopAppMessage,\n  NextFunction,\n} from '@airtame/dove';\nimport {\n  AutoReadyMessagingProxy,\n  PageEndpoint,\n  ProxyEnvelope,\n  Sender,\n} from '@airtame/display-manager-utils';\n\nconst endpoint = new PageEndpoint<\n  ProxyEnvelope<ControlMessage, DesktopAppMessage>\n>({\n  sendWindow: window.parent,\n  receiveWindow: window,\n  name: Sender.Page,\n  peerName: Sender.ContentScript,\n});\nconst proxy = new AutoReadyMessagingProxy<ControlMessage, DesktopAppMessage>({\n  endpoint,\n});\ncontrolMessenger = new ControlMessenger(proxy);\n\nconst handleRequest = (\n  message: DesktopAppMessage,\n  next: NextFunction\n): Promise<ControlMessage> => {\n  if (message.name === DesktopAppMessageName.CALL_INFO_REQUEST_v1) {\n    return Promise.resolve({\n      name: ControlMessageName.CALL_INFO_RESPONSE,\n      isInCall: meetingJoined !== -1 && meetingLeft === -1,\n    });\n  }\n\n  next();\n};\n\ncontrolMessenger.addRequestListener(handleRequest);\n```\n\n#### Examples in tests\n\nA few tests are included which showcases usage of the various **Messenger** classes:\n\n- [Messenger.test.ts](./src/Messenger.test.ts)\n\n### Versioning of messages\n\nThe versioning of messages is relatively simple: we will have the versioning made via new messages (see [adr](./doc/adr/0002-message-versioning.md)).\n\nThat means that for if a message need to be upgraded, we simply create a new message.\n\nHere is an example:\n\n```ts\n// You are using the message to send the SDP offer:\ntype ControlMessages = {\n  name: ControlMessageName.SDP_OFFER_v1;\n  description: RTCSessionDescriptionJSON;\n};\n\n// All is well but now there is a new field that is useful in the new version that\n// would allow you to tell the peer if this is a renewal or not. For that you need\n// to create a new version of the message:\ntype ControlMessages =\n  | {\n      name: ControlMessageName.SDP_OFFER_v1;\n      description: RTCSessionDescriptionJSON;\n    }\n  | {\n      name: ControlMessageName.SDP_OFFER_v2;\n      description: RTCSessionDescriptionJSON;\n      renewal: boolean;\n    };\n\n// In the handler, in an effort to keep backward compatibility you could have:\ndesktopAppMessenger.addRequestListener(\n  (message: ControlMessage, next: NextFunction): Promise<DesktopAppMessage> => {\n    switch (message.name) {\n      case ControlMessageName.SDP_OFFER_v2: {\n        if (!this.isActive) {\n          return Promise.reject();\n        }\n        const { description, renewal } = message;\n        return this.handleSDPOffer(description, renewal).then(\n          (descriptionResp) => {\n            const replyMessage: DesktopAppMessage = {\n              name: DesktopAppMessageName.SDP_ANSWER_v2,\n              description: descriptionResp,\n              renewal,\n            };\n            return Promise.resolve(replyMessage);\n          }\n        );\n      }\n\n      case ControlMessageName.SDP_OFFER_v1: {\n        if (!this.isActive) {\n          return Promise.reject();\n        }\n        const { description } = message;\n        return this.handleSDPOffer(\n          description,\n          true /* Imagine this would be our default in case*/\n        ).then((descriptionResp) => {\n          const replyMessage: DesktopAppMessage = {\n            name: DesktopAppMessageName.SDP_ANSWER_v1,\n            description: descriptionResp,\n          };\n          return Promise.resolve(replyMessage);\n        });\n      }\n\n      default:\n        next();\n    }\n  }\n);\n```\n\nThis would be the same for notifications and replies.\n\n## Build\n\nTo build the library:\n\n```bash\n# Install the dependencies\nnpm install\n\n# Run the build script\nnpm run build\n```\n\nAfter that you have the artifacts in the `dist/` folder.\n\n## Development\n\nUse [`yalc`](https://www.npmjs.com/package/yalc) package to publish and install\nlocal version of `@airtame/dove` to another local project.\n\nTo install `yalc` globally, run:\n\n```bash\nnpm i -g yalc\n```\n\nTo publish, first build the changes, then run:\n\n```bash\nnpx yalc publish\n```\n\nThen inside another project run:\n\n```bash\nnpx yalc install @airtame/dove\n```\n\n## Release\n\nTo create a release, you need to update related files, merge changes into\n`master` branch and create a tag from master named as version number prefixed\nwith v as follows: `v1.2.3`.\n\nTo update related files run the following command:\n\n```bash\nnpm run release:prepare [major | minor | patch]\n```\n\nThen push to remote, review and merge the changes.\n\nAfter that switch back to master, pull the latest changes, and create a tag:\n\n```bash\ngit checkout master\ngit pull --rebase\ngit tag v1.2.3\ngit push origin v1.2.3\n```\n\n## [CHANGELOG](./CHANGELOG.md)\n\n## Architecture Decision Records\n\n1. [Record architecture decisions](./doc/adr/0001-record-architecture-decisions.md)\n2. [Message versioning](./doc/adr/0002-message-versioning.md)\n\n[arc]: https://gitlab.com/airtame/arc/arc\n","readmeFilename":"README.md"}