@corto-ai/integrations-messenger 0.0.6 → 0.0.8-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README-internal.md +32 -13
- package/README.md +100 -5
- package/package.json +3 -2
- package/src/lib/models/branding.d.ts +0 -1
package/README-internal.md
CHANGED
|
@@ -109,22 +109,40 @@ Buildspec behavior:
|
|
|
109
109
|
3. Runs `npm run pack:integrations-messenger` and moves the generated `.tgz` into `dist/libs/integrations-messenger/`.
|
|
110
110
|
4. Copies `buildspecs/integrations-messenger-deployspec.yml` into that artifact directory for the deploy stage.
|
|
111
111
|
|
|
112
|
-
Deployspec derives
|
|
112
|
+
Deployspec derives the npm package version and dist-tag from `BUILD_ARGS` (`dev`, `test`, `live`). All environments publish a package version; we no longer promote an existing version by moving dist-tags.
|
|
113
113
|
|
|
114
|
-
Environment mapping
|
|
114
|
+
Environment mapping:
|
|
115
115
|
|
|
116
|
-
1. `dev` ->
|
|
117
|
-
2. `test` ->
|
|
118
|
-
3. `live` ->
|
|
116
|
+
1. `dev` -> publishes `{version}-dev.{devVersion}` with `dev` tag
|
|
117
|
+
2. `test` -> publishes `{version}-test.{devVersion}` with `test` tag
|
|
118
|
+
3. `live` -> publishes `{version}` with `latest` tag
|
|
119
|
+
|
|
120
|
+
`version` and `devVersion` come from `libs/integrations-messenger/package.json`.
|
|
121
|
+
|
|
122
|
+
Example package metadata:
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"version": "0.0.8",
|
|
127
|
+
"devVersion": "1"
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Generated npm versions:
|
|
132
|
+
|
|
133
|
+
1. `dev` -> `0.0.8-dev.1`
|
|
134
|
+
2. `test` -> `0.0.8-test.1`
|
|
135
|
+
3. `live` -> `0.0.8`
|
|
119
136
|
|
|
120
137
|
Additional deployspec checks/requirements:
|
|
121
138
|
|
|
122
139
|
1. Package name must be exactly `@corto-ai/integrations-messenger` (validated against `EXPECTED_NAME`).
|
|
123
140
|
2. `NPM_TOKEN` is loaded from SSM Parameter Store path `/FrontEnd/Npm/AuthToken`.
|
|
124
|
-
3.
|
|
125
|
-
4.
|
|
141
|
+
3. `devVersion` is required for `dev` and `test` releases.
|
|
142
|
+
4. Deployspec skips publish if the exact generated version already exists on npm.
|
|
143
|
+
5. When publishing, deployspec unpacks the build-created `.tgz`, rewrites only the unpacked `package.json` version, and publishes that unpacked package with the derived tag.
|
|
126
144
|
|
|
127
|
-
In this flow,
|
|
145
|
+
In this flow, `version` and `devVersion` are maintained in package metadata. `BUILD_ARGS` determines how those values are combined into the npm version and which dist-tag is used.
|
|
128
146
|
|
|
129
147
|
Tag semantics:
|
|
130
148
|
|
|
@@ -134,9 +152,9 @@ Tag semantics:
|
|
|
134
152
|
|
|
135
153
|
Examples:
|
|
136
154
|
|
|
137
|
-
1. Publish `0.0.1` with `dev` -> `dev` points to `0.0.1`.
|
|
138
|
-
2. Publish `0.0.2` with `dev` -> `dev` now points to `0.0.2`.
|
|
139
|
-
3. `0.0.1` still exists and can be installed directly with `@corto-ai/integrations-messenger@0.0.1`.
|
|
155
|
+
1. Publish `0.0.8-dev.1` with `dev` -> `dev` points to `0.0.8-dev.1`.
|
|
156
|
+
2. Publish `0.0.8-dev.2` with `dev` -> `dev` now points to `0.0.8-dev.2`.
|
|
157
|
+
3. `0.0.8-dev.1` still exists and can be installed directly with `@corto-ai/integrations-messenger@0.0.8-dev.1`.
|
|
140
158
|
|
|
141
159
|
The npm token is loaded from SSM Parameter Store in deployspec:
|
|
142
160
|
|
|
@@ -152,7 +170,7 @@ Current branch strategy:
|
|
|
152
170
|
This keeps publishing idempotent:
|
|
153
171
|
|
|
154
172
|
- Re-running deploy on unchanged versions does not republish.
|
|
155
|
-
-
|
|
173
|
+
- Existing generated versions are treated as already deployed.
|
|
156
174
|
|
|
157
175
|
### Versioning policy
|
|
158
176
|
|
|
@@ -162,4 +180,5 @@ Reason:
|
|
|
162
180
|
|
|
163
181
|
1. This package is published to npm, where each new version is immutable.
|
|
164
182
|
2. Forcing version bumps during general CI validation creates unnecessary publishes and burns version numbers without meaningful package changes.
|
|
165
|
-
3. We only increment this package version when there is an actual change to `integrations-messenger` that should be released.
|
|
183
|
+
3. We only increment this package `version` when there is an actual change to `integrations-messenger` that should be released to live.
|
|
184
|
+
4. We increment `devVersion` when a new dev/test prerelease needs to be published for the same base `version`.
|
package/README.md
CHANGED
|
@@ -8,8 +8,6 @@ This package is currently in early development and is being published to npm to
|
|
|
8
8
|
|
|
9
9
|
This package is intended for teams adding applications into the CORTO platform (for example, iframe-based integrations).
|
|
10
10
|
|
|
11
|
-
For product information about CORTO, visit <https://www.docorto.ai>.
|
|
12
|
-
|
|
13
11
|
## Status
|
|
14
12
|
|
|
15
13
|
- Early development
|
|
@@ -22,18 +20,115 @@ For product information about CORTO, visit <https://www.docorto.ai>.
|
|
|
22
20
|
npm install @corto-ai/integrations-messenger
|
|
23
21
|
```
|
|
24
22
|
|
|
23
|
+
## Capabilities
|
|
24
|
+
|
|
25
|
+
- **Handshake & identity** -- every window (host or integration) registers itself with a unique `id`. Nested windows automatically perform a handshake with their parent so both sides know who they're talking to before any action is sent.
|
|
26
|
+
- **Origin-checked messaging** -- once the handshake completes, messages from a given source are only accepted if they come from the origin observed during that handshake, protecting against messages from unexpected origins.
|
|
27
|
+
- **Request/response actions** -- typed helpers for the actions below, each with a `send{{Action}}` (caller side) and `handle{{Action}}` (implementer side) pair that resolves once a matching response is received.
|
|
28
|
+
- **Streaming/pubsub notifications** -- a channel-based notification action that can be sent or handled repeatedly, useful for pushing multiple updates over time rather than a single request/response.
|
|
29
|
+
- **Automatic forwarding across nested iframes** -- if a window has no handler registered for an action, the message is forwarded up/down the iframe tree automatically, so multi-level nesting doesn't require every level to implement every action.
|
|
30
|
+
- **Optional debug logging** -- pass `withLogging: true` to `init` to log handshake and message activity to the console while integrating.
|
|
31
|
+
|
|
25
32
|
## Usage
|
|
26
33
|
|
|
34
|
+
### Initialization
|
|
35
|
+
|
|
36
|
+
Every window that uses this package -- host and embedded integrations alike -- must call `init` first:
|
|
37
|
+
|
|
27
38
|
```ts
|
|
28
39
|
import messenger from '@corto-ai/integrations-messenger';
|
|
29
40
|
|
|
30
41
|
await messenger.init({ id: 'my-integration-app' });
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
- `id` is required and must be unique for the window calling `init`.
|
|
45
|
+
- `parentRef` is optional and defaults to `window.parent`. Only override it if the page isn't communicating with its direct parent.
|
|
46
|
+
- `withLogging` is optional and enables console logging for debugging the handshake/messaging flow.
|
|
47
|
+
- If the window is nested (its `parentRef` isn't `window` itself), `init` also kicks off the handshake with the parent. `init` resolves once setup is complete; the handshake with the parent finishes asynchronously.
|
|
48
|
+
|
|
49
|
+
Host applications that embed an integration in an iframe must also call `registerChild` with a reference to the iframe's `contentWindow` and the same `id` the child passed to `init`:
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
messenger.registerChild(iframe.contentWindow, 'my-integration-app');
|
|
53
|
+
```
|
|
31
54
|
|
|
32
|
-
|
|
33
|
-
|
|
55
|
+
`registerChild` listens for the handshake from that child and resolves once it completes. Call it before the iframe's own `init` call runs, or the handshake may be missed.
|
|
56
|
+
|
|
57
|
+
### Actions
|
|
58
|
+
|
|
59
|
+
`messenger.actions` groups all supported actions by the entity/flow they affect:
|
|
60
|
+
|
|
61
|
+
| Group | Action | Description |
|
|
62
|
+
| ---------- | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
|
|
63
|
+
| `matter` | `sendOpenMatter` / `handleOpenMatter` | Open a matter by `matterId`. |
|
|
64
|
+
| `matter` | `sendOpenChatSession` / `handleOpenChatSession` | Open a specific chat session (`sessionId`) on a matter. |
|
|
65
|
+
| `matter` | `sendOpenAgentSession` / `handleOpenAgentSession` | Open a specific agent session (`sessionId`) on a matter. |
|
|
66
|
+
| `matter` | `sendOpenDetails` / `handleOpenDetails` | Open the details view for a matter. |
|
|
67
|
+
| `matter` | `sendOpenEdit` / `handleOpenEdit` | Open the edit view for a matter. |
|
|
68
|
+
| `matter` | `sendOpenDocumentStatus` / `handleOpenDocumentStatus` | Open the document status view for a matter. |
|
|
69
|
+
| `matter` | `sendOpenPrompt` / `handleOpenPrompt` | Open a specific prompt (`promptId`) on a matter. |
|
|
70
|
+
| `matter` | `sendOpenPromptLibrary` / `handleOpenPromptLibrary` | Open the prompt library for a matter. |
|
|
71
|
+
| `matter` | `sendPreviewDocument` / `handlePreviewDocument` | Preview a document (`documentId`, `documentName`) on a matter. |
|
|
72
|
+
| `contact` | `sendOpenContact` / `handleOpenContact` | Open a contact by `contactId`. |
|
|
73
|
+
| `contact` | `sendOpenEditContact` / `handleOpenEditContact` | Open the edit view for a contact. |
|
|
74
|
+
| `settings` | `sendOpenSettings` / `handleOpenSettings` | Open the host application's settings. |
|
|
75
|
+
| `branding` | `sendGetBranding` / `handleGetBranding` | Request the active brand name and logo URL, or pass an optional `brandName` to request a specific brand instead of the active one. |
|
|
76
|
+
| `auth` | `sendExchangeTokenRequest` / `handleExchangeTokenRequest` | Exchange a `clientId` for an auth token. |
|
|
77
|
+
| `pubsub` | `sendNotificationRequest` / `handleNotificationRequest` | Subscribe to (or publish) notifications on a `channel`, supporting multiple responses over time. |
|
|
78
|
+
|
|
79
|
+
All `matter`, `contact`, and `settings` actions accept an optional `newTab` flag to indicate the host should open the target in a new tab, and `matter` actions also accept an optional `matterId` beyond what's called out above.
|
|
80
|
+
|
|
81
|
+
For each action, the `send...` function is intended for the embedded integration to call, to ask the host application to perform some action or return some data. The matching `handle...` function is intended to be implemented by the host application: it registers a callback that receives the request and returns the response to send back.
|
|
82
|
+
|
|
83
|
+
```typescript
|
|
84
|
+
// in the host application
|
|
85
|
+
await messenger.init({ id: 'host' });
|
|
86
|
+
|
|
87
|
+
messenger.registerChild(iframe.contentWindow, 'child');
|
|
88
|
+
|
|
89
|
+
messenger.actions.matter.handleOpenChatSession(async ({ matterId, sessionId }) => {
|
|
90
|
+
try {
|
|
91
|
+
await someService.openSession(matterId, sessionId);
|
|
92
|
+
return { success: true };
|
|
93
|
+
} catch (err) {
|
|
94
|
+
return { success: false, error: err.message };
|
|
95
|
+
}
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// in the embedded integration
|
|
99
|
+
await messenger.init({ id: 'child' });
|
|
100
|
+
|
|
101
|
+
const response = await messenger.actions.matter.sendOpenChatSession({
|
|
102
|
+
matterId: '123',
|
|
103
|
+
sessionId: 'abc'
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
if (response.success) {
|
|
107
|
+
// happy path
|
|
108
|
+
} else {
|
|
109
|
+
// sad path
|
|
110
|
+
}
|
|
34
111
|
```
|
|
35
112
|
|
|
36
|
-
|
|
113
|
+
#### Streaming actions (pubsub)
|
|
114
|
+
|
|
115
|
+
`pubsub` notifications differ from the other actions: instead of resolving once with a single response, `sendNotificationRequest` and `handleNotificationRequest` can fire their callback multiple times for the same `channel`, and both return a handle with a `remove()` function to stop listening.
|
|
116
|
+
|
|
117
|
+
```typescript
|
|
118
|
+
// listen for notifications on a channel
|
|
119
|
+
const handle = messenger.actions.pubsub.sendNotificationRequest({ channel: 'documents' }, (notification) => {
|
|
120
|
+
console.log('received', notification.data);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// later, stop listening
|
|
124
|
+
handle.remove();
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Forwarding
|
|
128
|
+
|
|
129
|
+
In order to support multiple levels of iframe nesting, the package inherently has a "forwarding" mechanic: for any action, if no handler is defined in a given window, the message continues up or down the iframe tree until a handler picks it up. This is enabled by default and requires no opt-in.
|
|
130
|
+
|
|
131
|
+
Adding a handler in a child application can shadow the same action's handling in a parent application, since forwarding only happens when a handler isn't defined. If you're not sure whether you should implement a handler for a given action, don't -- let it forward to the host.
|
|
37
132
|
|
|
38
133
|
## Demo Repository
|
|
39
134
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@corto-ai/integrations-messenger",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8-dev.1",
|
|
4
|
+
"devVersion": "1",
|
|
4
5
|
"private": false,
|
|
5
6
|
"type": "module",
|
|
6
7
|
"main": "./src/index.js",
|
|
@@ -9,4 +10,4 @@
|
|
|
9
10
|
"tslib": "^2.3.0"
|
|
10
11
|
},
|
|
11
12
|
"module": "./src/index.js"
|
|
12
|
-
}
|
|
13
|
+
}
|