chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
import * as dynamodb from '@aws-sdk/client-dynamodb'
|
||||
import util from 'util'
|
||||
|
||||
const format = (x: any): string => util.inspect(x, { depth: null, colors: true })
|
||||
|
||||
const getEnv = (envName: string): string => {
|
||||
const envValue = process.env[envName]
|
||||
if (!envValue) {
|
||||
throw new Error(`${envName} is required`)
|
||||
}
|
||||
return envValue
|
||||
}
|
||||
|
||||
const endpoint = getEnv('endpoint')
|
||||
const table_name = getEnv('table_name')
|
||||
const partition_key = getEnv('partition_key')
|
||||
const sort_key = getEnv('sort_key')
|
||||
const index_name = getEnv('index_name')
|
||||
const index_sort_key = getEnv('index_sort_key')
|
||||
|
||||
console.info(`### endpoint=${endpoint} ###`)
|
||||
console.info(`### table_name=${table_name} ###`)
|
||||
console.info(`### partition_key=${partition_key} ###`)
|
||||
console.info(`### sort_key=${sort_key} ###`)
|
||||
console.info(`### index_name=${index_name} ###`)
|
||||
console.info(`### index_sort_key=${index_sort_key} ###`)
|
||||
|
||||
const main = async () => {
|
||||
const ddbClient = new dynamodb.DynamoDBClient({
|
||||
endpoint,
|
||||
})
|
||||
|
||||
const listTablesCmd = new dynamodb.ListTablesCommand({})
|
||||
const listTablesRes = await ddbClient.send(listTablesCmd)
|
||||
if (listTablesRes.TableNames?.includes(table_name)) {
|
||||
console.info(`Table ${table_name} already exists. Skipping creation.`)
|
||||
return
|
||||
}
|
||||
|
||||
const createTableCmd = new dynamodb.CreateTableCommand({
|
||||
TableName: table_name,
|
||||
AttributeDefinitions: [
|
||||
{
|
||||
AttributeName: partition_key,
|
||||
AttributeType: 'S',
|
||||
},
|
||||
{
|
||||
AttributeName: sort_key,
|
||||
AttributeType: 'S',
|
||||
},
|
||||
{
|
||||
AttributeName: index_sort_key,
|
||||
AttributeType: 'S',
|
||||
},
|
||||
],
|
||||
KeySchema: [
|
||||
{
|
||||
AttributeName: partition_key,
|
||||
KeyType: 'HASH',
|
||||
},
|
||||
{
|
||||
AttributeName: sort_key,
|
||||
KeyType: 'RANGE',
|
||||
},
|
||||
],
|
||||
BillingMode: 'PAY_PER_REQUEST',
|
||||
LocalSecondaryIndexes: [
|
||||
{
|
||||
IndexName: index_name,
|
||||
KeySchema: [
|
||||
{
|
||||
AttributeName: partition_key,
|
||||
KeyType: 'HASH',
|
||||
},
|
||||
{
|
||||
AttributeName: index_sort_key,
|
||||
KeyType: 'RANGE',
|
||||
},
|
||||
],
|
||||
Projection: {
|
||||
ProjectionType: 'KEYS_ONLY',
|
||||
},
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
await ddbClient.send(createTableCmd)
|
||||
|
||||
const describeTableCmd = new dynamodb.DescribeTableCommand({
|
||||
TableName: table_name,
|
||||
})
|
||||
|
||||
const describeTableRes = await ddbClient.send(describeTableCmd)
|
||||
|
||||
console.info('### Table Description ###')
|
||||
console.info(format(describeTableRes.Table))
|
||||
}
|
||||
|
||||
void main()
|
||||
.then(() => {
|
||||
process.exit(0)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -0,0 +1,58 @@
|
||||
import { Client } from '@botpress/client'
|
||||
import fslib from 'fs'
|
||||
import pathlib from 'path'
|
||||
|
||||
const getEnv = (envName: string): string => {
|
||||
const envValue = process.env[envName]
|
||||
if (!envValue) {
|
||||
throw new Error(`${envName} is required`)
|
||||
}
|
||||
return envValue
|
||||
}
|
||||
|
||||
const apiUrl = getEnv('BP_API_URL')
|
||||
const token = getEnv('BP_TOKEN')
|
||||
const workspaceId = getEnv('BP_WORKSPACE_ID')
|
||||
|
||||
const integrationPath = getEnv('CHAT_PATH')
|
||||
const botPath = getEnv('ECHO_PATH')
|
||||
|
||||
const readDevId = async (path: string): Promise<string> => {
|
||||
const cachePath = pathlib.join(path, '.botpress', 'project.cache.json')
|
||||
const cacheContent = await fslib.promises.readFile(cachePath, 'utf-8')
|
||||
const cache = JSON.parse(cacheContent)
|
||||
const { devId } = cache
|
||||
if (!devId) {
|
||||
throw new Error(`devId not found at "${cachePath}"`)
|
||||
}
|
||||
return devId
|
||||
}
|
||||
|
||||
const main = async () => {
|
||||
const client = new Client({
|
||||
apiUrl,
|
||||
token,
|
||||
workspaceId,
|
||||
})
|
||||
|
||||
const chatDevId = await readDevId(integrationPath)
|
||||
const echoDevId = await readDevId(botPath)
|
||||
|
||||
const { bot } = await client.getBot({ id: echoDevId })
|
||||
|
||||
const chatIntegrationInstance = bot.integrations[chatDevId]
|
||||
if (!chatIntegrationInstance) {
|
||||
throw new Error(`Chat integration with dev id "${chatDevId}" not installed in bot "${echoDevId}"`)
|
||||
}
|
||||
|
||||
console.info(chatIntegrationInstance.webhookId)
|
||||
}
|
||||
|
||||
void main()
|
||||
.then(() => {
|
||||
process.exit(0)
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -0,0 +1,165 @@
|
||||
import 'dotenv/config'
|
||||
import { Client } from '@botpress/client'
|
||||
import axios from 'axios'
|
||||
import { spawnSync } from 'child_process'
|
||||
import fs from 'fs'
|
||||
|
||||
type Args = Record<string, string | undefined>
|
||||
|
||||
const DEFAULT_API_URL = 'https://api.botpress.cloud'
|
||||
|
||||
function readIntegrationDefinition(integrationPath: string): any {
|
||||
const readCmdResult = spawnSync('pnpm', ['exec', 'bp', 'read', '--json', '--workDir', integrationPath])
|
||||
if (readCmdResult.status !== 0) {
|
||||
throw new Error(
|
||||
`Failed to read integration definition: ${readCmdResult.error?.message || readCmdResult.stderr.toString() || 'Unknown error'}`
|
||||
)
|
||||
}
|
||||
return JSON.parse(readCmdResult.stdout.toString())
|
||||
}
|
||||
|
||||
const _fallbackProfileArgs = () => ({
|
||||
apiUrl: undefined,
|
||||
workspaceId: undefined,
|
||||
token: undefined,
|
||||
})
|
||||
function getProfileArgs(): any {
|
||||
const activeProfileCmdResult = spawnSync('pnpm', ['exec', 'bp', 'profiles', 'active', '--json', '--displayToken'])
|
||||
if (activeProfileCmdResult.status !== 0) {
|
||||
console.debug(
|
||||
`Failed to get active profile: ${activeProfileCmdResult.error?.message || activeProfileCmdResult.stderr.toString() || 'Unknown error'}`
|
||||
)
|
||||
return _fallbackProfileArgs()
|
||||
}
|
||||
|
||||
try {
|
||||
return JSON.parse(activeProfileCmdResult.stdout.toString())
|
||||
} catch {
|
||||
return _fallbackProfileArgs()
|
||||
}
|
||||
}
|
||||
|
||||
function parseArgs(): Args {
|
||||
return process.argv.slice(2).reduce<Record<string, string | undefined>>((acc, arg) => {
|
||||
const [key, value] = arg.split('=')
|
||||
if (key && value) acc[key.replace(/^--/, '')] = value
|
||||
return acc
|
||||
}, {})
|
||||
}
|
||||
|
||||
async function uploadScripts({
|
||||
apiUrl,
|
||||
token,
|
||||
workspaceId,
|
||||
userEmail,
|
||||
integrationId,
|
||||
integrationPath,
|
||||
}: {
|
||||
apiUrl: string
|
||||
token: string
|
||||
workspaceId: string
|
||||
userEmail: string
|
||||
integrationId?: string
|
||||
integrationPath?: string
|
||||
}) {
|
||||
if (apiUrl !== DEFAULT_API_URL) {
|
||||
console.debug(`🔗 Using custom url ${apiUrl}`)
|
||||
}
|
||||
if (integrationId) {
|
||||
console.debug(`🧩 Using custom integration ID ${integrationId}`)
|
||||
}
|
||||
|
||||
integrationPath ||= '.'
|
||||
console.info('Reading integration definition...')
|
||||
const { name, version } = readIntegrationDefinition(integrationPath)
|
||||
|
||||
const client = new Client({ apiUrl, token, workspaceId })
|
||||
let integration: Awaited<ReturnType<Client['getIntegrationByName']>>['integration']
|
||||
console.info(`Fetching remote integration definition ${name} ${version}...`)
|
||||
if (!integrationId) {
|
||||
console.debug('No integration ID provided, searching by name and version')
|
||||
const getIntegrationResponse = await client.getIntegrationByName({
|
||||
name,
|
||||
version,
|
||||
})
|
||||
integration = getIntegrationResponse.integration
|
||||
} else {
|
||||
console.debug('Integration ID provided, fetching by ID')
|
||||
const getIntegrationResponse = await client.getIntegration({
|
||||
id: integrationId,
|
||||
})
|
||||
integration = getIntegrationResponse.integration
|
||||
}
|
||||
|
||||
integrationId = integration.id
|
||||
console.info(`Integration ID: ${integrationId}`)
|
||||
if (!integration.configurations['sandbox']) {
|
||||
console.info('Integration does not implement the sandbox feature, no scripts to upload')
|
||||
process.exit(0)
|
||||
}
|
||||
|
||||
const identifierExtractScriptPath = `${integrationPath}/sandboxIdentifierExtract.vrl`
|
||||
const messageExtractScriptPath = `${integrationPath}/sandboxShareableIdExtract.vrl`
|
||||
const identifierExtractScript = fs.readFileSync(identifierExtractScriptPath, 'utf8')
|
||||
const messageExtractScript = fs.readFileSync(messageExtractScriptPath, 'utf8')
|
||||
|
||||
return await await axios.put(
|
||||
`${apiUrl}/v1/corporate/integrations/${integrationId}/sandbox`,
|
||||
{
|
||||
identifierExtractScript,
|
||||
messageExtractScript,
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
Authorization: `Bearer ${token}`,
|
||||
'x-user-email': userEmail,
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const args = parseArgs()
|
||||
const profileArgs = getProfileArgs()
|
||||
const apiUrl = args.apiUrl || profileArgs.apiUrl || process.env.BP_API_URL || DEFAULT_API_URL
|
||||
const token = args.token || profileArgs.token || process.env.BP_TOKEN
|
||||
const workspaceId = args.workspaceId || profileArgs.workspaceId || process.env.BP_WORKSPACE_ID
|
||||
const userEmail = args.userEmail
|
||||
const integrationId = args.integrationId || process.env.BP_INTEGRATION_ID
|
||||
const integrationPath = args.integrationPath
|
||||
if (!userEmail || !token || !workspaceId) {
|
||||
const missingArgs: string[] = [
|
||||
!userEmail ? 'userEmail' : null,
|
||||
!token ? 'token' : null,
|
||||
!workspaceId ? 'workspaceId' : null,
|
||||
].filter((value) => value !== null)
|
||||
console.error(`Missing required arguments: ${missingArgs.join(', ')}`)
|
||||
console.error(
|
||||
'Usage: pnpm run ts-node -T upload-sandbox-scripts.ts --userEmail=<email> --token=<token> --workspaceId=<workspaceId> [--apiUrl=<apiUrl>] [--integrationId=<id>] [--integrationPath=<path>]\n' +
|
||||
'integrationId, apiUrl, token, and workspaceId can also be set in the environment variables BP_INTEGRATION_ID, BP_API_URL, BP_TOKEN, BP_WORKSPACE_ID'
|
||||
)
|
||||
process.exit(1)
|
||||
}
|
||||
|
||||
uploadScripts({
|
||||
apiUrl,
|
||||
token,
|
||||
workspaceId,
|
||||
userEmail,
|
||||
integrationId,
|
||||
integrationPath,
|
||||
})
|
||||
.then((res) => {
|
||||
console.info('Sandbox scripts updated successfully:', res.data)
|
||||
})
|
||||
.catch((error) => {
|
||||
console.error('Failed to update sandbox scripts')
|
||||
if (error.response) {
|
||||
console.error('Error Data:', error.response.data)
|
||||
console.error('Error Status:', error.response.status)
|
||||
console.error('Error Headers:', error.response.headers)
|
||||
} else if (error.request) {
|
||||
console.error('Error Request:', error.request)
|
||||
} else {
|
||||
console.error('Error Message:', error.message)
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user