@microsoft/omnichannel-amsclient 0.1.12 → 0.1.14
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.md +179 -83
- package/lib/config.js +6 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,134 +1,228 @@
|
|
|
1
1
|
# Omnichannel AMSClient
|
|
2
|
+
|
|
2
3
|
[](https://badge.fury.io/js/%40microsoft%2Fomnichannel-amsclient)
|
|
3
4
|

|
|
4
5
|
|
|
5
|
-
|
|
6
|
+
TypeScript client for Microsoft Azure Messaging Services (AMS) APIs. Handles file uploads and downloads in Omnichannel conversations. Compatible with Web (browser), Node.js, and React Native.
|
|
7
|
+
|
|
8
|
+
**Zero runtime dependencies.**
|
|
6
9
|
|
|
7
10
|
## Table of Contents
|
|
11
|
+
|
|
8
12
|
- [Installation](#installation)
|
|
9
|
-
- [
|
|
13
|
+
- [Quick Start](#quick-start)
|
|
14
|
+
- [Client Modes](#client-modes)
|
|
15
|
+
- [Configuration](#configuration)
|
|
16
|
+
- [API Reference](#api-reference)
|
|
17
|
+
- [File Upload Flow](#file-upload-flow)
|
|
18
|
+
- [File Download Flow](#file-download-flow)
|
|
19
|
+
- [Telemetry](#telemetry)
|
|
10
20
|
- [Development](#development)
|
|
21
|
+
- [Contributing](#contributing)
|
|
11
22
|
|
|
12
23
|
## Installation
|
|
13
24
|
|
|
14
|
-
```
|
|
15
|
-
|
|
25
|
+
```bash
|
|
26
|
+
npm install @microsoft/omnichannel-amsclient --save
|
|
16
27
|
```
|
|
17
28
|
|
|
18
|
-
|
|
29
|
+
### CDN
|
|
19
30
|
|
|
20
|
-
|
|
31
|
+
The CDN bundle exposes the SDK on the global namespace:
|
|
21
32
|
|
|
22
33
|
```ts
|
|
34
|
+
const { createAMSClient, FramedClient, FramedlessClient } = window.Microsoft.CRM.Omnichannel.AMS.SDK;
|
|
35
|
+
```
|
|
23
36
|
|
|
24
|
-
|
|
37
|
+
## Quick Start
|
|
38
|
+
|
|
39
|
+
```ts
|
|
25
40
|
import createAMSClient from '@microsoft/omnichannel-amsclient';
|
|
26
41
|
|
|
27
|
-
//
|
|
28
|
-
const
|
|
42
|
+
// Create client (browser — uses iframe isolation)
|
|
43
|
+
const client = await createAMSClient({
|
|
44
|
+
framedMode: true,
|
|
45
|
+
debug: false
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
// Initialize with chat token
|
|
49
|
+
await client.initialize({ chatToken });
|
|
50
|
+
|
|
51
|
+
// Upload a file
|
|
52
|
+
const objectResponse = await client.createObject(chatToken.chatId, file);
|
|
53
|
+
const fileMetadata = await client.uploadDocument(objectResponse.id, file);
|
|
29
54
|
|
|
55
|
+
// Download a file
|
|
56
|
+
const viewStatus = await client.getViewStatus(fileMetadata);
|
|
57
|
+
const blob = await client.getView(fileMetadata, viewStatus.view_location);
|
|
30
58
|
```
|
|
31
59
|
|
|
32
|
-
|
|
33
|
-
```ts
|
|
60
|
+
## Client Modes
|
|
34
61
|
|
|
35
|
-
|
|
36
|
-
const chatToken = getChatToken();
|
|
62
|
+
The library provides two client implementations selected via the `framedMode` config flag:
|
|
37
63
|
|
|
38
|
-
|
|
39
|
-
framedMode: true,
|
|
40
|
-
debug: false, // optional
|
|
41
|
-
logger: null // optional
|
|
42
|
-
};
|
|
64
|
+
### FramedClient (`framedMode: true`)
|
|
43
65
|
|
|
44
|
-
|
|
66
|
+
For **browser** environments. Loads a hidden iframe from a CDN blob that contains the `IframeCommunicator`. All AMS API calls execute inside the iframe for cross-origin isolation. Communication between the host page and iframe uses `postMessage`.
|
|
45
67
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
68
|
+
- Requires a CDN-hosted iframe bundle (configured via `baseUrl`)
|
|
69
|
+
- Supports multiple concurrent instances via `multiClient: true`
|
|
70
|
+
- Call `dispose()` to remove the iframe when done
|
|
71
|
+
|
|
72
|
+
### FramedlessClient (`framedMode: false`)
|
|
73
|
+
|
|
74
|
+
For **Node.js** and **React Native** environments. Calls AMS APIs directly via `fetch`. Logs a warning if used in a browser (use FramedClient instead for proper CORS handling).
|
|
75
|
+
|
|
76
|
+
## Configuration
|
|
50
77
|
|
|
51
|
-
### Upload Attachment
|
|
52
78
|
```ts
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
fileSelector.click();
|
|
61
|
-
fileSelector.onchange = async (event: any) => {
|
|
62
|
-
console.log(file); // FileInfo
|
|
63
|
-
|
|
64
|
-
try {
|
|
65
|
-
const objectResponse = await AMSClient.createObject(chatToken?.chatId as string, fileInfo);
|
|
66
|
-
const fileMetadata = await this.uploadDocument(objectResponse.id, file);
|
|
67
|
-
|
|
68
|
-
// Success
|
|
69
|
-
|
|
70
|
-
// Read file content as base64 encoded string
|
|
71
|
-
const fileReader = new FileReader();
|
|
72
|
-
fileReader.readAsDataURL(file);
|
|
73
|
-
fileReader.onloadend = () => {
|
|
74
|
-
console.log(fileReader.result);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Create URL to access file
|
|
78
|
-
const objectUrl = URL.createObjectURL(file);
|
|
79
|
-
console.log(objectUrl);
|
|
80
|
-
} catch {
|
|
81
|
-
throw new Error('uploadFile');
|
|
82
|
-
}
|
|
79
|
+
interface AMSConfig {
|
|
80
|
+
framedMode: boolean; // true = FramedClient (browser), false = FramedlessClient (Node/RN)
|
|
81
|
+
debug?: boolean; // Enable console.log/console.time debug output (default: false)
|
|
82
|
+
logger?: PluggableLogger; // Custom telemetry logger
|
|
83
|
+
silentError?: boolean; // Suppress console.error on failures (default: true)
|
|
84
|
+
multiClient?: boolean; // Allow multiple FramedClient iframe instances (default: false)
|
|
85
|
+
baseUrl?: string; // CDN base URL for iframe (FramedClient only)
|
|
83
86
|
}
|
|
84
87
|
```
|
|
85
88
|
|
|
86
|
-
|
|
89
|
+
## API Reference
|
|
90
|
+
|
|
91
|
+
Both `FramedClient` and `FramedlessClient` expose the same public API:
|
|
92
|
+
|
|
93
|
+
### `initialize(initConfig)`
|
|
94
|
+
|
|
95
|
+
Authenticates with AMS using the provided chat token.
|
|
96
|
+
|
|
87
97
|
```ts
|
|
88
|
-
|
|
98
|
+
await client.initialize({
|
|
99
|
+
chatToken: {
|
|
100
|
+
chatId: string;
|
|
101
|
+
token: string;
|
|
102
|
+
regionGTMS?: Record<string, string>;
|
|
103
|
+
amsEndpoint?: string;
|
|
104
|
+
// ...other fields
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
```
|
|
89
108
|
|
|
90
|
-
|
|
109
|
+
### `createObject(chatId, file, chatToken?, supportedImagesMimeTypes?)`
|
|
91
110
|
|
|
92
|
-
|
|
111
|
+
Creates an AMS object for the file. Returns `{ id: string }` (the document ID).
|
|
93
112
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
113
|
+
- `chatId` — Conversation ID
|
|
114
|
+
- `file` — `File` object
|
|
115
|
+
- `chatToken` — Optional override (uses token from `initialize()` by default)
|
|
116
|
+
- `supportedImagesMimeTypes` — Optional custom list of image MIME types
|
|
97
117
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
118
|
+
### `uploadDocument(documentId, file, chatToken?, supportedImagesMimeTypes?)`
|
|
119
|
+
|
|
120
|
+
Uploads file content to the AMS object. Returns `FileMetadata`.
|
|
121
|
+
|
|
122
|
+
- `documentId` — ID from `createObject()` response
|
|
123
|
+
- `file` — `File` or `AMSFileInfo` (with `data: ArrayBuffer` for non-browser)
|
|
124
|
+
|
|
125
|
+
### `getViewStatus(fileMetadata, chatToken?, supportedImagesMimeTypes?)`
|
|
126
|
+
|
|
127
|
+
Checks the processing status of an uploaded file. Returns `AMSViewStatusResponse` including `view_location`, `content_state`, and `view_state`.
|
|
128
|
+
|
|
129
|
+
### `getView(fileMetadata, viewLocation, chatToken?, supportedImagesMimeTypes?)`
|
|
130
|
+
|
|
131
|
+
Downloads the file content. Returns a `Blob`.
|
|
132
|
+
|
|
133
|
+
- `viewLocation` — URL from `getViewStatus()` response
|
|
134
|
+
|
|
135
|
+
### `fetchBlob(contentUrl)`
|
|
104
136
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
137
|
+
Direct blob download helper. Fetches any URL and returns the response as a `Blob`.
|
|
138
|
+
|
|
139
|
+
### `dispose()` (FramedClient only)
|
|
140
|
+
|
|
141
|
+
Removes the iframe element and cleans up internal state. Call when the client is no longer needed.
|
|
142
|
+
|
|
143
|
+
### Supported Image MIME Types
|
|
144
|
+
|
|
145
|
+
By default, the following types are treated as images (affecting which AMS API path is used):
|
|
146
|
+
|
|
147
|
+
- `image/jpeg`
|
|
148
|
+
- `image/png`
|
|
149
|
+
- `image/gif`
|
|
150
|
+
- `image/heic`
|
|
151
|
+
- `image/webp`
|
|
152
|
+
|
|
153
|
+
Override by passing `supportedImagesMimeTypes` to any API method.
|
|
154
|
+
|
|
155
|
+
## File Upload Flow
|
|
156
|
+
|
|
157
|
+
```
|
|
158
|
+
1. createObject(chatId, file) → { id: documentId }
|
|
159
|
+
2. uploadDocument(documentId, file) → FileMetadata { name, size, type, id, url }
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
Images use the `pish/image` → `imgpsh` API path. Documents use `sharing/file` → `original`.
|
|
163
|
+
|
|
164
|
+
## File Download Flow
|
|
165
|
+
|
|
166
|
+
```
|
|
167
|
+
1. getViewStatus(fileMetadata) → { view_location, content_state, view_state }
|
|
168
|
+
2. getView(fileMetadata, response.view_location) → Blob
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
The `content_state` must not be `expired`. The `view_state` should be `ready`.
|
|
172
|
+
|
|
173
|
+
## Telemetry
|
|
174
|
+
|
|
175
|
+
Integrate custom telemetry by providing a `PluggableLogger`:
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
interface PluggableLogger {
|
|
179
|
+
logClientSdkTelemetryEvent(logLevel: LogLevel, event: AMSLogData): void;
|
|
180
|
+
}
|
|
108
181
|
```
|
|
109
182
|
|
|
183
|
+
The client uses a `ScenarioMarker` internally that emits `Started`, `Completed`, and `Failed` events with elapsed time tracking for each API operation.
|
|
184
|
+
|
|
185
|
+
`LogLevel` values: `INFO`, `DEBUG`, `WARN`, `ERROR`, `LOG`.
|
|
186
|
+
|
|
110
187
|
## Development
|
|
111
188
|
|
|
189
|
+
### Prerequisites
|
|
190
|
+
|
|
191
|
+
- Node.js 22.x
|
|
192
|
+
- npm
|
|
193
|
+
|
|
194
|
+
### Build
|
|
195
|
+
|
|
196
|
+
```bash
|
|
197
|
+
npm install
|
|
198
|
+
npm run build:tsc # Compile TypeScript → lib/
|
|
199
|
+
```
|
|
200
|
+
|
|
112
201
|
### Build CDN Package
|
|
113
202
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
203
|
+
```bash
|
|
204
|
+
npm run build:tsc
|
|
205
|
+
BASE_URL=https://[blob-url] SDK_VERSION=[version] node ./esbuild.config.js
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
This produces `dist/SDK.js`, `dist/SDK.min.js`, `dist/iframe.js`, `dist/iframe.min.js`, and `dist/iframe.html`.
|
|
118
209
|
|
|
119
|
-
###
|
|
210
|
+
### Test
|
|
120
211
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
212
|
+
```bash
|
|
213
|
+
npm test # Jest unit tests
|
|
214
|
+
npm run lint # ESLint
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### CI
|
|
218
|
+
|
|
219
|
+
- **Pull Request**: Build + test + lint (GitHub Actions, Node 22)
|
|
220
|
+
- **Release**: Build CDN + npm package, upload to Azure Blob Storage, publish to npm registry
|
|
221
|
+
- **Azure Pipelines**: Component Governance scan
|
|
128
222
|
|
|
129
223
|
## Contributing
|
|
130
224
|
|
|
131
|
-
This project welcomes contributions and suggestions.
|
|
225
|
+
This project welcomes contributions and suggestions. Most contributions require you to agree to a
|
|
132
226
|
Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
|
|
133
227
|
the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
|
|
134
228
|
|
|
@@ -140,6 +234,8 @@ This project has adopted the [Microsoft Open Source Code of Conduct](https://ope
|
|
|
140
234
|
For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
|
|
141
235
|
contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
|
|
142
236
|
|
|
237
|
+
See also: [Code of Conduct](docs/CODE_OF_CONDUCT.md) | [Security](docs/SECURITY.md) | [Support](docs/SUPPORT.md) | [Changelog](docs/CHANGELOG.md)
|
|
238
|
+
|
|
143
239
|
## Trademarks
|
|
144
240
|
|
|
145
241
|
This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
|
package/lib/config.js
CHANGED
|
@@ -1 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.sdkVersion = exports.baseUrl = void 0;
|
|
4
|
+
exports.baseUrl = '';
|
|
5
|
+
exports.sdkVersion = '';
|
|
6
|
+
//# sourceMappingURL=config.js.map
|