Security News
Maven Central Adds Sigstore Signature Validation
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.
@botmock/export
Advanced tools
Provides classes and methods for integration of Botmock data with development platforms.
@botmock/export
Provides classes and methods for integration of Botmock data with development platforms.
npm install @botmock/export
The previous exporters were designed to transform your Botmock project directly into the format required by the end platform by cloning a particular repository, running
npm install
and thennpm start
.@botmock/export
, however, has been redesigned to be more granular and developer-friendly. Let's see what this means.
This short example shows how to use the included DialogflowExporter
to export data from a specific Botmock project to the Dialogflow platform.
import { DialogflowExporter, FileWriter, Kind } from "@botmock/export";
const projectReference: ProjectReference = {
teamId: process.env.TEAM_ID as string,
projectId: process.env.PROJECT_ID as string,
boardId: process.env.BOARD_ID,
};
/**
* This main function boots up the `DialogflowExporter` with an access token,
* and then runs `exportProjectUnderDataTransformations` on `projectReference` to create `data`.
*
* `data` is an object where keys are filepaths and values are descriptions of data that belong
* in those filepaths.
*
* `data` can then be passed to `FileWriter`'s `writeAllResourcesToFiles` method to write the
* data to the correct directory paths.
*
* @example
* ```
* npm run start
* ```
*/
async function main(): Promise<void> {
const exporter = new DialogflowExporter({ token: process.env.TOKEN as string });
const { data } = await exporter.exportProjectUnderDataTransformations({ projectReference });
const writeResult = await (new FileWriter()).writeAllResourcesToFiles({ data });
if (writeResult.kind === Kind.OK) {
console.log(writeResult.value);
}
}
main().catch((err: Error) => {
console.error(err);
});
What if you are targeting a platform that is not included in the stock exporters?
BaseExporter
is available on @botmock/export
for this reason.
Let's see how to use it.
Create a new file "./exporter.ts", and add the following.
import { BaseExporter } from "@botmock/export";
Imagine we have our own platform called "Flatland", and imagine this platform describes projects via a .yml
file and .json
file.
We would like to integrate data from Botmock into it.
The first step is to write our own class that extends BaseExporter
.
import {
BaseExporter,
DataTransformation,
Resources,
Botmock,
} from "@botmock/export";
export class FlatlandExporter extends BaseExporter { }
This code produces a TypeScript compilation error. This is because BaseExporter
needs to have a property called dataTransformations
defined on it.
dataTransformations
is a Map
that relates directory paths to functions that take Resources
,
and return DataTransformation
.
Resources
resources
are the single parameter passed to every value in a dataTranformation
Map
.
Resources might look like the following.
{
"intents": [
{
"id": "6ef70cd0-9c20-11ea-9d3b-91ab6dd1aa2f",
"name": "begin",
"utterances": {
"en": [
{
"text": "hi",
"variables": []
}
]
},
"created_at": {
"date": "2020-05-22 11:36:10.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"updated_at": {
"date": "2020-05-22 11:36:10.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"is_global": false,
"slots": []
},
{
"id": "2ff08a20-8e17-11ea-9af2-3b66755d0983",
"name": "one",
"utterances": {
"en": [
{
"text": "one",
"variables": []
}
]
},
"created_at": {
"date": "2020-05-04 14:54:42.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"updated_at": {
"date": "2020-05-04 14:54:42.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"is_global": false,
"slots": []
},
{
"id": "0c900ab0-a5ac-11ea-b102-696fc338cf15",
"name": "second_intent",
"utterances": {
"en": [
{
"text": "give %ReservationPersonsNumber%",
"variables": [
{
"id": "fe1c9ed0-8e0e-11ea-a54c-35dc7cb8db58",
"name": "%ReservationPersonsNumber%",
"type": "int",
"entity": "d9e693a0-4455-11ea-b208-ab55d7896de3",
"default_value": "",
"start_index": 5
}
]
}
]
},
"created_at": {
"date": "2020-06-03 15:08:15.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"updated_at": {
"date": "2020-06-03 15:08:15.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"is_global": false,
"slots": [
{
"id": "f0256a7b-600a-45a1-a818-9fadadce0ae4",
"variable_id": "fe1c9ed0-8e0e-11ea-a54c-35dc7cb8db58",
"is_required": true,
"prompt": "missing persons!"
}
]
}
],
"entities": [
{
"id": "fe1a7800-8e0e-11ea-b472-e3ecdf3932f8",
"name": "DinnerOrLunch",
"data": {
"en": [
{
"value": "dinner",
"synonyms": []
},
{
"value": "lunch",
"synonyms": []
}
]
},
"created_at": {
"date": "2020-05-04 13:56:03.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"updated_at": {
"date": "2020-05-04 13:56:03.000000",
"timezone_type": 3,
"timezone": "UTC"
}
},
{
"id": "fe1e56d0-8e0e-11ea-8a1a-45ca961859cb",
"name": "ReservationPersonsNumber",
"data": {
"en": [
{
"value": "42",
"synonyms": []
}
]
},
"created_at": {
"date": "2020-05-04 13:56:03.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"updated_at": {
"date": "2020-05-04 13:56:03.000000",
"timezone_type": 3,
"timezone": "UTC"
}
}
],
"variables": [
{
"id": "fe17b400-8e0e-11ea-89b9-93f612e81ac2",
"name": "DinnerOrLunch",
"default_value": "dinner",
"type": "text",
"entity": "f62f1e60-4455-11ea-ae09-b7ba8a9ae270",
"created_at": {
"date": "2020-05-04 13:56:03.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"updated_at": {
"date": "2020-05-04 13:56:03.000000",
"timezone_type": 3,
"timezone": "UTC"
}
},
{
"id": "fe1c9ed0-8e0e-11ea-a54c-35dc7cb8db58",
"name": "ReservationPersonsNumber",
"default_value": "",
"type": "int",
"entity": "d9e693a0-4455-11ea-b208-ab55d7896de3",
"created_at": {
"date": "2020-05-04 13:56:03.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"updated_at": {
"date": "2020-05-04 13:56:03.000000",
"timezone_type": 3,
"timezone": "UTC"
}
}
],
"project": {
"id": "8d550c20-8d3a-11ea-aa4e-5f57749d4d32",
"name": "basic",
"type": "flow",
"platform": "multi-channel",
"channels": [
"google-actions",
"generic"
],
"locales": [
"en",
"es"
],
"created_at": {
"date": "2020-05-03 12:35:20.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"updated_at": {
"date": "2020-06-17 13:28:26.000000",
"timezone_type": 3,
"timezone": "UTC"
}
},
"board": {
"board": {
"root_messages": [
"8d585900-8d3a-11ea-b32a-67229b391039"
],
"messages": [
{
"message_id": "8d585900-8d3a-11ea-b32a-67229b391039",
"message_type": "response",
"next_message_ids": [
{
"message_id": "0ac39c3f-ebfe-4f31-8ec9-a551395e4d6b",
"action": "*",
"intent": {
"label": "begin",
"value": "6ef70cd0-9c20-11ea-9d3b-91ab6dd1aa2f"
},
"conditional": {
"id": "g-V7kpFszuWdt8q_wdDnXor",
"rules": [],
"combinator": "and",
"not": false
}
}
],
"previous_message_ids": [],
"is_root": true,
"node_name": "Starting Point",
"payload": {
"en": {
"generic": {
"blocks": []
}
}
}
},
{
"message_id": "0ac39c3f-ebfe-4f31-8ec9-a551395e4d6b",
"message_type": "response",
"next_message_ids": [
{
"message_id": "52611df2-7216-4c0c-94bf-3707b08eda4b",
"action": "*",
"intent": {
"label": "one",
"value": "2ff08a20-8e17-11ea-9af2-3b66755d0983"
},
"conditional": {
"id": "g-CSNPKr7MiwLxfeUMUdb3A",
"rules": [],
"combinator": "and",
"not": false
}
}
],
"previous_message_ids": [
{
"message_id": "8d585900-8d3a-11ea-b32a-67229b391039",
"action": "*"
}
],
"is_root": false,
"node_name": "First block",
"payload": {
"en": {
"generic": {
"blocks": [
{
"component_type": "text",
"nodeName": "Bot Says",
"context": [],
"text": "one thing",
"audio_file": "",
"ssml": "",
"delay": 2000,
"alternate_replies": [
"another thing"
]
},
{
"component_type": "text",
"nodeName": "Bot Says",
"context": [],
"text": "one more thing!",
"audio_file": "",
"ssml": "",
"delay": 2000
},
{
"component_type": "button",
"nodeName": "Button",
"context": [],
"text": "one",
"buttons": [
{
"type": "postback",
"title": "one",
"payload": "ONE"
}
],
"audio_file": "",
"ssml": "",
"delay": 2000,
"nextMessagesIds": []
}
]
}
}
}
},
{
"message_id": "52611df2-7216-4c0c-94bf-3707b08eda4b",
"message_type": "response",
"next_message_ids": [
{
"message_id": "7e236f12-d02a-4eac-8939-1221533baa4c",
"action": "*",
"intent": {
"label": "second_intent",
"value": "0c900ab0-a5ac-11ea-b102-696fc338cf15"
},
"conditional": {
"id": "g-P6xjtHxlyKJ6wHjN8FLYw",
"rules": [],
"combinator": "and",
"not": false
}
}
],
"previous_message_ids": [
{
"message_id": "0ac39c3f-ebfe-4f31-8ec9-a551395e4d6b",
"action": "*"
}
],
"is_root": false,
"node_name": "Response block",
"payload": {
"en": {
"generic": {
"blocks": [
{
"component_type": "text",
"nodeName": "Bot Says",
"context": [],
"text": "Says!",
"audio_file": "",
"ssml": "",
"delay": 2000
}
]
},
"google-actions": {
"blocks": [
{
"component_type": "text",
"nodeName": "Bot Says",
"text": "Your text here",
"buttons": [],
"ssml": "",
"audio_file": "",
"delay": 2000
},
{
"component_type": "card",
"nodeName": "Card",
"image_url": "https://app.botmock.com/img/placeholder.png",
"title": "This is your card title",
"subtitle": "",
"text": "This is the body of the card.",
"link": "",
"ssml": "",
"audio_file": "",
"delay": 2000
}
]
}
}
}
},
{
"message_id": "7e236f12-d02a-4eac-8939-1221533baa4c",
"message_type": "response",
"next_message_ids": [],
"previous_message_ids": [
{
"message_id": "52611df2-7216-4c0c-94bf-3707b08eda4b",
"action": "*"
}
],
"is_root": false,
"node_name": "Response block",
"payload": {
"en": {
"google-actions": {
"blocks": []
},
"generic": {
"blocks": [
{
"component_type": "quick_replies",
"nodeName": "Quick Replies",
"text": "Your text goes here...",
"quick_replies": [
{
"content_type": "text",
"title": "Button",
"image_url": "",
"payload": "BUTTON"
}
],
"audio_file": "",
"ssml": "",
"delay": 2000
}
]
}
},
"es": {
"google-actions": {
"blocks": []
},
"generic": {
"blocks": []
}
}
}
}
]
},
"slots": {
"6ef70cd0-9c20-11ea-9d3b-91ab6dd1aa2f": [],
"2ff08a20-8e17-11ea-9af2-3b66755d0983": [],
"0c900ab0-a5ac-11ea-b102-696fc338cf15": [
{
"id": "f0256a7b-600a-45a1-a818-9fadadce0ae4",
"variable_id": "fe1c9ed0-8e0e-11ea-a54c-35dc7cb8db58",
"is_required": true,
"prompt": "missing persons!"
}
]
},
"variables": [
{
"id": "fe17b400-8e0e-11ea-89b9-93f612e81ac2",
"name": "DinnerOrLunch",
"default_value": "dinner",
"type": "text",
"entity": "f62f1e60-4455-11ea-ae09-b7ba8a9ae270",
"created_at": {
"date": "2020-05-04 13:56:03.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"updated_at": {
"date": "2020-05-04 13:56:03.000000",
"timezone_type": 3,
"timezone": "UTC"
}
},
{
"id": "fe1c9ed0-8e0e-11ea-a54c-35dc7cb8db58",
"name": "ReservationPersonsNumber",
"default_value": "",
"type": "int",
"entity": "d9e693a0-4455-11ea-b208-ab55d7896de3",
"created_at": {
"date": "2020-05-04 13:56:03.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"updated_at": {
"date": "2020-05-04 13:56:03.000000",
"timezone_type": 3,
"timezone": "UTC"
}
}
],
"created_at": {
"date": "2020-05-03 12:35:20.000000",
"timezone_type": 3,
"timezone": "UTC"
},
"updated_at": {
"date": "2020-06-17 13:28:11.000000",
"timezone_type": 3,
"timezone": "UTC"
}
}
}
DataTransformation
DataTransformation
interface should be returned by every function in a dataTranformation
Map
.
It can be an array of objects, or a single object that has the following structure
{
filename: string;
data: any;
}
export class FlatlandExporter extends BaseExporter {
/**
* Returns transformation from resources.
* @param resources Botmock {@link Resources} object.
*/
#outputDataTransformation = (resources: Resources): DataTransformation => {
return [
{
filename: `${resources.project.name}.geo.yml`,
data: this.#createGeometries({
board: resources.board,
project: resources.project,
intents: resources.intents,
entities: resources.entities,
variables: resources.variables,
}),
},
{
filename: `${resources.project.name}.ctx.json`,
data: this.#createConversationContext(),
},
];
};
/**
*
*/
dataTransformations = new Map([
["./output", this.#outputDataTransformation],
]);
}
Then, FlatlandExporter
can be used to write files just like in the stock exporter example.
async function main(args: string[]): Promise<void> {
const exporter = new FlatlandExporter({ token: process.env.TOKEN as string });
const { data } = await exporter.exportProjectUnderDataTransformations({ projectReference });
await (new FileWriter()).writeAllResourcesToFiles({ data });
}
data
structureThe data
property returned by exportProjectUnderDataTransformations
is an object that relates directory paths to objects describing the filename and contents.
It may look like the following.
{
"./": [
{
"filename": "agent.json",
"data": {
"description": "",
"language": "en",
"shortDescription": "",
"examples": "",
"linkToDocs": "",
"disableInteractionLogs": false,
"disableStackdriverLogs": true,
"googleAssistant": {
"googleAssistantCompatible": false,
"project": "basic",
"welcomeIntentSignInRequired": false,
"startIntents": [],
"systemIntents": [],
"endIntentIds": [],
"oAuthLinking": {
"required": false,
"providerId": "",
"authorizationUrl": "",
"tokenUrl": "",
"scopes": "",
"privacyPolicyUrl": "",
"grantType": "AUTH_CODE_GRANT"
},
"voiceType": "MALE_1",
"capabilities": [],
"env": "",
"protocolVersion": "V2",
"autoPreviewEnabled": false,
"isDeviceAgent": false
},
"defaultTimezone": "America/Barbados",
"webhook": {
"url": "",
"username": "",
"headers": {},
"available": false,
"useForDomains": false,
"cloudFunctionsEnabled": false,
"cloudFunctionsInitialized": false
},
"isPrivate": true,
"customClassifierMode": "use.after",
"mlMinConfidence": 0.3,
"supportedLanguages": [
"es"
],
"onePlatformApiVersion": "v2",
"analyzeQueryTextSentiment": false,
"enabledKnowledgeBaseNames": [],
"knowledgeServiceConfidenceAdjustment": -0.4,
"dialogBuilderMode": false,
"baseActionPackagesUrl": ""
}
},
{
"filename": "package.json",
"data": {
"version": "1.0.0"
}
}
],
"./entities": [
{
"filenames": [
"DinnerOrLunch.json",
"DinnerOrLunch_entries_en.json"
],
"data": [
{
"id": "fe1a7800-8e0e-11ea-b472-e3ecdf3932f8",
"name": "DinnerOrLunch",
"isOverridable": true,
"isEnum": false,
"isRegexp": false,
"automatedExpansion": false,
"allowFuzzyExtraction": false
},
[
{
"value": "dinner",
"synonyms": []
},
{
"value": "lunch",
"synonyms": []
}
]
]
},
{
"filenames": [
"ReservationPersonsNumber.json",
"ReservationPersonsNumber_entries_en.json"
],
"data": [
{
"id": "fe1e56d0-8e0e-11ea-8a1a-45ca961859cb",
"name": "ReservationPersonsNumber",
"isOverridable": true,
"isEnum": false,
"isRegexp": false,
"automatedExpansion": false,
"allowFuzzyExtraction": false
},
[
{
"value": "42",
"synonyms": []
}
]
]
}
],
"./intents": [
{
"filenames": [
"begin.json",
"begin_usersays_en.json"
],
"data": [
{
"id": "0ac39c3f-ebfe-4f31-8ec9-a551395e4d6b",
"name": "begin",
"auto": true,
"contexts": [
"begin"
],
"responses": [
{
"resetContexts": false,
"action": "input.welcome",
"affectedContexts": [
{
"name": "welcome",
"parameters": {},
"lifespan": 5
},
{
"name": "one",
"parameters": {},
"lifespan": 5
}
],
"parameters": [],
"messages": [
{
"type": 0,
"lang": "en",
"condition": "",
"speech": "one thing"
},
{
"type": 0,
"lang": "en",
"condition": "",
"speech": "one more thing!"
},
{
"type": 4,
"lang": "en",
"condition": "",
"payload": {
"component_type": "button",
"nodeName": "Button",
"context": [],
"text": "one",
"buttons": [
{
"type": "postback",
"title": "one",
"payload": "ONE"
}
],
"audio_file": "",
"ssml": "",
"delay": 2000,
"nextMessagesIds": []
}
}
],
"defaultResponsePlatforms": {},
"speech": []
}
],
"priority": 5000,
"webhookUsed": false,
"webhookForSlotFilling": false,
"fallbackIntent": false,
"events": [
{
"name": "WELCOME"
}
],
"conditionalResponses": [],
"condition": "",
"conditionalFollowupEvents": []
},
[
{
"id": "ed59bc6f-b208-42a8-bbaa-253747941ee1",
"data": [
{
"text": "hi",
"userDefined": false
}
],
"isTemplate": false,
"count": 0,
"updated": 0
},
{
"id": "f22e3a1d-c811-4838-8c54-74e7539c0cbb",
"data": [
{
"text": "hi",
"userDefined": false
}
],
"isTemplate": false,
"count": 0,
"updated": 0,
"isAuto": false
}
]
]
},
{
"filenames": [
"one.json",
"one_usersays_en.json"
],
"data": [
{
"id": "52611df2-7216-4c0c-94bf-3707b08eda4b",
"name": "one",
"auto": true,
"contexts": [
"one",
"begin"
],
"responses": [
{
"resetContexts": false,
"action": "input.welcome",
"affectedContexts": [
{
"name": "second_intent",
"parameters": {},
"lifespan": 5
}
],
"parameters": [],
"messages": [
{
"type": 0,
"lang": "en",
"condition": "",
"speech": "Says!"
},
{
"type": "simple_response",
"lang": "en",
"condition": "",
"textToSpeech": "Your text here"
},
{
"type": 4,
"lang": "en",
"condition": "",
"payload": {
"component_type": "card",
"nodeName": "Card",
"image_url": "https://app.botmock.com/img/placeholder.png",
"title": "This is your card title",
"subtitle": "",
"text": "This is the body of the card.",
"link": "",
"ssml": "",
"audio_file": "",
"delay": 2000
}
}
],
"defaultResponsePlatforms": {},
"speech": []
}
],
"priority": 5000,
"webhookUsed": false,
"webhookForSlotFilling": false,
"fallbackIntent": false,
"events": [],
"conditionalResponses": [],
"condition": "",
"conditionalFollowupEvents": []
},
[
{
"id": "aa82f86e-82a0-42e9-b330-47868471c263",
"data": [
{
"text": "hi",
"userDefined": false
}
],
"isTemplate": false,
"count": 0,
"updated": 0
},
{
"id": "0be85546-26f3-4539-b490-bb12d3f5ece2",
"data": [
{
"text": "one",
"userDefined": false
}
],
"isTemplate": false,
"count": 0,
"updated": 0,
"isAuto": false
}
]
]
},
{
"filenames": [
"second_intent.json",
"second_intent_usersays_en.json"
],
"data": [
{
"id": "7e236f12-d02a-4eac-8939-1221533baa4c",
"name": "second_intent",
"auto": true,
"contexts": [
"second_intent",
"one",
"begin"
],
"responses": [
{
"resetContexts": false,
"action": "input.welcome",
"affectedContexts": [],
"parameters": [
{
"id": "fe1c9ed0-8e0e-11ea-a54c-35dc7cb8db58",
"required": false,
"name": "ReservationPersonsNumber",
"value": "$",
"promptMessages": [],
"noMatchPromptMessages": [],
"outputDialogContexts": [],
"isList": false
}
],
"messages": [
{
"type": 4,
"lang": "en",
"condition": "",
"payload": {
"component_type": "quick_replies",
"nodeName": "Quick Replies",
"text": "Your text goes here...",
"quick_replies": [
{
"content_type": "text",
"title": "Button",
"image_url": "",
"payload": "BUTTON"
}
],
"audio_file": "",
"ssml": "",
"delay": 2000
}
}
],
"defaultResponsePlatforms": {},
"speech": []
}
],
"priority": 5000,
"webhookUsed": false,
"webhookForSlotFilling": false,
"fallbackIntent": false,
"events": [],
"conditionalResponses": [],
"condition": "",
"conditionalFollowupEvents": []
},
[
{
"id": "cad355d2-20bb-44b8-9fa4-0531d1307ea5",
"data": [
{
"text": "hi",
"userDefined": false
}
],
"isTemplate": false,
"count": 0,
"updated": 0
},
{
"id": "baf89010-c0d5-4159-a162-651b7a31aac2",
"data": [
{
"text": "give $ReservationPersonsNumber",
"userDefined": false
}
],
"isTemplate": false,
"count": 0,
"updated": 0,
"isAuto": false
}
]
]
}
]
}
The following filetypes are supported for the filename
property within DataTransformation
.
.json
.yml
.md
FAQs
## Overview
The npm package @botmock/export receives a total of 2 weekly downloads. As such, @botmock/export popularity was classified as not popular.
We found that @botmock/export demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Maven Central now validates Sigstore signatures, making it easier for developers to verify the provenance of Java packages.
Security News
CISOs are racing to adopt AI for cybersecurity, but hurdles in budgets and governance may leave some falling behind in the fight against cyber threats.
Research
Security News
Socket researchers uncovered a backdoored typosquat of BoltDB in the Go ecosystem, exploiting Go Module Proxy caching to persist undetected for years.