Skip to content

Commit 876b3b9

Browse files
New release 2.6.5 (#40)
- Added support for REST service event handlers - Added support for userInputReceived event
1 parent f07617c commit 876b3b9

File tree

24 files changed

+682
-34
lines changed

24 files changed

+682
-34
lines changed

ENTITY_EVENT_HANDLER.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ The table below lists all entity level events currently supported:
136136
| `attachmentReceived`| A function that gets called when the user sends an attachment. If the attachment can be mapped to a composite bag item, the validate function of that item will be called first. | <ul><li><b>value</b>: The attachment JSON object with `type` and `url` properties.</li></ul>
137137
| `locationReceived`| A function that gets called when the user sends a location. If the location can be mapped to a composite bag item, the validate function of that item will be called first. | <ul><li><b>value</b>: The location JSON object with `latitude` and `longitude` properties.</li></ul>
138138
| `disambiguateBagItem` | A handler that can be used to modify the message that is shown to disambiguate between bag items when an entity match applies to more than one bag item. Note that this handler only fires when the skill configuration parameter `Use Enhanced Slot Filling` is switched on. | <ul><li><b>matchValue</b>: The entity value matched based on the user input</li><li><b>matchedBagItems</b>: list of the names of the bag items that are matched against the entity value.</li><li><b>userInput</b>: the last user input message that matched to multiple bag items.</li></ul>
139+
| `userInputReceived` | A handler that can be used to inspect and modify new item matches and disambiguation values before the bag items are validated and updated. The handler is invoked on every turn while resolving the composite bag entity. | <ul><li><b>currentItem</b>: The full name of the bag item currently being resolved.</li><li><b>userInput</b>: the last user input message.</li><li><b>newItemMatches</b>: a key-value map where each key is the full name of a bag item, and the value the candidate value for the item. The new item matches can be changed using `context.setItemMatches` and `context.clearItemMatch`.</li><li><b>disambiguationValues</b>: a key-value map where each key is the full name of a bag item, and the value a list of matched values for the item. The disambiguation values for an item can be changed using `context.setDisambiguationValues()` or `context.clearDisambiguationValues()`</li><li><b>disambiguationItems</b>: a key-value map where each key is the full name of a bag item, and the value a map with two properties: <ul><li><b>matchValue</b>: an entity value that matches against multiple bag items</li><li> <b>matchedBagItems</b>: list of the names of all the bag items that match against the entity value. The first item in the list is used as the key in the disambiguationItems map.</li></ul> A disambiguation value that matches multiple items can be removed by calling `context.clearDisambiguationItems()` and passing the full name of the first item in the list as argument.</li></ul>
139140

140141
### Entity-Item Level Events <a name="itemEvents">
141142
The table below lists all entity-item level events currently supported:

RELEASE_NOTES.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Release Notes
22

3+
- [Version 2.6.5](#v265)
34
- [Version 2.6.4](#v264)
45
- [Version 2.6.3](#v263)
56
- [Version 2.6.2](#v262)
@@ -14,6 +15,19 @@
1415
- [Version 2.4.3](#v243)
1516
- [Version 2.4.2](#v242)
1617

18+
## Version 2.6.5 <a name="v265">
19+
20+
### New Features
21+
22+
- **New UserInputReceived Entity Event Handler Method**: See [Writing Entity Event Handlers](https://github.com/oracle/bots-node-sdk/blob/master/ENTIY_EVENT_HANDLER.md) for more information.
23+
24+
- **REST Service Event Handlers**: REST service event handlers can be used to transform the REST request and response body when using the Call REST component in your flow. See [Writing REST Service Event Handlers](https://github.com/oracle/bots-node-sdk/blob/master/REST_SERVCICE_EVENT_HANDLER.md) for more information. This feature is only available in the Limited Availability release of Oracle Digital Assistant version 23.06.
25+
26+
### Fixed Issues
27+
28+
- Fixed TypeScript definition of EntityValidateEvent
29+
- Added TypeScript definition for DisambiguateItemEvemt
30+
1731
## Version 2.6.4 <a name="v264">
1832

1933
### New Features

REST_SERVICE_EVENT_HANDLER.md

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# Writing REST Service Event Handlers
2+
3+
## Table of contents
4+
- [Introduction](#introduction)
5+
- [REST Service Handler Structure](#structure)
6+
- [Using Javascript](#js)
7+
- [Using Typescript](#ts)
8+
- [Writing REST Service Handler Functions](#writing)
9+
- [Supported Events](#events)
10+
11+
## Introduction <a name="introduction">
12+
13+
A REST Service Event Handler (RSEH) enables you to transform customize the REST request body before the REST call is made, and to transform the response body after the REST call is made.
14+
15+
<br/><br/>
16+
The RSEH is deployed as part of a component service. The built-in Call REST component checks whether an event handler is registered
17+
and if so, the component invokes the event handler methods to transform the request and/or response body.
18+
19+
## RESTService Event Handler Structure <a name="structure">
20+
21+
### Using Javascript <a name="js">
22+
23+
A REST service event handler exports two objects: the `metadata` object that provides the name of the component and the `eventHandlerType` (which should be set to `RestService`), and the `handlers` object that contains the event handler functions.
24+
25+
```javascript
26+
module.exports = {
27+
metadata: {
28+
name: 'myRestServiceEventHandler',
29+
eventHandlerType: 'RestService'
30+
},
31+
handlers: {
32+
33+
/**
34+
* Handler to transform the request payload
35+
* @param {TransformPayloadEvent} event
36+
* @param {RestServiceContext} context
37+
* @returns {object} the transformed request payload
38+
*/
39+
transformRequestPayload: async (event, context) => {
40+
return event.payload;
41+
},
42+
43+
/**
44+
* Handler to transform the response payload
45+
* @param {TransformPayloadEvent} event
46+
* @param {RestServiceContext} context
47+
* @returns {object} the transformed response payload
48+
*/
49+
transformResponsePayload: async (event, context) => {
50+
return event.payload;
51+
}
52+
}
53+
};
54+
```
55+
56+
If needed, you can define the `metadata` and `handlers` members as functions rather than as an objects.
57+
58+
### Using TypeScript <a name="ts">
59+
60+
In TypeScript, the event handler class implements the `RestServiceEventHandler` interface. This interface requires both of the following methods:
61+
62+
- The `metadata` method that returns an object of type `RestServiceEventHandlerMetadata`.
63+
- The `handlers` method that returns an object of type `RestServiceEventHandlers`.
64+
65+
```typescript
66+
import { RestServiceContext, RestServiceEventHandler, RestServiceEventHandlers, RestServiceEventHandlerMetadata, TransformPayloadEvent } from '@oracle/bots-node-sdk/lib';
67+
68+
export class MyRestServiceEventHandler implements RestServiceEventHandler {
69+
70+
public metadata(): RestServiceEventHandlerMetadata {
71+
return {
72+
name: 'myRestServiceEventHandler',
73+
eventHandlerType: 'RestService'
74+
};
75+
}
76+
77+
public handlers(): RestServiceEventHandlers {
78+
return {
79+
80+
/**
81+
* Handler to transform the request payload
82+
* @param {TransformPayloadEvent} event
83+
* @param {RestServiceContext} context
84+
* @returns {object} the transformed request payload
85+
*/
86+
transformRequestPayload: async (event: TransformPayloadEvent, context: RestServiceContext): Promise<any> => {
87+
return event.payload;
88+
},
89+
90+
/**
91+
* Handler to transform the response payload
92+
* @param {TransformPayloadEvent} event
93+
* @param {RestServiceContext} context
94+
* @returns {object} the transformed response payload
95+
*/
96+
transformResponsePayload: async (event: TransformPayloadEvent, context: RestServiceContext): Promise<any> => {
97+
return event.payload;
98+
}
99+
100+
};
101+
}
102+
103+
}
104+
```
105+
106+
## Writing Event Handler Functions <a name="writing">
107+
108+
The first argument of each event method is the `event` object. The properties available in this object depend on the type of event.
109+
See the [list of supported entity events](#events) for information on which properties are available with which event.
110+
111+
The second argument of each event method is the `context` object. This object references the [RestServiceContext](https://oracle.github.io/bots-node-sdk/RestServiceContext.html) that provides access to convenience methods you can use to create your event handler logic.
112+
113+
<b>TIP</b>: if you are using a JavaScript IDE like Visual Studio Code, you can get code insight and code completion support by defining the types used in the event handlers as follows in your JavaScript handler file:
114+
```javascript
115+
const { RestServiceContext, RestServiceEventHandler, RestServiceEventHandlers, RestServiceEventHandlerMetadata, TransformPayloadEvent } = require ('@oracle/bots-node-sdk/lib');
116+
```
117+
When using TypeScript, you will automatically get code completion support if your IDE supports it.
118+
119+
## Supported Events <a name="events">
120+
121+
The table below lists the event methods that can be implemented:
122+
123+
| Event | Description | Event Properties |
124+
|--|--|--|
125+
| `transformRequestPayload` | A handler that can be used to trasnform the REST request body. | <ul><li><b>payload</b>: The request body object.</li></ul>
126+
| `transformResponsePayload` | A handler that can be used to trasnform the REST response body. | <ul><li><b>payload</b>: The response body object.</li></ul>
127+

bin/commands/init.js

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,17 @@ function nameOpt(name) {
1313

1414
function componentTypeOpt(type) {
1515
let t = type.toLowerCase();
16-
t = t === 'c' ? 'custom' : (t === 'e' ? 'entityeventhandler' : (t === 's' ? 'sqlqueryeventhandler' : t));
17-
if (!~['custom', 'entityeventhandler', 'sqlqueryeventhandler'].indexOf(t)) {
18-
throw new Error(`Invalid component type: ${type}, allowable values are [c]ustom or [e]ntityEventHandler or [s]qlQueryEventHandler..`);
16+
if (t === 'c') {
17+
t = 'custom';
18+
} else if (t === 'e') {
19+
t = 'entityeventhandler';
20+
} else if (t === 's') {
21+
t = 'sqlqueryeventhandler';
22+
} else if (t === 'r') {
23+
t = 'restserviceeventhandler';
24+
}
25+
if (!~['custom', 'entityeventhandler', 'sqlqueryeventhandler', 'restserviceeventhandler'].indexOf(t)) {
26+
throw new Error(`Invalid component type: ${type}, allowable values are [c]ustom or [e]ntityEventHandler or [s]qlQueryEventHandler or [r]estServiceEventHandler.`);
1927
}
2028
return t;
2129
}
@@ -42,7 +50,7 @@ class CCInit extends CommandDelegate {
4250
.option('-r --run', 'Start service when init completes (with defaults)')
4351
.option('-n --name <name>', 'Specify a name for the new project', null, nameOpt)
4452
.option('-c --component-name <name>', 'Name for the first custom component', 'helloWorld', nameOpt)
45-
.option('-t --component-type <type>', 'Specify the component type [c]ustom or [e]ntityEventHandler or [s]qlQueryEventHandler', 'custom', componentTypeOpt);
53+
.option('-t --component-type <type>', 'Specify the component type [c]ustom or [e]ntityEventHandler or [s]qlQueryEventHandler or [r]estServiceEventHandler', 'custom', componentTypeOpt);
4654
// add child command 'init component'
4755
this.command.delegate(CCInitComponent, 'component');
4856
}
@@ -174,7 +182,7 @@ class CCInitComponent extends CommandDelegate {
174182
this.command
175183
.ignore('componentName').ignore('run').ignore('skipInstall') // inherited from parent
176184
.argument('name', 'Specify a name for the component', true, nameOpt)
177-
.argument('type', 'Specify the component type [c]ustom or [e]ntityEventHandler or [s]qlQueryEventHandler', true, componentTypeOpt)
185+
.argument('type', 'Specify the component type [c]ustom or [e]ntityEventHandler or [s]qlQueryEventHandler or [r]estServiceEventHandler', true, componentTypeOpt)
178186
.argument('dest', 'Destination directory where component should be added', false)
179187
.option('-q --quiet', 'Suppress outputs')
180188

@@ -225,7 +233,14 @@ class CCInitComponent extends CommandDelegate {
225233
if (!fs.existsSync(to)) {
226234
let className = name.charAt(0).toUpperCase() + name.slice(1);
227235
className = className.replace('.','');
228-
let eventHandlerType = type === 'entityeventhandler' ? 'ResolveEntities' : 'DataQuery';
236+
let eventHandlerType;
237+
if (type === 'entityeventhandler') {
238+
eventHandlerType = 'ResolveEntities';
239+
} else if (type === 'sqlqueryeventhandler') {
240+
eventHandlerType = 'DataQuery';
241+
} else if (type === 'restserviceeventhandler') {
242+
eventHandlerType = 'RestService';
243+
}
229244
writeTemplate(from, to, {
230245
name,
231246
className: className,

bin/templates/components/entityeventhandler/template.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,10 @@ module.exports = {
2727
context.addCandidateMessages();
2828
},
2929
/**
30-
* This handler is called when the composite bag entity is resolved
30+
* This handler is called when the composite bag entity is resolved
3131
* @param {EntityBaseEvent} event
3232
* @param {EntityResolutionContext} context
33-
*/
33+
*/
3434
resolved: async (event, context) => { // eslint-disable-line no-unused-vars
3535
// add your back-end REST API call here
3636
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/* eslint-disable no-unused-vars */
2+
3+
'use strict';
4+
5+
// Documentation for writing REST Service query event handlers: https://github.com/oracle/bots-node-sdk/blob/master/REST_SERVICE_EVENT_HANDLER.md
6+
7+
// You can use your favorite http client package to make REST calls, however, the node fetch API is pre-installed with the bots-node-sdk.
8+
// Documentation can be found at https://www.npmjs.com/package/node-fetch
9+
// Un-comment the next line if you want to make REST calls using node-fetch.
10+
// const fetch = require("node-fetch");
11+
12+
module.exports = {
13+
metadata: {
14+
name: '{{name}}',
15+
eventHandlerType: '{{eventHandlerType}}'
16+
},
17+
handlers: {
18+
19+
/**
20+
* Handler to transform the request payload
21+
* @param {TransformPayloadEvent} event
22+
* @param {RestServiceContext} context
23+
* @returns {object} the transformed request payload
24+
*/
25+
transformRequestPayload: async (event, context) => {
26+
return event.payload;
27+
},
28+
29+
/**
30+
* Handler to transform the response payload
31+
* @param {TransformPayloadEvent} event
32+
* @param {RestServiceContext} context
33+
* @returns {object} the transformed response payload
34+
*/
35+
transformResponsePayload: async (event, context) => {
36+
return event.payload;
37+
}
38+
}
39+
};
40+
41+
/* eslint-enable no-unused-vars */
42+
43+
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
import { RestServiceContext
2+
, RestServiceEventHandler
3+
, RestServiceEventHandlers
4+
, RestServiceEventHandlerMetadata
5+
, TransformPayloadEvent
6+
7+
} from '@oracle/bots-node-sdk/lib';
8+
9+
// Documentation for writing SQL query event handlers: https://github.com/oracle/bots-node-sdk/blob/master/REST_SERVICE_EVENT_HANDLER.md
10+
11+
// You can use your favorite http client package to make REST calls, however, the node fetch API is pre-installed with the bots-node-sdk.
12+
// Documentation can be found at https://www.npmjs.com/package/node-fetch
13+
// Un-comment the next line if you want to make REST calls using node-fetch.
14+
// import fetch from 'node-fetch';
15+
16+
export class {{className}} implements RestServiceEventHandler {
17+
18+
public metadata(): RestServiceEventHandlerMetadata {
19+
return {
20+
name: '{{name}}',
21+
eventHandlerType: '{{eventHandlerType}}'
22+
};
23+
}
24+
25+
public handlers(): RestServiceEventHandlers {
26+
return {
27+
28+
/**
29+
* Handler to transform the request payload
30+
* @param {TransformPayloadEvent} event
31+
* @param {RestServiceContext} context
32+
* @returns {object} the transformed request payload
33+
*/
34+
transformRequestPayload: async (event: TransformPayloadEvent, context: RestServiceContext): Promise<any> => {
35+
return event.payload;
36+
},
37+
38+
/**
39+
* Handler to transform the response payload
40+
* @param {TransformPayloadEvent} event
41+
* @param {RestServiceContext} context
42+
* @returns {object} the transformed response payload
43+
*/
44+
transformResponsePayload: async (event: TransformPayloadEvent, context: RestServiceContext): Promise<any> => {
45+
return event.payload;
46+
}
47+
48+
};
49+
}
50+
}

0 commit comments

Comments
 (0)