@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.
@@ -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 release mode and dist-tag from `BUILD_ARGS` (`dev`, `test`, `live`).
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 (required values):
114
+ Environment mapping:
115
115
 
116
- 1. `dev` -> publish mode with `dev` tag
117
- 2. `test` -> promote mode with `test` tag
118
- 3. `live` -> promote mode with `latest` tag
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. For `publish` mode, deployspec skips publish if the exact version already exists on npm.
125
- 4. For `promote` mode, deployspec fails if the exact version does not already exist on npm.
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, publish vs promote and dist-tag are not set manually; they are derived from `BUILD_ARGS`.
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
- - Tag updates on `test` and `master-integrations-messenger` are safe to run repeatedly.
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
- // Use messenger.actions to send or handle integration actions.
33
- // Parent apps can also register child windows when needed.
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
- More complete usage examples and API documentation will be added in upcoming releases.
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.6",
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
+ }
@@ -7,6 +7,5 @@ export declare enum BrandNameEnum {
7
7
  }
8
8
  export type GetBrandingResponseDTO = ActionResponseBaseDTO & {
9
9
  brandName: BrandNameEnum;
10
- stylesheetUrl?: string;
11
10
  logoUrl?: string;
12
11
  };