chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
import { z } from '@botpress/sdk'
|
||||
|
||||
export type Lead = z.infer<typeof leadSchema>
|
||||
export const leadSchema = z
|
||||
.object({
|
||||
id: z.number().title('ID').describe('Unique identifier of the lead'),
|
||||
email: z.string().email().title('Email').describe('Email address of the lead'),
|
||||
first_name: z.string().nullable().title('First Name').describe('First name of the lead'),
|
||||
last_name: z.string().nullable().title('Last Name').describe('Last name of the lead'),
|
||||
position: z.string().nullable().title('Position').describe('Job position of the lead'),
|
||||
company: z.string().nullable().title('Company').describe('Company name of the lead'),
|
||||
company_industry: z.string().nullable().title('Company Industry').describe('Industry of the lead company'),
|
||||
company_size: z.string().nullable().title('Company Size').describe('Size of the lead company'),
|
||||
confidence_score: z
|
||||
.number()
|
||||
.min(0)
|
||||
.max(100)
|
||||
.nullable()
|
||||
.title('Confidence Score')
|
||||
.describe('Confidence score of the lead email'),
|
||||
website: z.string().nullable().title('Website').describe('Website URL of the lead'),
|
||||
country_code: z.string().nullable().title('Country Code').describe('Country code of the lead'),
|
||||
source: z.string().nullable().title('Source').describe('Source of the lead'),
|
||||
linkedin_url: z.string().nullable().title('LinkedIn URL').describe('LinkedIn profile URL of the lead'),
|
||||
phone_number: z.string().nullable().title('Phone Number').describe('Phone number of the lead'),
|
||||
twitter: z.string().nullable().title('Twitter').describe('Twitter handle of the lead'),
|
||||
sync_status: z.string().nullable().title('Sync Status').describe('Synchronization status of the lead'),
|
||||
notes: z.string().nullable().title('Notes').describe('Additional notes about the lead'),
|
||||
sending_status: z.string().nullable().title('Sending Status').describe('Email sending status of the lead'),
|
||||
last_activity_at: z.string().nullable().title('Last Activity At').describe('Last activity timestamp of the lead'),
|
||||
last_contacted_at: z
|
||||
.string()
|
||||
.nullable()
|
||||
.title('Last Contacted At')
|
||||
.describe('Last contacted timestamp of the lead'),
|
||||
verification: z
|
||||
.object({
|
||||
date: z.string().nullable().title('Date').describe('Verification date of the lead email'),
|
||||
status: z.string().nullable().title('Status').describe('Verification status of the lead email'),
|
||||
})
|
||||
.title('Verification')
|
||||
.describe('Email verification details'),
|
||||
leads_list: z
|
||||
.object({
|
||||
id: z.number().title('ID').describe('ID of the leads list'),
|
||||
name: z.string().title('Name').describe('Name of the leads list'),
|
||||
leads_count: z.number().title('Leads Count').describe('Number of leads in the list'),
|
||||
})
|
||||
.title('Leads List')
|
||||
.describe('Leads list information'),
|
||||
created_at: z.string().title('Created At').describe('Creation timestamp of the lead'),
|
||||
})
|
||||
.catchall(z.string().nullable())
|
||||
.title('Lead')
|
||||
.describe('Schema representing a lead in Hunter.io')
|
||||
|
||||
export type LeadPayload = z.infer<typeof leadPayloadSchema>
|
||||
export const leadPayloadSchema = z
|
||||
.object({
|
||||
email: z.string().email().title('Email').describe('Email address of the lead'),
|
||||
first_name: z.string().optional().title('First Name').describe('First name of the lead'),
|
||||
last_name: z.string().optional().title('Last Name').describe('Last name of the lead'),
|
||||
position: z.string().optional().title('Position').describe('Job position of the lead'),
|
||||
company: z.string().optional().title('Company').describe('Company name of the lead'),
|
||||
company_industry: z.string().optional().title('Company Industry').describe('Industry of the lead company'),
|
||||
company_size: z.string().optional().title('Company Size').describe('Size of the lead company'),
|
||||
confidence_score: z
|
||||
.number()
|
||||
.min(0)
|
||||
.max(100)
|
||||
.optional()
|
||||
.title('Confidence Score')
|
||||
.describe('Confidence score of the lead email'),
|
||||
website: z.string().optional().title('Website').describe('Website URL of the lead'),
|
||||
country_code: z.string().optional().title('Country Code').describe('Country code of the lead'),
|
||||
source: z.string().optional().title('Source').describe('Source of the lead'),
|
||||
linkedin_url: z.string().optional().title('LinkedIn URL').describe('LinkedIn profile URL of the lead'),
|
||||
phone_number: z.string().optional().title('Phone Number').describe('Phone number of the lead'),
|
||||
twitter: z.string().optional().title('Twitter').describe('Twitter handle of the lead'),
|
||||
notes: z.string().optional().title('Notes').describe('Additional notes about the lead'),
|
||||
leads_list_id: z.number().optional().title('Leads List ID').describe('ID of the leads list'),
|
||||
leads_list_ids: z.array(z.number()).optional().title('Leads List IDs').describe('Array of leads list IDs'),
|
||||
custom_attributes: z
|
||||
.record(z.string())
|
||||
.optional()
|
||||
.title('Custom Attributes')
|
||||
.describe('Custom attributes for the lead'),
|
||||
})
|
||||
.title('Lead Payload')
|
||||
.describe('Schema for creating or updating a lead in Hunter.io')
|
||||
|
||||
export type SearchLeadsPayload = z.infer<typeof searchLeadsPayloadSchema>
|
||||
export const searchLeadsPayloadSchema = z
|
||||
.object({
|
||||
leads_list_id: z.number().optional().title('Leads List ID').describe('Filter by leads list ID'),
|
||||
email: z.string().optional().title('Email').describe('Filter by email address'),
|
||||
first_name: z.string().optional().title('First Name').describe('Filter by first name'),
|
||||
last_name: z.string().optional().title('Last Name').describe('Filter by last name'),
|
||||
position: z.string().optional().title('Position').describe('Filter by job position'),
|
||||
company: z.string().optional().title('Company').describe('Filter by company name'),
|
||||
industry: z.string().optional().title('Industry').describe('Filter by company industry'),
|
||||
website: z.string().optional().title('Website').describe('Filter by website URL'),
|
||||
country_code: z.string().optional().title('Country Code').describe('Filter by country code'),
|
||||
company_size: z.string().optional().title('Company Size').describe('Filter by company size'),
|
||||
source: z.string().optional().title('Source').describe('Filter by lead source'),
|
||||
twitter: z.string().optional().title('Twitter').describe('Filter by Twitter handle'),
|
||||
linkedin_url: z.string().optional().title('LinkedIn URL').describe('Filter by LinkedIn URL'),
|
||||
phone_number: z.string().optional().title('Phone Number').describe('Filter by phone number'),
|
||||
sync_status: z
|
||||
.enum(['pending', 'error', 'success'])
|
||||
.optional()
|
||||
.title('Sync Status')
|
||||
.describe('Filter by synchronization status'),
|
||||
sending_status: z
|
||||
.array(z.enum(['clicked', 'opened', 'sent', 'pending', 'error', 'bounced', 'unsubscribed', 'replied', '~']))
|
||||
.optional()
|
||||
.title('Sending Status')
|
||||
.describe('Filter by email sending status'),
|
||||
verification_status: z
|
||||
.array(z.enum(['accept_all', 'disposable', 'invalid', 'unknown', 'valid', 'webmail', 'pending', '~']))
|
||||
.optional()
|
||||
.title('Verification Status')
|
||||
.describe('Filter by email verification status'),
|
||||
last_activity_at: z
|
||||
.enum(['*', '~'])
|
||||
.optional()
|
||||
.title('Last Activity At')
|
||||
.describe('Filter by last activity timestamp'),
|
||||
last_contacted_at: z
|
||||
.enum(['*', '~'])
|
||||
.optional()
|
||||
.title('Last Contacted At')
|
||||
.describe('Filter by last contacted timestamp'),
|
||||
custom_attributes: z
|
||||
.record(z.string())
|
||||
.optional()
|
||||
.title('Custom Attributes')
|
||||
.describe('Filter by custom attributes'),
|
||||
query: z.string().optional().title('Query').describe('Filter on first name, last name or email'),
|
||||
limit: z.number().min(1).max(1000).optional().title('Limit').describe('Maximum number of results to return'),
|
||||
offset: z.number().min(0).max(100000).optional().title('Offset').describe('Number of results to skip'),
|
||||
})
|
||||
.title('Search Leads Payload')
|
||||
.describe('Schema for searching leads in Hunter.io')
|
||||
@@ -0,0 +1,39 @@
|
||||
# Hunter Integration
|
||||
|
||||
## Overview
|
||||
|
||||
Connect your Botpress chatbot to [Hunter.io](https://hunter.io/), a leading platform for finding and managing professional email leads.
|
||||
|
||||
This integration allows your bot to interact with Hunter’s API to manage your lead database efficiently.
|
||||
|
||||
## Key Features
|
||||
|
||||
- Manage your leads directly from your bot
|
||||
- Retrieve or update existing lead information
|
||||
- Add new leads to your Hunter account
|
||||
|
||||
## Use Cases
|
||||
|
||||
- **Lead Management** – Centralize lead creation and updates directly from your chatbot
|
||||
- **CRM Automation** – Automatically push new user information to Hunter
|
||||
- **Sales Operations** – Keep your Hunter database clean and up to date
|
||||
|
||||
# Configuration
|
||||
|
||||
You need a **Hunter API key** to authenticate the integration.
|
||||
|
||||
1. Go to your [Hunter dashboard](https://hunter.io/dashboard).
|
||||
2. Navigate to **API** → copy your **API key**.
|
||||
3. In Botpress, open the Hunter integration settings and paste your API key.
|
||||
|
||||
Once saved, your bot will be able to perform operations via Hunter’s API.
|
||||
|
||||
## Limitations
|
||||
|
||||
- Only lead management endpoints are currently supported
|
||||
- Email verification, campaign management, and domain search are not yet implemented
|
||||
- Standard [Hunter API rate limits](https://hunter.io/api-documentation/v2) apply
|
||||
|
||||
# Changelog
|
||||
|
||||
- **1.0.0** – Initial release with lead management (list, retrieve, create, update, create/update, delete)
|
||||
@@ -0,0 +1,3 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="250px" height="250px" viewBox="240 240 370 370" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g><path style="opacity:0.982" fill="#fe5722" d="M 386.5,260.5 C 393.36,259.855 398.527,262.522 402,268.5C 407.367,278.261 411.367,288.594 414,299.5C 414.615,301.116 415.615,302.449 417,303.5C 419.667,302.167 421.667,300.167 423,297.5C 426.198,288.77 430.198,280.437 435,272.5C 439.529,265.293 445.362,263.793 452.5,268C 456.866,272.561 460.366,277.728 463,283.5C 471.782,305.731 481.115,327.731 491,349.5C 505.315,370.823 524.148,386.657 547.5,397C 560.102,398.83 572.769,400.163 585.5,401C 608.59,407.577 614.09,421.41 602,442.5C 595.917,451.918 588.417,460.085 579.5,467C 571.505,471.164 563.171,474.497 554.5,477C 535.06,482.359 515.726,488.026 496.5,494C 466.233,504.604 443.733,524.104 429,552.5C 423.945,565.388 420.778,578.721 419.5,592.5C 379.35,583.422 342.35,567.255 308.5,544C 295.149,533.987 285.649,521.154 280,505.5C 277.828,496.739 278.161,488.073 281,479.5C 289.115,462.824 295.448,445.49 300,427.5C 303.958,408.451 296.791,401.618 278.5,407C 266.621,412.434 255.288,418.601 244.5,425.5C 245.671,404.819 252.838,386.485 266,370.5C 272.901,362.928 280.401,356.095 288.5,350C 308.169,337.497 328.169,325.497 348.5,314C 358.914,304.919 366.081,293.752 370,280.5C 373.945,272.403 379.445,265.737 386.5,260.5 Z M 420.5,366.5 C 428.124,365.449 435.124,366.949 441.5,371C 449.789,378.078 457.289,385.912 464,394.5C 465.009,396.025 465.509,397.692 465.5,399.5C 451.221,401.632 436.888,401.132 422.5,398C 416.513,396.434 411.68,393.267 408,388.5C 407.217,378.403 411.384,371.07 420.5,366.5 Z"/></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.8 KiB |
@@ -0,0 +1,104 @@
|
||||
import { z, IntegrationDefinition } from '@botpress/sdk'
|
||||
import { leadSchema, leadPayloadSchema, searchLeadsPayloadSchema } from './definitions/schemas'
|
||||
|
||||
export default new IntegrationDefinition({
|
||||
name: 'hunter',
|
||||
version: '1.0.2',
|
||||
title: 'Hunter.io',
|
||||
description: 'Manage leads in Hunter.io',
|
||||
readme: 'hub.md',
|
||||
icon: 'icon.svg',
|
||||
configuration: {
|
||||
schema: z.object({
|
||||
apiKey: z.string().min(1, 'API Key is required').title('API Key').describe('Your Hunter.io API Key'),
|
||||
}),
|
||||
},
|
||||
actions: {
|
||||
getLeads: {
|
||||
title: 'Get Leads',
|
||||
description: 'Fetch leads from Hunter.io',
|
||||
input: {
|
||||
schema: z.object({
|
||||
search: searchLeadsPayloadSchema.title('Search filters').describe('Filters to search leads in Hunter.io'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
leads: z.array(leadSchema).title('Leads List').describe('List of leads retrieved from Hunter.io'),
|
||||
}),
|
||||
},
|
||||
},
|
||||
retrieveLead: {
|
||||
title: 'Retrieve Lead',
|
||||
description: 'Retrieve a specific lead by ID from Hunter.io',
|
||||
input: {
|
||||
schema: z.object({
|
||||
id: z.number().title('Lead ID').describe('The ID of the lead to retrieve'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
lead: leadSchema,
|
||||
}),
|
||||
},
|
||||
},
|
||||
createLead: {
|
||||
title: 'Create Lead',
|
||||
description: 'Create a new lead in Hunter.io',
|
||||
input: {
|
||||
schema: z.object({
|
||||
lead: leadPayloadSchema,
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
lead: leadSchema,
|
||||
}),
|
||||
},
|
||||
},
|
||||
createOrUpdateLead: {
|
||||
title: 'Create or update Lead',
|
||||
description: 'Create or update a lead in Hunter.io',
|
||||
input: {
|
||||
schema: z.object({
|
||||
lead: leadPayloadSchema,
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({
|
||||
lead: leadSchema,
|
||||
}),
|
||||
},
|
||||
},
|
||||
updateLead: {
|
||||
title: 'Update Lead',
|
||||
description: 'Update an existing lead in Hunter.io',
|
||||
input: {
|
||||
schema: z.object({
|
||||
id: z.number().title('Lead ID').describe('The ID of the lead to update'),
|
||||
lead: leadPayloadSchema.partial({ email: true }),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({}),
|
||||
},
|
||||
},
|
||||
deleteLead: {
|
||||
title: 'Delete Lead',
|
||||
description: 'Delete a lead from Hunter.io',
|
||||
input: {
|
||||
schema: z.object({
|
||||
id: z.number().title('Lead ID').describe('The ID of the lead to delete'),
|
||||
}),
|
||||
},
|
||||
output: {
|
||||
schema: z.object({}),
|
||||
},
|
||||
},
|
||||
},
|
||||
attributes: {
|
||||
category: 'Marketing & Email',
|
||||
guideSlug: 'hunter',
|
||||
repo: 'botpress',
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"name": "@botpresshub/hunter",
|
||||
"description": "Hunter.io integration for Botpress",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "bp add -y && bp build",
|
||||
"check:type": "tsc --noEmit",
|
||||
"check:bplint": "bp lint",
|
||||
"test": "vitest --run"
|
||||
},
|
||||
"dependencies": {
|
||||
"@botpress/client": "workspace:*",
|
||||
"@botpress/sdk": "workspace:*",
|
||||
"axios": "^1.13.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@botpress/cli": "workspace:*",
|
||||
"@botpress/sdk": "workspace:*"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
import axios, { AxiosInstance } from 'axios'
|
||||
import { LeadPayload, Lead, SearchLeadsPayload } from '../definitions/schemas'
|
||||
|
||||
type LeadPayloadWithOptionalEmail = Omit<LeadPayload, 'email'> & Partial<Pick<LeadPayload, 'email'>>
|
||||
|
||||
export class HunterClient {
|
||||
private _client: AxiosInstance
|
||||
|
||||
public constructor(apiKey: string) {
|
||||
this._client = axios.create({
|
||||
baseURL: 'https://api.hunter.io/v2/',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Cache-Control': 'no-cache',
|
||||
'X-API-KEY': apiKey,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
public async getLeads(data?: SearchLeadsPayload): Promise<Lead[]> {
|
||||
const params = new URLSearchParams()
|
||||
if (data) {
|
||||
for (const [key, value] of Object.entries(data)) {
|
||||
if (Array.isArray(value)) {
|
||||
for (const v of value) {
|
||||
params.append(key + '[]', String(v))
|
||||
}
|
||||
} else if (typeof value === 'object' && value !== null) {
|
||||
for (const [k, v] of Object.entries(value)) {
|
||||
params.append(`${key}[${k}]`, String(v))
|
||||
}
|
||||
} else if (value !== undefined) {
|
||||
params.append(key, String(value))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const res = await this._client.get('leads?' + params.toString())
|
||||
return res.data.data.leads
|
||||
}
|
||||
|
||||
public async retrieveLead(id: number): Promise<Lead> {
|
||||
const res = await this._client.get(`leads/${id}`)
|
||||
return res.data.data
|
||||
}
|
||||
|
||||
public async createLead(data: LeadPayload): Promise<Lead> {
|
||||
const res = await this._client.post('leads', data)
|
||||
return res.data.data
|
||||
}
|
||||
|
||||
public async createOrUpdateLead(data: LeadPayload): Promise<Lead> {
|
||||
const res = await this._client.put('leads', data)
|
||||
return res.data.data
|
||||
}
|
||||
|
||||
public async updateLead(id: number, data: LeadPayloadWithOptionalEmail): Promise<void> {
|
||||
await this._client.put(`leads/${id}`, data)
|
||||
}
|
||||
|
||||
public async deleteLead(id: number): Promise<void> {
|
||||
await this._client.delete(`leads/${id}`)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
import { isAxiosError } from 'axios'
|
||||
|
||||
export function parseError(error: unknown): string {
|
||||
if (isAxiosError(error)) {
|
||||
if (error.response) {
|
||||
if (typeof error.response.data === 'string') {
|
||||
return `Request failed with status ${error.response.status}: ${error.response.data}`
|
||||
}
|
||||
return `Request failed with status ${error.response.status}: ${error.message}`
|
||||
}
|
||||
if (error.request) {
|
||||
return `No response received: ${error.message}`
|
||||
}
|
||||
return `Axios error: ${error.message}`
|
||||
}
|
||||
|
||||
if (error instanceof Error) {
|
||||
return error.message
|
||||
}
|
||||
|
||||
if (typeof error === 'string' || typeof error === 'number' || typeof error === 'boolean') {
|
||||
return String(error)
|
||||
}
|
||||
|
||||
if (error && typeof error === 'object' && 'message' in error) {
|
||||
const message = error.message
|
||||
return parseError(message)
|
||||
}
|
||||
|
||||
return 'An unexpected error occurred'
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
import { RuntimeError } from '@botpress/sdk'
|
||||
import { HunterClient } from './client'
|
||||
import { parseError } from './error-parser'
|
||||
import * as bp from '.botpress'
|
||||
|
||||
export default new bp.Integration({
|
||||
register: async ({ ctx, logger }) => {
|
||||
try {
|
||||
const client = new HunterClient(ctx.configuration.apiKey)
|
||||
await client.getLeads()
|
||||
logger.forBot().info('Hunter.io integration configured successfully')
|
||||
} catch (error) {
|
||||
const parsed = parseError(error)
|
||||
throw new RuntimeError(`Failed to configure Hunter.io integration. Make sure the API key is valid: ${parsed}`)
|
||||
}
|
||||
},
|
||||
unregister: async ({ logger }) => {
|
||||
logger.forBot().info('Hunter.io integration unregistered')
|
||||
},
|
||||
actions: {
|
||||
getLeads: async ({ ctx, input, logger }) => {
|
||||
try {
|
||||
const hunterClient = new HunterClient(ctx.configuration.apiKey)
|
||||
|
||||
const leads = await hunterClient.getLeads(input.search)
|
||||
|
||||
logger.forBot().info('Leads got successfully from Hunter.io')
|
||||
|
||||
return { leads }
|
||||
} catch (error) {
|
||||
throw new RuntimeError(parseError(error))
|
||||
}
|
||||
},
|
||||
retrieveLead: async ({ ctx, input, logger }) => {
|
||||
try {
|
||||
const hunterClient = new HunterClient(ctx.configuration.apiKey)
|
||||
|
||||
const lead = await hunterClient.retrieveLead(input.id)
|
||||
|
||||
logger.forBot().info(`Lead with ID ${input.id} retrieved successfully from Hunter.io`)
|
||||
|
||||
return { lead }
|
||||
} catch (error) {
|
||||
throw new RuntimeError(parseError(error))
|
||||
}
|
||||
},
|
||||
createLead: async ({ ctx, input, logger }) => {
|
||||
try {
|
||||
const hunterClient = new HunterClient(ctx.configuration.apiKey)
|
||||
|
||||
const lead = await hunterClient.createLead(input.lead)
|
||||
|
||||
logger.forBot().info('Lead created successfully in Hunter.io')
|
||||
|
||||
return { lead }
|
||||
} catch (error) {
|
||||
throw new RuntimeError(parseError(error))
|
||||
}
|
||||
},
|
||||
createOrUpdateLead: async ({ ctx, input, logger }) => {
|
||||
try {
|
||||
const hunterClient = new HunterClient(ctx.configuration.apiKey)
|
||||
|
||||
const lead = await hunterClient.createOrUpdateLead(input.lead)
|
||||
|
||||
logger.forBot().info('Lead created/updated successfully in Hunter.io')
|
||||
|
||||
return { lead }
|
||||
} catch (error) {
|
||||
throw new RuntimeError(parseError(error))
|
||||
}
|
||||
},
|
||||
updateLead: async ({ ctx, input, logger }) => {
|
||||
try {
|
||||
const hunterClient = new HunterClient(ctx.configuration.apiKey)
|
||||
|
||||
await hunterClient.updateLead(input.id, input.lead)
|
||||
|
||||
logger.forBot().info(`Lead with ID ${input.id} updated successfully in Hunter.io`)
|
||||
|
||||
return {}
|
||||
} catch (error) {
|
||||
throw new RuntimeError(parseError(error))
|
||||
}
|
||||
},
|
||||
deleteLead: async ({ ctx, input, logger }) => {
|
||||
try {
|
||||
const hunterClient = new HunterClient(ctx.configuration.apiKey)
|
||||
|
||||
await hunterClient.deleteLead(input.id)
|
||||
|
||||
logger.forBot().info(`Lead with ID ${input.id} deleted successfully from Hunter.io`)
|
||||
|
||||
return {}
|
||||
} catch (error) {
|
||||
throw new RuntimeError(parseError(error))
|
||||
}
|
||||
},
|
||||
},
|
||||
channels: {},
|
||||
handler: async () => {},
|
||||
})
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"paths": { "*": ["./*"] },
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": [".botpress/**/*", "definitions/**/*", "src/**/*", "*.ts"]
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
import config from '../../vitest.config'
|
||||
export default config
|
||||
Reference in New Issue
Block a user