chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1 @@
|
||||
.botpress
|
||||
@@ -0,0 +1,13 @@
|
||||
import rootConfig from '../../eslint.config.mjs'
|
||||
|
||||
export default [
|
||||
...rootConfig,
|
||||
{
|
||||
languageOptions: {
|
||||
parserOptions: {
|
||||
project: ['./tsconfig.json'],
|
||||
tsconfigRootDir: import.meta.dirname,
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
@@ -0,0 +1,13 @@
|
||||
The Asana Integration facilitates the connection between your Botpress and Asana, a widely used project management platform. By utilizing this integration, you can effortlessly oversee your projects and tasks directly from your chatbot interface.
|
||||
|
||||
## Setup
|
||||
|
||||
To establish this integration, you will need to provide your **Asana API token** and **workspace ID**. After the setup, you can make use of the built-in functionalities to perform actions such as task creation, task updates, task comment addition, and more.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
Before activating the Botpress Asana Integration, please ensure the availability of the following:
|
||||
|
||||
- Authorized access to an existing Asana workspace.
|
||||
|
||||
- A valid API token generated from Asana (Personal Access Token).
|
||||
@@ -0,0 +1,10 @@
|
||||
<svg width="110" height="102" viewBox="0 0 110 102" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_370_36560)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M86.0769 53.9995C72.8649 53.9995 62.1537 64.7445 62.1537 78.0002C62.1537 91.255 72.8649 102 86.0769 102C99.2893 102 110 91.255 110 78.0002C110 64.7445 99.2893 53.9995 86.0769 53.9995ZM23.923 54.0018C10.7108 54.0018 0 64.7445 0 78.0002C0 91.255 10.7108 102 23.923 102C37.1358 102 47.8472 91.255 47.8472 78.0002C47.8472 64.7445 37.1358 54.0018 23.923 54.0018ZM78.9227 23.9992C78.9227 37.2548 68.2125 48.001 55 48.001C41.7873 48.001 31.0771 37.2548 31.0771 23.9992C31.0771 10.7462 41.7873 0 55 0C68.2125 0 78.9227 10.7462 78.9227 23.9992Z" fill="#F06A6A"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_370_36560">
|
||||
<rect width="110" height="102" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 858 B |
@@ -0,0 +1,23 @@
|
||||
import { IntegrationDefinition } from '@botpress/sdk'
|
||||
|
||||
import { INTEGRATION_NAME } from './src/const'
|
||||
import { configuration, states, user, channels, actions } from './src/definitions'
|
||||
|
||||
export default new IntegrationDefinition({
|
||||
name: INTEGRATION_NAME,
|
||||
version: '0.3.14',
|
||||
title: 'Asana',
|
||||
readme: 'hub.md',
|
||||
description: 'Connect your bot to your Asana inbox, create and update tasks, add comments, and locate users.',
|
||||
icon: 'icon.svg',
|
||||
configuration,
|
||||
channels,
|
||||
user,
|
||||
actions,
|
||||
states,
|
||||
|
||||
attributes: {
|
||||
category: 'Project Management',
|
||||
repo: 'botpress',
|
||||
},
|
||||
})
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"name": "@botpresshub/asana",
|
||||
"description": "Asana integration for Botpress",
|
||||
"scripts": {
|
||||
"build": "bp add -y && bp build",
|
||||
"check:type": "tsc --noEmit",
|
||||
"check:bplint": "bp lint",
|
||||
"test": "vitest --run"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@botpress/sdk": "workspace:*",
|
||||
"@botpress/sdk-addons": "workspace:*",
|
||||
"asana": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@botpress/cli": "workspace:*",
|
||||
"@botpress/client": "workspace:*",
|
||||
"@botpress/common": "workspace:*",
|
||||
"@botpress/sdk": "workspace:*",
|
||||
"@types/asana": "^0.18.12"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { addCommentToTaskInputSchema } from '../misc/custom-schemas'
|
||||
import type { IntegrationProps } from '../misc/types'
|
||||
|
||||
import { getClient } from '../utils'
|
||||
|
||||
export const addCommentToTask: IntegrationProps['actions']['addCommentToTask'] = async ({ ctx, input, logger }) => {
|
||||
const validatedInput = addCommentToTaskInputSchema.parse(input)
|
||||
const asanaClient = getClient(ctx.configuration)
|
||||
let response
|
||||
try {
|
||||
response = await asanaClient.addCommentToTask(validatedInput.taskId, validatedInput.comment)
|
||||
logger.forBot().info(`Successful - Add Comment to Task - ${response.text}`)
|
||||
} catch (error) {
|
||||
logger.forBot().debug(`'Add Comment to Task' exception ${JSON.stringify(error)}`)
|
||||
response = {}
|
||||
}
|
||||
return { text: response.text || '' }
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { createTaskInputSchema } from '../misc/custom-schemas'
|
||||
import type { IntegrationProps } from '../misc/types'
|
||||
|
||||
import { getClient } from '../utils'
|
||||
|
||||
export const createTask: IntegrationProps['actions']['createTask'] = async ({ ctx, input, logger }) => {
|
||||
const validatedInput = createTaskInputSchema.parse(input)
|
||||
const asanaClient = getClient(ctx.configuration)
|
||||
const task = {
|
||||
workspace: ctx.configuration.workspaceGid,
|
||||
name: validatedInput.name,
|
||||
notes: validatedInput.notes || undefined,
|
||||
assignee: validatedInput.assignee || undefined,
|
||||
projects: validatedInput.projects?.split(',').map((project) => project.trim()) || undefined,
|
||||
parent: validatedInput.parent || undefined,
|
||||
due_on: validatedInput.due_on || validatedInput.start_on || undefined,
|
||||
start_on: validatedInput.start_on || undefined,
|
||||
}
|
||||
let response
|
||||
try {
|
||||
response = await asanaClient.createTask(task)
|
||||
logger.forBot().info(`Successful - Create Task - ${response.permalink_url}`)
|
||||
} catch (error) {
|
||||
logger.forBot().debug(`'Create Task' exception ${JSON.stringify(error)}`)
|
||||
response = {}
|
||||
}
|
||||
return { permalink_url: response.permalink_url || '' }
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
import { findUserInputSchema } from '../misc/custom-schemas'
|
||||
import type { IntegrationProps } from '../misc/types'
|
||||
|
||||
import { getClient } from '../utils'
|
||||
|
||||
export const findUser: IntegrationProps['actions']['findUser'] = async ({ ctx, input, logger }) => {
|
||||
const validatedInput = findUserInputSchema.parse(input)
|
||||
const asanaClient = getClient(ctx.configuration)
|
||||
let response
|
||||
try {
|
||||
response = await asanaClient.findUser(validatedInput.userEmail)
|
||||
logger.forBot().info(`Successful - Find User - ${response.name}`)
|
||||
} catch (error) {
|
||||
logger.forBot().debug(`'Find User' exception ${JSON.stringify(error)}`)
|
||||
response = {}
|
||||
}
|
||||
return response
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import { addCommentToTask } from './add-comment-to-task'
|
||||
import { createTask } from './create-task'
|
||||
import { findUser } from './find-user'
|
||||
import { updateTask } from './update-task'
|
||||
|
||||
export default { createTask, updateTask, findUser, addCommentToTask }
|
||||
@@ -0,0 +1,26 @@
|
||||
import { updateTaskInputSchema } from '../misc/custom-schemas'
|
||||
import type { IntegrationProps } from '../misc/types'
|
||||
|
||||
import { getClient } from '../utils'
|
||||
|
||||
export const updateTask: IntegrationProps['actions']['updateTask'] = async ({ ctx, input, logger }) => {
|
||||
const validatedInput = updateTaskInputSchema.parse(input)
|
||||
const asanaClient = getClient(ctx.configuration)
|
||||
const task = {
|
||||
name: validatedInput.name,
|
||||
notes: validatedInput.notes || undefined,
|
||||
assignee: validatedInput.assignee || undefined,
|
||||
due_on: validatedInput.due_on || validatedInput.start_on || undefined,
|
||||
start_on: validatedInput.start_on || undefined,
|
||||
completed: validatedInput.completed === 'true' ? true : undefined,
|
||||
}
|
||||
let response
|
||||
try {
|
||||
response = await asanaClient.updateTask(validatedInput.taskId, task)
|
||||
logger.forBot().info(`Successful - Update Task - ${response.permalink_url}`)
|
||||
} catch (error) {
|
||||
logger.forBot().debug(`'Update Task' exception ${JSON.stringify(error)}`)
|
||||
response = {}
|
||||
}
|
||||
return { permalink_url: response.permalink_url || '' }
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
import * as asana from 'asana'
|
||||
|
||||
export class AsanaApi {
|
||||
private _client: asana.Client
|
||||
|
||||
public constructor(apiToken: string) {
|
||||
this._client = asana.Client.create({
|
||||
defaultHeaders: {
|
||||
'Asana-Enable': 'new_goal_memberships,new_user_task_lists',
|
||||
},
|
||||
}).useAccessToken(apiToken)
|
||||
}
|
||||
|
||||
public async createTask(
|
||||
task: asana.resources.Tasks.CreateParams & { workspace: string }
|
||||
): Promise<asana.resources.Tasks.Type> {
|
||||
return await this._client.tasks.create(task)
|
||||
}
|
||||
|
||||
public async updateTask(
|
||||
taskId: string,
|
||||
task: asana.resources.Tasks.UpdateParams
|
||||
): Promise<asana.resources.Tasks.Type> {
|
||||
return await this._client.tasks.update(taskId, task)
|
||||
}
|
||||
|
||||
public async addCommentToTask(taskId: string, comment: string): Promise<asana.resources.Stories.Type> {
|
||||
return await this._client.tasks.addComment(taskId, { text: comment })
|
||||
}
|
||||
|
||||
public async findUser(userEmail: string): Promise<asana.resources.Users.Type> {
|
||||
return await this._client.users.findById(userEmail)
|
||||
}
|
||||
|
||||
public async findAllUsers(workspace: string): Promise<asana.resources.Users.Type[]> {
|
||||
const users = await this._client.users.findAll({ workspace })
|
||||
return users.data as asana.resources.Users.Type[]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export const INTEGRATION_NAME = 'asana'
|
||||
@@ -0,0 +1,65 @@
|
||||
import * as sdk from '@botpress/sdk'
|
||||
import {
|
||||
createTaskInputSchema,
|
||||
createTaskOutputSchema,
|
||||
updateTaskInputSchema,
|
||||
updateTaskOutputSchema,
|
||||
findUserInputSchema,
|
||||
findUserOutputSchema,
|
||||
addCommentToTaskInputSchema,
|
||||
addCommentToTaskOutputSchema,
|
||||
} from '../misc/custom-schemas'
|
||||
|
||||
type SdkActions = NonNullable<sdk.IntegrationDefinitionProps['actions']>
|
||||
type SdkAction = SdkActions[string]
|
||||
|
||||
const createTask = {
|
||||
title: 'Create Task',
|
||||
description: 'Create Task',
|
||||
input: {
|
||||
schema: createTaskInputSchema,
|
||||
},
|
||||
output: {
|
||||
schema: createTaskOutputSchema,
|
||||
},
|
||||
} satisfies SdkAction
|
||||
|
||||
const updateTask = {
|
||||
title: 'Update Task',
|
||||
description: 'Update Task by taskId',
|
||||
input: {
|
||||
schema: updateTaskInputSchema,
|
||||
},
|
||||
output: {
|
||||
schema: updateTaskOutputSchema,
|
||||
},
|
||||
} satisfies SdkAction
|
||||
|
||||
const findUser = {
|
||||
title: 'Find User',
|
||||
description: 'Find User by userId',
|
||||
input: {
|
||||
schema: findUserInputSchema,
|
||||
},
|
||||
output: {
|
||||
schema: findUserOutputSchema,
|
||||
},
|
||||
} satisfies SdkAction
|
||||
|
||||
const addCommentToTask = {
|
||||
title: 'Add Comment to Task',
|
||||
description: 'Add Comment to Task, by task ID',
|
||||
input: {
|
||||
schema: addCommentToTaskInputSchema,
|
||||
},
|
||||
output: {
|
||||
schema: addCommentToTaskOutputSchema,
|
||||
},
|
||||
} satisfies SdkAction
|
||||
|
||||
export const actions = {
|
||||
createTask,
|
||||
updateTask,
|
||||
findUser,
|
||||
addCommentToTask,
|
||||
} satisfies SdkActions
|
||||
@@ -0,0 +1,13 @@
|
||||
import { IntegrationDefinitionProps, messages } from '@botpress/sdk'
|
||||
|
||||
export const channels = {
|
||||
channel: {
|
||||
title: 'Channel',
|
||||
description: 'The channel for Asana',
|
||||
messages: {
|
||||
...messages.defaults,
|
||||
markdown: messages.markdown,
|
||||
bloc: messages.markdownBloc,
|
||||
},
|
||||
},
|
||||
} satisfies IntegrationDefinitionProps['channels']
|
||||
@@ -0,0 +1,32 @@
|
||||
import { z, IntegrationDefinitionProps } from '@botpress/sdk'
|
||||
|
||||
export { actions } from './actions'
|
||||
export { channels } from './channels'
|
||||
|
||||
export const configuration = {
|
||||
schema: z.object({
|
||||
apiToken: z.string().min(1).title('API Token').describe('API Token'),
|
||||
workspaceGid: z.string().min(1).title('Workspace Global ID').describe('Workspace Global ID'),
|
||||
}),
|
||||
} satisfies IntegrationDefinitionProps['configuration']
|
||||
|
||||
export const states = {
|
||||
// voidStateOne: {
|
||||
// type: 'integration',
|
||||
// schema: z.object({
|
||||
// dataField: z.string(),
|
||||
// }),
|
||||
// },
|
||||
// voidStateTwo: {
|
||||
// type: 'conversation',
|
||||
// schema: z.object({
|
||||
// otherDataField: z.string(),
|
||||
// }),
|
||||
// },
|
||||
} satisfies IntegrationDefinitionProps['states']
|
||||
|
||||
export const user = {
|
||||
tags: {
|
||||
// id: {},
|
||||
},
|
||||
} satisfies IntegrationDefinitionProps['user']
|
||||
@@ -0,0 +1,14 @@
|
||||
import { reporting } from '@botpress/sdk-addons'
|
||||
import actions from './actions'
|
||||
import { register, unregister, channels, handler } from './setup'
|
||||
import * as bp from '.botpress'
|
||||
|
||||
const integration = new bp.Integration({
|
||||
register,
|
||||
unregister,
|
||||
actions,
|
||||
channels,
|
||||
handler,
|
||||
})
|
||||
|
||||
export default reporting.wrapIntegration(integration)
|
||||
@@ -0,0 +1,95 @@
|
||||
import { z } from '@botpress/sdk'
|
||||
import { photoSchema, workspaceSchema } from './sub-schemas'
|
||||
|
||||
export const createTaskInputSchema = z.object({
|
||||
name: z.string().describe('The name of the task (e.g. "My Test Task")').title('Name'),
|
||||
notes: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe('The description of the task (Optional) (e.g. "This is my other task created using the Asana API")')
|
||||
.title('Notes'),
|
||||
assignee: z
|
||||
.string()
|
||||
.optional()
|
||||
.default('me')
|
||||
.describe(
|
||||
'The ID of the user who will be assigned to the task or "me" to assign to the current user (Optional) (e.g. "1215207682932839") (Default: "me")'
|
||||
)
|
||||
.title('Assignee'),
|
||||
projects: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
'The project IDs should be strings separated by commas (Optional) (e.g. "1205199808673678, 1215207282932839").'
|
||||
)
|
||||
.title('Projects'),
|
||||
parent: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe('The ID of the parent task (Optional) (e.g. "1205206556256028")')
|
||||
.title('Parent'),
|
||||
start_on: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe('The start date of the task in YYYY-MM-DD format (Optional) (e.g. "2023-08-13")')
|
||||
.title('Start On'),
|
||||
due_on: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe('The due date of the task without a specific time in YYYY-MM-DD format (Optional) (e.g. "2023-08-15")')
|
||||
.title('Due On'),
|
||||
})
|
||||
|
||||
export const taskOutputSchema = z.object({
|
||||
permalink_url: z.string().describe('The permalink url').title('Permalink Url'),
|
||||
})
|
||||
export const createTaskOutputSchema = taskOutputSchema
|
||||
|
||||
export const updateTaskInputSchema = createTaskInputSchema
|
||||
.omit({
|
||||
projects: true,
|
||||
parent: true,
|
||||
})
|
||||
.extend({
|
||||
taskId: z.string().describe('Task ID to update').title('Task ID'),
|
||||
name: z.string().optional().describe('The name of the task (Optional) (e.g. "My Test Task")').title('Name'),
|
||||
assignee: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
'The ID of the user who will be assigned to the task or "me" to assign to the current user (Optional) (e.g. "1215207682932839")'
|
||||
)
|
||||
.title('Assignee'),
|
||||
completed: z
|
||||
.string()
|
||||
.optional()
|
||||
.describe(
|
||||
'If the task is completed, enter "true" (without quotes), otherwise it will keep its previous status. (Optional)'
|
||||
)
|
||||
.title('Completed'),
|
||||
})
|
||||
export const updateTaskOutputSchema = taskOutputSchema
|
||||
|
||||
export const findUserInputSchema = z.object({
|
||||
userEmail: z.string().describe('User Email (e.g. "mrsomebody@example.com")').title('User Email'),
|
||||
})
|
||||
|
||||
export const findUserOutputSchema = z
|
||||
.object({
|
||||
gid: z.string().describe('The GID of the User').title('GID'),
|
||||
name: z.string().describe('The name of the user').title('Name'),
|
||||
email: z.string().describe('The email of the user').title('Email'),
|
||||
photo: photoSchema.describe('The photo of the user').title('Photo'),
|
||||
resource_type: z.string().describe('The resource type of the user').title('Resource Type'),
|
||||
workspaces: z.array(workspaceSchema).describe('List of the workspaces').title('Workspaces'),
|
||||
})
|
||||
.partial()
|
||||
|
||||
export const addCommentToTaskInputSchema = z.object({
|
||||
taskId: z.string().describe('Task ID to comment').title('Task ID'),
|
||||
comment: z.string().describe('Content of the comment to be added').title('Comment'),
|
||||
})
|
||||
|
||||
export const addCommentToTaskOutputSchema = z.object({
|
||||
text: z.string().describe('The text of the comment').title('Text'),
|
||||
})
|
||||
@@ -0,0 +1,19 @@
|
||||
import { z } from '@botpress/sdk'
|
||||
|
||||
const workspaceSchema = z.object({
|
||||
gid: z.string().describe('The GID of the workspace').title('GID'),
|
||||
name: z.string().describe('The name of the workspace').title('Name'),
|
||||
resource_type: z.string().describe('The resource type of the workspace').title('Resource Type'),
|
||||
})
|
||||
|
||||
const photoSchema = z
|
||||
.object({
|
||||
image_21x21: z.string().describe('An Image 21 by 21').title('Image 21x21'),
|
||||
image_27x27: z.string().describe('An Image 27 by 27').title('Image 27x27'),
|
||||
image_36x36: z.string().describe('An Image 36 by 36').title('Image 36x36'),
|
||||
image_60x60: z.string().describe('An Image 60 by 60').title('Image 60x60'),
|
||||
image_128x128: z.string().describe('An Image 128 by 128').title('Image 128x128'),
|
||||
})
|
||||
.nullable()
|
||||
|
||||
export { workspaceSchema, photoSchema }
|
||||
@@ -0,0 +1,9 @@
|
||||
import * as bp from '.botpress'
|
||||
|
||||
export type Configuration = bp.configuration.Configuration
|
||||
export type IntegrationProps = bp.IntegrationProps
|
||||
export type IntegrationCtx = bp.Context
|
||||
export type RegisterFunction = IntegrationProps['register']
|
||||
export type UnregisterFunction = IntegrationProps['unregister']
|
||||
export type Channels = IntegrationProps['channels']
|
||||
export type Handler = IntegrationProps['handler']
|
||||
@@ -0,0 +1,50 @@
|
||||
import type { Channels } from '../misc/types'
|
||||
|
||||
class NotImplementedError extends Error {
|
||||
public constructor() {
|
||||
super('Not implemented')
|
||||
}
|
||||
}
|
||||
|
||||
export const channels: Channels = {
|
||||
channel: {
|
||||
messages: {
|
||||
text: async () => {
|
||||
throw new NotImplementedError()
|
||||
},
|
||||
image: async () => {
|
||||
throw new NotImplementedError()
|
||||
},
|
||||
markdown: async () => {
|
||||
throw new NotImplementedError()
|
||||
},
|
||||
audio: async () => {
|
||||
throw new NotImplementedError()
|
||||
},
|
||||
video: async () => {
|
||||
throw new NotImplementedError()
|
||||
},
|
||||
file: async () => {
|
||||
throw new NotImplementedError()
|
||||
},
|
||||
location: async () => {
|
||||
throw new NotImplementedError()
|
||||
},
|
||||
carousel: async () => {
|
||||
throw new NotImplementedError()
|
||||
},
|
||||
card: async () => {
|
||||
throw new NotImplementedError()
|
||||
},
|
||||
choice: async () => {
|
||||
throw new NotImplementedError()
|
||||
},
|
||||
dropdown: async () => {
|
||||
throw new NotImplementedError()
|
||||
},
|
||||
bloc: async () => {
|
||||
throw new NotImplementedError()
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
import type { Handler } from '../misc/types'
|
||||
|
||||
class NotImplementedError extends Error {
|
||||
public constructor() {
|
||||
super('Not implemented')
|
||||
}
|
||||
}
|
||||
|
||||
export const handler: Handler = async () => {
|
||||
throw new NotImplementedError()
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
export { register } from './register'
|
||||
export { unregister } from './unregister'
|
||||
export { channels } from './channels'
|
||||
export { handler } from './handler'
|
||||
@@ -0,0 +1,8 @@
|
||||
import type { RegisterFunction } from '../misc/types'
|
||||
|
||||
export const register: RegisterFunction = async () => {
|
||||
/**
|
||||
* This is called when an integration configuration is saved.
|
||||
* You should use this handler to instanciate ressources in the external service and ensure that the configuration is valid.
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
import type { UnregisterFunction } from '../misc/types'
|
||||
|
||||
export const unregister: UnregisterFunction = async () => {
|
||||
/**
|
||||
* This is called when a bot removes the integration.
|
||||
* You should use this handler to instanciate ressources in the external service and ensure that the configuration is valid.
|
||||
*/
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
import { AsanaApi } from '../client'
|
||||
import type { Configuration } from '../misc/types'
|
||||
|
||||
export const getClient = (config: Configuration) => new AsanaApi(config.apiToken)
|
||||
@@ -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