@botpress/cli 0.4.2 → 0.4.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/client.js +14 -19
- package/dist/api/client.js.map +2 -2
- package/dist/api/paging.js +42 -0
- package/dist/api/paging.js.map +7 -0
- package/dist/code-generation/index.js +12 -4
- package/dist/code-generation/index.js.map +2 -2
- package/dist/code-generation/integration-implementation.js +1 -38
- package/dist/code-generation/integration-implementation.js.map +2 -2
- package/dist/code-generation/integration-instance.js +2 -1
- package/dist/code-generation/integration-instance.js.map +2 -2
- package/dist/code-generation/map-integration.js +72 -0
- package/dist/code-generation/map-integration.js.map +7 -0
- package/dist/code-generation/typings.js.map +1 -1
- package/dist/command-implementations/add-command.js +27 -5
- package/dist/command-implementations/add-command.js.map +2 -2
- package/dist/command-implementations/deploy-command.js +8 -2
- package/dist/command-implementations/deploy-command.js.map +2 -2
- package/dist/command-implementations/dev-command.js +3 -2
- package/dist/command-implementations/dev-command.js.map +2 -2
- package/dist/command-implementations/integration-commands.js +6 -0
- package/dist/command-implementations/integration-commands.js.map +2 -2
- package/dist/command-implementations/login-command.js +4 -2
- package/dist/command-implementations/login-command.js.map +2 -2
- package/dist/command-implementations/project-command.js +35 -6
- package/dist/command-implementations/project-command.js.map +3 -3
- package/dist/integration-ref.js +10 -0
- package/dist/integration-ref.js.map +2 -2
- package/dist/integration-ref.test.js +76 -0
- package/dist/integration-ref.test.js.map +7 -0
- package/package.json +3 -3
- package/templates/echo-bot/package.json +2 -2
- package/templates/empty-integration/package.json +2 -2
|
@@ -65,6 +65,11 @@ class DeployCommand extends import_project_command.ProjectCommand {
|
|
|
65
65
|
const iconFileContent = await this._readMediaFile("icon", iconRelativeFilePath);
|
|
66
66
|
const readmeFileContent = await this._readMediaFile("readme", readmeRelativeFilePath);
|
|
67
67
|
const integration = await api.findIntegration({ type: "name", name, version });
|
|
68
|
+
if (integration && !integration.workspaceId) {
|
|
69
|
+
throw new errors.BotpressCLIError(
|
|
70
|
+
`Public integration ${integrationDef.name} v${integrationDef.version} is already deployed in another workspace.`
|
|
71
|
+
);
|
|
72
|
+
}
|
|
68
73
|
let message;
|
|
69
74
|
if (integration) {
|
|
70
75
|
this.logger.warn("Integration already exists. If you decide to deploy, it will overwrite the existing one.");
|
|
@@ -78,7 +83,7 @@ class DeployCommand extends import_project_command.ProjectCommand {
|
|
|
78
83
|
return;
|
|
79
84
|
}
|
|
80
85
|
const createBody = {
|
|
81
|
-
...this.
|
|
86
|
+
...this.prepareIntegrationDefinition(integrationDef),
|
|
82
87
|
icon: iconFileContent,
|
|
83
88
|
readme: readmeFileContent,
|
|
84
89
|
code
|
|
@@ -140,7 +145,8 @@ class DeployCommand extends import_project_command.ProjectCommand {
|
|
|
140
145
|
{
|
|
141
146
|
id: bot.id,
|
|
142
147
|
code,
|
|
143
|
-
...this.
|
|
148
|
+
...this.prepareBot(botImpl),
|
|
149
|
+
...await this.prepareBotIntegrationInstances(botImpl, api)
|
|
144
150
|
},
|
|
145
151
|
bot
|
|
146
152
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/command-implementations/deploy-command.ts"],
|
|
4
|
-
"sourcesContent": ["import type * as bpclient from '@botpress/client'\nimport type * as bpsdk from '@botpress/sdk'\nimport chalk from 'chalk'\nimport * as fs from 'fs'\nimport { prepareUpdateBotBody } from '../api/bot-body'\nimport type { ApiClient } from '../api/client'\nimport { prepareUpdateIntegrationBody, CreateIntegrationBody } from '../api/integration-body'\nimport type commandDefinitions from '../command-definitions'\nimport * as consts from '../consts'\nimport * as errors from '../errors'\nimport * as utils from '../utils'\nimport { BuildCommand } from './build-command'\nimport { ProjectCommand } from './project-command'\n\nexport type DeployCommandDefinition = typeof commandDefinitions.deploy\nexport class DeployCommand extends ProjectCommand<DeployCommandDefinition> {\n public async run(): Promise<void> {\n const api = await this.ensureLoginAndCreateClient(this.argv)\n if (api.url !== consts.defaultBotpressApiUrl) {\n this.logger.log(`Using custom url ${api.url}`)\n }\n\n if (!this.argv.noBuild) {\n await this._runBuild() // This ensures the bundle is always synced with source code\n }\n\n const integrationDef = await this.readIntegrationDefinitionFromFS()\n if (integrationDef) {\n return this._deployIntegration(api, integrationDef)\n }\n return this._deployBot(api, this.argv.botId, this.argv.createNewBot)\n }\n\n private async _runBuild() {\n return new BuildCommand(this.api, this.prompt, this.logger, this.argv).run()\n }\n\n private async _deployIntegration(api: ApiClient, integrationDef: bpsdk.IntegrationDefinition) {\n const outfile = this.projectPaths.abs.outFile\n let code = await fs.promises.readFile(outfile, 'utf-8')\n\n const secrets = await this.promptSecrets(integrationDef, this.argv)\n // TODO: provide these secrets to the backend by API and remove this string replacement hack\n for (const [secretName, secretValue] of Object.entries(secrets)) {\n code = code.replace(new RegExp(`process\\\\.env\\\\.${secretName}`, 'g'), `\"${secretValue}\"`)\n }\n\n const { name, version, icon: iconRelativeFilePath, readme: readmeRelativeFilePath } = integrationDef\n\n const iconFileContent = await this._readMediaFile('icon', iconRelativeFilePath)\n const readmeFileContent = await this._readMediaFile('readme', readmeRelativeFilePath)\n\n const integration = await api.findIntegration({ type: 'name', name, version })\n\n let message: string\n if (integration) {\n this.logger.warn('Integration already exists. If you decide to deploy, it will overwrite the existing one.')\n message = `Are you sure you want to override integration ${integrationDef.name} v${integrationDef.version}?`\n } else {\n message = `Are you sure you want to deploy integration ${integrationDef.name} v${integrationDef.version}?`\n }\n\n const confirm = await this.prompt.confirm(message)\n if (!confirm) {\n this.logger.log('Aborted')\n return\n }\n\n const createBody: CreateIntegrationBody = {\n ...this.
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,mBAAkB;AAClB,SAAoB;AACpB,sBAAqC;AAErC,8BAAoE;AAEpE,aAAwB;AACxB,aAAwB;AACxB,YAAuB;AACvB,2BAA6B;AAC7B,6BAA+B;AAGxB,MAAM,sBAAsB,sCAAwC;AAAA,EACzE,MAAa,MAAqB;AAChC,UAAM,MAAM,MAAM,KAAK,2BAA2B,KAAK,IAAI;AAC3D,QAAI,IAAI,QAAQ,OAAO,uBAAuB;AAC5C,WAAK,OAAO,IAAI,oBAAoB,IAAI,KAAK;AAAA,IAC/C;AAEA,QAAI,CAAC,KAAK,KAAK,SAAS;AACtB,YAAM,KAAK,UAAU;AAAA,IACvB;AAEA,UAAM,iBAAiB,MAAM,KAAK,gCAAgC;AAClE,QAAI,gBAAgB;AAClB,aAAO,KAAK,mBAAmB,KAAK,cAAc;AAAA,IACpD;AACA,WAAO,KAAK,WAAW,KAAK,KAAK,KAAK,OAAO,KAAK,KAAK,YAAY;AAAA,EACrE;AAAA,EAEA,MAAc,YAAY;AACxB,WAAO,IAAI,kCAAa,KAAK,KAAK,KAAK,QAAQ,KAAK,QAAQ,KAAK,IAAI,EAAE,IAAI;AAAA,EAC7E;AAAA,EAEA,MAAc,mBAAmB,KAAgB,gBAA6C;AAC5F,UAAM,UAAU,KAAK,aAAa,IAAI;AACtC,QAAI,OAAO,MAAM,GAAG,SAAS,SAAS,SAAS,OAAO;AAEtD,UAAM,UAAU,MAAM,KAAK,cAAc,gBAAgB,KAAK,IAAI;AAElE,eAAW,CAAC,YAAY,WAAW,KAAK,OAAO,QAAQ,OAAO,GAAG;AAC/D,aAAO,KAAK,QAAQ,IAAI,OAAO,mBAAmB,cAAc,GAAG,GAAG,IAAI,cAAc;AAAA,IAC1F;AAEA,UAAM,EAAE,MAAM,SAAS,MAAM,sBAAsB,QAAQ,uBAAuB,IAAI;AAEtF,UAAM,kBAAkB,MAAM,KAAK,eAAe,QAAQ,oBAAoB;AAC9E,UAAM,oBAAoB,MAAM,KAAK,eAAe,UAAU,sBAAsB;AAEpF,UAAM,cAAc,MAAM,IAAI,gBAAgB,EAAE,MAAM,QAAQ,MAAM,QAAQ,CAAC;
|
|
4
|
+
"sourcesContent": ["import type * as bpclient from '@botpress/client'\nimport type * as bpsdk from '@botpress/sdk'\nimport chalk from 'chalk'\nimport * as fs from 'fs'\nimport { prepareUpdateBotBody } from '../api/bot-body'\nimport type { ApiClient } from '../api/client'\nimport { prepareUpdateIntegrationBody, CreateIntegrationBody } from '../api/integration-body'\nimport type commandDefinitions from '../command-definitions'\nimport * as consts from '../consts'\nimport * as errors from '../errors'\nimport * as utils from '../utils'\nimport { BuildCommand } from './build-command'\nimport { ProjectCommand } from './project-command'\n\nexport type DeployCommandDefinition = typeof commandDefinitions.deploy\nexport class DeployCommand extends ProjectCommand<DeployCommandDefinition> {\n public async run(): Promise<void> {\n const api = await this.ensureLoginAndCreateClient(this.argv)\n if (api.url !== consts.defaultBotpressApiUrl) {\n this.logger.log(`Using custom url ${api.url}`)\n }\n\n if (!this.argv.noBuild) {\n await this._runBuild() // This ensures the bundle is always synced with source code\n }\n\n const integrationDef = await this.readIntegrationDefinitionFromFS()\n if (integrationDef) {\n return this._deployIntegration(api, integrationDef)\n }\n return this._deployBot(api, this.argv.botId, this.argv.createNewBot)\n }\n\n private async _runBuild() {\n return new BuildCommand(this.api, this.prompt, this.logger, this.argv).run()\n }\n\n private async _deployIntegration(api: ApiClient, integrationDef: bpsdk.IntegrationDefinition) {\n const outfile = this.projectPaths.abs.outFile\n let code = await fs.promises.readFile(outfile, 'utf-8')\n\n const secrets = await this.promptSecrets(integrationDef, this.argv)\n // TODO: provide these secrets to the backend by API and remove this string replacement hack\n for (const [secretName, secretValue] of Object.entries(secrets)) {\n code = code.replace(new RegExp(`process\\\\.env\\\\.${secretName}`, 'g'), `\"${secretValue}\"`)\n }\n\n const { name, version, icon: iconRelativeFilePath, readme: readmeRelativeFilePath } = integrationDef\n\n const iconFileContent = await this._readMediaFile('icon', iconRelativeFilePath)\n const readmeFileContent = await this._readMediaFile('readme', readmeRelativeFilePath)\n\n const integration = await api.findIntegration({ type: 'name', name, version })\n if (integration && !integration.workspaceId) {\n throw new errors.BotpressCLIError(\n `Public integration ${integrationDef.name} v${integrationDef.version} is already deployed in another workspace.`\n )\n }\n\n let message: string\n if (integration) {\n this.logger.warn('Integration already exists. If you decide to deploy, it will overwrite the existing one.')\n message = `Are you sure you want to override integration ${integrationDef.name} v${integrationDef.version}?`\n } else {\n message = `Are you sure you want to deploy integration ${integrationDef.name} v${integrationDef.version}?`\n }\n\n const confirm = await this.prompt.confirm(message)\n if (!confirm) {\n this.logger.log('Aborted')\n return\n }\n\n const createBody: CreateIntegrationBody = {\n ...this.prepareIntegrationDefinition(integrationDef),\n icon: iconFileContent,\n readme: readmeFileContent,\n code,\n }\n\n const line = this.logger.line()\n line.started(`Deploying integration ${chalk.bold(integrationDef.name)} v${integrationDef.version}...`)\n if (integration) {\n const updateBody = prepareUpdateIntegrationBody(\n {\n id: integration.id,\n ...createBody,\n },\n integration\n )\n\n await api.client.updateIntegration(updateBody).catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, `Could not update integration \"${integrationDef.name}\"`)\n })\n } else {\n await api.client.createIntegration(createBody).catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, `Could not create integration \"${integrationDef.name}\"`)\n })\n }\n line.success('Integration deployed')\n }\n\n private _readMediaFile = async (\n filePurpose: 'icon' | 'readme',\n filePath: string | undefined\n ): Promise<string | undefined> => {\n if (!filePath) {\n return undefined\n }\n\n const absoluteFilePath = utils.path.absoluteFrom(this.projectPaths.abs.workDir, filePath)\n return fs.promises.readFile(absoluteFilePath, 'base64').catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, `Could not read ${filePurpose} file \"${absoluteFilePath}\"`)\n })\n }\n\n private async _deployBot(api: ApiClient, argvBotId: string | undefined, argvCreateNew: boolean | undefined) {\n const outfile = this.projectPaths.abs.outFile\n const code = await fs.promises.readFile(outfile, 'utf-8')\n const { default: botImpl } = utils.require.requireJsFile<{ default: bpsdk.Bot }>(outfile)\n\n let bot: bpclient.Bot\n if (argvBotId && argvCreateNew) {\n throw new errors.BotpressCLIError('Cannot specify both --botId and --createNew')\n } else if (argvCreateNew) {\n const confirm = await this.prompt.confirm('Are you sure you want to create a new bot ?')\n if (!confirm) {\n this.logger.log('Aborted')\n return\n }\n\n bot = await this._createNewBot(api)\n } else {\n bot = await this._getExistingBot(api, argvBotId)\n\n const confirm = await this.prompt.confirm(`Are you sure you want to deploy the bot \"${bot.name}\"?`)\n if (!confirm) {\n this.logger.log('Aborted')\n return\n }\n }\n\n const line = this.logger.line()\n line.started(`Deploying bot ${chalk.bold(bot.name)}...`)\n\n const updateBotBody = prepareUpdateBotBody(\n {\n id: bot.id,\n code,\n ...this.prepareBot(botImpl),\n ...(await this.prepareBotIntegrationInstances(botImpl, api)),\n },\n bot\n )\n\n const { bot: updatedBot } = await api.client.updateBot(updateBotBody).catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, `Could not update bot \"${bot.name}\"`)\n })\n line.success('Bot deployed')\n this.displayWebhookUrls(updatedBot)\n }\n\n private async _createNewBot(api: ApiClient): Promise<bpclient.Bot> {\n const line = this.logger.line()\n const { bot: createdBot } = await api.client.createBot({}).catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, 'Could not create bot')\n })\n line.success(`Bot created with ID \"${createdBot.id}\" and name \"${createdBot.name}\"`)\n await this.projectCache.set('botId', createdBot.id)\n return createdBot\n }\n\n private async _getExistingBot(api: ApiClient, botId: string | undefined): Promise<bpclient.Bot> {\n const promptedBotId = await this.projectCache.sync('botId', botId, async (defaultId) => {\n const userBots = await api\n .listAllPages(api.client.listBots, (r) => r.bots)\n .catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, 'Could not fetch existing bots')\n })\n\n if (!userBots.length) {\n throw new errors.NoBotsFoundError()\n }\n\n const initial = userBots.find((bot) => bot.id === defaultId)\n\n const prompted = await this.prompt.select('Which bot do you want to deploy?', {\n initial: initial && { title: initial.name, value: initial.id },\n choices: userBots.map((bot) => ({ title: bot.name, value: bot.id })),\n })\n\n if (!prompted) {\n throw new errors.ParamRequiredError('Bot Id')\n }\n\n return prompted\n })\n\n const { bot: fetchedBot } = await api.client.getBot({ id: promptedBotId }).catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, 'Could not get bot info')\n })\n\n return fetchedBot\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["chalk"]
|
|
7
7
|
}
|
|
@@ -199,7 +199,7 @@ class DevCommand extends import_project_command.ProjectCommand {
|
|
|
199
199
|
const line = this.logger.line();
|
|
200
200
|
line.started(`Deploying dev integration ${import_chalk.default.bold(integrationDef.name)}...`);
|
|
201
201
|
const integrationBody = {
|
|
202
|
-
...this.
|
|
202
|
+
...this.prepareIntegrationDefinition(integrationDef),
|
|
203
203
|
url: externalUrl
|
|
204
204
|
};
|
|
205
205
|
if (integration) {
|
|
@@ -258,7 +258,8 @@ class DevCommand extends import_project_command.ProjectCommand {
|
|
|
258
258
|
{
|
|
259
259
|
id: bot.id,
|
|
260
260
|
url: externalUrl,
|
|
261
|
-
...this.
|
|
261
|
+
...this.prepareBot(botImpl),
|
|
262
|
+
...await this.prepareBotIntegrationInstances(botImpl, api)
|
|
262
263
|
},
|
|
263
264
|
bot
|
|
264
265
|
);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/command-implementations/dev-command.ts"],
|
|
4
|
-
"sourcesContent": ["import type * as bpclient from '@botpress/client'\nimport type * as bpsdk from '@botpress/sdk'\nimport { TunnelRequest, TunnelResponse } from '@bpinternal/tunnel'\nimport axios, { AxiosRequestConfig, AxiosResponse } from 'axios'\nimport chalk from 'chalk'\nimport * as pathlib from 'path'\nimport * as uuid from 'uuid'\nimport { prepareUpdateBotBody } from '../api/bot-body'\nimport type { ApiClient } from '../api/client'\nimport { prepareUpdateIntegrationBody, CreateIntegrationBody } from '../api/integration-body'\nimport type commandDefinitions from '../command-definitions'\nimport * as errors from '../errors'\nimport * as utils from '../utils'\nimport { Worker } from '../worker'\nimport { BuildCommand } from './build-command'\nimport { ProjectCommand } from './project-command'\n\nconst DEFAULT_BOT_PORT = 8075\nconst DEFAULT_INTEGRATION_PORT = 8076\nconst TUNNEL_HELLO_INTERVAL = 5000\n\nexport type DevCommandDefinition = typeof commandDefinitions.dev\nexport class DevCommand extends ProjectCommand<DevCommandDefinition> {\n private _initialDef: bpsdk.IntegrationDefinition | undefined = undefined\n\n public async run(): Promise<void> {\n this.logger.warn('This command is experimental and subject to breaking changes without notice.')\n\n const api = await this.ensureLoginAndCreateClient(this.argv)\n\n this._initialDef = await this.readIntegrationDefinitionFromFS()\n\n let env: Record<string, string> = {\n ...process.env,\n BP_API_URL: api.url,\n BP_TOKEN: api.token,\n }\n\n let defaultPort = DEFAULT_BOT_PORT\n if (this._initialDef) {\n defaultPort = DEFAULT_INTEGRATION_PORT\n const secrets = await this.promptSecrets(this._initialDef, this.argv)\n env = { ...env, ...secrets }\n }\n\n const port = this.argv.port ?? defaultPort\n\n const urlParseResult = utils.url.parse(this.argv.tunnelUrl)\n if (urlParseResult.status === 'error') {\n throw new errors.BotpressCLIError(`Invalid tunnel URL: ${urlParseResult.error}`)\n }\n\n const tunnelId = uuid.v4()\n\n const { url: parsedTunnelUrl } = urlParseResult\n const isSecured = parsedTunnelUrl.protocol === 'https' || parsedTunnelUrl.protocol === 'wss'\n\n const wsTunnelUrl: string = utils.url.format({ ...parsedTunnelUrl, protocol: isSecured ? 'wss' : 'ws' })\n const httpTunnelUrl: string = utils.url.format({\n ...parsedTunnelUrl,\n protocol: isSecured ? 'https' : 'http',\n path: `/${tunnelId}`,\n })\n\n let worker: Worker | undefined = undefined\n\n const supervisor = new utils.tunnel.TunnelSupervisor(wsTunnelUrl, tunnelId, this.logger)\n supervisor.events.on('connected', ({ tunnel }) => {\n // prevents the tunnel from closing due to inactivity\n const timer = setInterval(() => tunnel.hello(), TUNNEL_HELLO_INTERVAL)\n tunnel.events.on('close', () => clearInterval(timer))\n\n tunnel.events.on('request', (req) => {\n if (!worker) {\n this.logger.debug('Worker not ready yet, ignoring request')\n tunnel.send({ requestId: req.id, status: 503, body: 'Worker not ready yet' })\n return\n }\n\n void this._forwardTunnelRequest(`http://localhost:${port}`, req)\n .then((res) => {\n tunnel.send(res)\n })\n .catch((thrown) => {\n const err = errors.BotpressCLIError.wrap(thrown, 'An error occurred while handling request')\n this.logger.error(err.message)\n tunnel.send({\n requestId: req.id,\n status: 500,\n body: err.message,\n })\n })\n })\n })\n await supervisor.start()\n\n await this._runBuild()\n await this._deploy(api, httpTunnelUrl)\n worker = await this._spawnWorker(env, port)\n\n try {\n const watcher = await utils.filewatcher.FileWatcher.watch(\n this.argv.workDir,\n async (events) => {\n if (!worker) {\n this.logger.debug('Worker not ready yet, ignoring file change event')\n return\n }\n\n const typescriptEvents = events.filter((e) => pathlib.extname(e.path) === '.ts')\n if (typescriptEvents.length === 0) {\n return\n }\n\n this.logger.log('Changes detected, rebuilding')\n await this._restart(api, worker, httpTunnelUrl)\n },\n {\n ignore: [this.projectPaths.abs.outDir],\n }\n )\n\n await Promise.race([worker.wait(), watcher.wait(), supervisor.wait()])\n\n if (worker.running) {\n await worker.kill()\n }\n await watcher.close()\n supervisor.close()\n } catch (thrown) {\n throw errors.BotpressCLIError.wrap(thrown, 'An error occurred while running the dev server')\n } finally {\n if (worker.running) {\n await worker.kill()\n }\n }\n }\n\n private _restart = async (api: ApiClient, worker: Worker, tunnelUrl: string) => {\n try {\n await this._runBuild()\n } catch (thrown) {\n const error = errors.BotpressCLIError.wrap(thrown, 'Build failed')\n this.logger.error(error.message)\n return\n }\n\n await this._deploy(api, tunnelUrl)\n await worker.reload()\n }\n\n private _deploy = async (api: ApiClient, tunnelUrl: string) => {\n const integrationDef = await this.readIntegrationDefinitionFromFS()\n if (integrationDef) {\n this._checkSecrets(integrationDef)\n await this._deployDevIntegration(api, tunnelUrl, integrationDef)\n } else {\n await this._deployDevBot(api, tunnelUrl)\n }\n }\n\n private _checkSecrets(integrationDef: bpsdk.IntegrationDefinition) {\n const initialSecrets = this._initialDef?.secrets ?? {}\n const currentSecrets = integrationDef.secrets ?? {}\n const newSecrets = Object.keys(currentSecrets).filter((s) => !initialSecrets[s])\n if (newSecrets.length > 0) {\n throw new errors.BotpressCLIError('Secrets were added while the server was running. A restart is required.')\n }\n }\n\n private _spawnWorker = async (env: Record<string, string>, port: number) => {\n const outfile = this.projectPaths.abs.outFile\n const importPath = utils.path.toUnix(outfile)\n const requireFrom = utils.path.rmExtension(importPath)\n const code = `require('${requireFrom}').default.start(${port})`\n const worker = await Worker.spawn(\n {\n type: 'code',\n code,\n env,\n },\n this.logger\n ).catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, 'Could not start dev worker')\n })\n\n return worker\n }\n\n private _runBuild() {\n return new BuildCommand(this.api, this.prompt, this.logger, this.argv).run()\n }\n\n private async _deployDevIntegration(\n api: ApiClient,\n externalUrl: string,\n integrationDef: bpsdk.IntegrationDefinition\n ): Promise<void> {\n const devId = await this.projectCache.get('devId')\n\n let integration: bpclient.Integration | undefined = undefined\n\n if (devId) {\n const resp = await api.client.getIntegration({ id: devId }).catch(async (thrown) => {\n const err = errors.BotpressCLIError.wrap(thrown, `Could not find existing dev integration with id \"${devId}\"`)\n this.logger.warn(err.message)\n return { integration: undefined }\n })\n\n if (resp.integration?.dev) {\n integration = resp.integration\n } else {\n await this.projectCache.rm('devId')\n }\n }\n\n const line = this.logger.line()\n line.started(`Deploying dev integration ${chalk.bold(integrationDef.name)}...`)\n\n const integrationBody: CreateIntegrationBody = {\n ...this.parseIntegrationDefinition(integrationDef),\n url: externalUrl,\n }\n\n if (integration) {\n const updateIntegrationBody = prepareUpdateIntegrationBody(\n { ...integrationBody, id: integration.id },\n integration\n )\n\n const resp = await api.client.updateIntegration(updateIntegrationBody).catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, `Could not update dev integration \"${integrationDef.name}\"`)\n })\n integration = resp.integration\n } else {\n const resp = await api.client.createIntegration({ ...integrationBody, dev: true }).catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, `Could not deploy dev integration \"${integrationDef.name}\"`)\n })\n integration = resp.integration\n }\n\n line.success(`Dev Integration deployed with id \"${integration.id}\"`)\n line.commit()\n\n await this.projectCache.set('devId', integration.id)\n }\n\n private async _deployDevBot(api: ApiClient, externalUrl: string): Promise<void> {\n const devId = await this.projectCache.get('devId')\n\n let bot: bpclient.Bot | undefined = undefined\n\n if (devId) {\n const resp = await api.client.getBot({ id: devId }).catch(async (thrown) => {\n const err = errors.BotpressCLIError.wrap(thrown, `Could not find existing dev bot with id \"${devId}\"`)\n this.logger.warn(err.message)\n return { bot: undefined }\n })\n\n if (resp.bot?.dev) {\n bot = resp.bot\n } else {\n await this.projectCache.rm('devId')\n }\n }\n\n if (!bot) {\n const createLine = this.logger.line()\n createLine.started('Creating dev bot...')\n const resp = await api.client\n .createBot({\n dev: true,\n url: externalUrl,\n })\n .catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, 'Could not deploy dev bot')\n })\n\n bot = resp.bot\n createLine.success(`Dev Bot created with id \"${bot.id}\"`)\n createLine.commit()\n await this.projectCache.set('devId', bot.id)\n }\n\n const outfile = this.projectPaths.abs.outFile\n const { default: botImpl } = utils.require.requireJsFile<{ default: bpsdk.Bot }>(outfile)\n\n const updateLine = this.logger.line()\n updateLine.started('Deploying dev bot...')\n\n const updateBotBody = prepareUpdateBotBody(\n {\n id: bot.id,\n url: externalUrl,\n ...this.parseBot(botImpl),\n },\n bot\n )\n\n const { bot: updatedBot } = await api.client.updateBot(updateBotBody).catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, 'Could not deploy dev bot')\n })\n updateLine.success(`Dev Bot deployed with id \"${updatedBot.id}\"`)\n updateLine.commit()\n\n this.displayWebhookUrls(updatedBot)\n }\n\n private _forwardTunnelRequest = async (baseUrl: string, request: TunnelRequest): Promise<TunnelResponse> => {\n const axiosConfig = {\n method: request.method,\n url: this._formatLocalUrl(baseUrl, request),\n headers: request.headers,\n data: request.body,\n responseType: 'text',\n validateStatus: () => true,\n } satisfies AxiosRequestConfig\n\n this.logger.debug(`Forwarding request to ${axiosConfig.url}`)\n const response = await axios(axiosConfig)\n this.logger.debug('Sending back response up the tunnel')\n\n return {\n requestId: request.id,\n status: response.status,\n headers: this._getHeaders(response.headers),\n body: response.data,\n }\n }\n\n private _formatLocalUrl = (baseUrl: string, req: TunnelRequest): string => {\n if (req.query) {\n return `${baseUrl}${req.path}?${req.query}`\n }\n return `${baseUrl}${req.path}`\n }\n\n private _getHeaders = (res: AxiosResponse['headers']): TunnelResponse['headers'] => {\n const headers: TunnelResponse['headers'] = {}\n for (const key in res) {\n if (typeof res[key] === 'string' || typeof res[key] === 'number') {\n headers[key] = res[key]\n }\n }\n return headers\n }\n}\n"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import type * as bpclient from '@botpress/client'\nimport type * as bpsdk from '@botpress/sdk'\nimport { TunnelRequest, TunnelResponse } from '@bpinternal/tunnel'\nimport axios, { AxiosRequestConfig, AxiosResponse } from 'axios'\nimport chalk from 'chalk'\nimport * as pathlib from 'path'\nimport * as uuid from 'uuid'\nimport { prepareUpdateBotBody } from '../api/bot-body'\nimport type { ApiClient } from '../api/client'\nimport { prepareUpdateIntegrationBody, CreateIntegrationBody } from '../api/integration-body'\nimport type commandDefinitions from '../command-definitions'\nimport * as errors from '../errors'\nimport * as utils from '../utils'\nimport { Worker } from '../worker'\nimport { BuildCommand } from './build-command'\nimport { ProjectCommand } from './project-command'\n\nconst DEFAULT_BOT_PORT = 8075\nconst DEFAULT_INTEGRATION_PORT = 8076\nconst TUNNEL_HELLO_INTERVAL = 5000\n\nexport type DevCommandDefinition = typeof commandDefinitions.dev\nexport class DevCommand extends ProjectCommand<DevCommandDefinition> {\n private _initialDef: bpsdk.IntegrationDefinition | undefined = undefined\n\n public async run(): Promise<void> {\n this.logger.warn('This command is experimental and subject to breaking changes without notice.')\n\n const api = await this.ensureLoginAndCreateClient(this.argv)\n\n this._initialDef = await this.readIntegrationDefinitionFromFS()\n\n let env: Record<string, string> = {\n ...process.env,\n BP_API_URL: api.url,\n BP_TOKEN: api.token,\n }\n\n let defaultPort = DEFAULT_BOT_PORT\n if (this._initialDef) {\n defaultPort = DEFAULT_INTEGRATION_PORT\n const secrets = await this.promptSecrets(this._initialDef, this.argv)\n env = { ...env, ...secrets }\n }\n\n const port = this.argv.port ?? defaultPort\n\n const urlParseResult = utils.url.parse(this.argv.tunnelUrl)\n if (urlParseResult.status === 'error') {\n throw new errors.BotpressCLIError(`Invalid tunnel URL: ${urlParseResult.error}`)\n }\n\n const tunnelId = uuid.v4()\n\n const { url: parsedTunnelUrl } = urlParseResult\n const isSecured = parsedTunnelUrl.protocol === 'https' || parsedTunnelUrl.protocol === 'wss'\n\n const wsTunnelUrl: string = utils.url.format({ ...parsedTunnelUrl, protocol: isSecured ? 'wss' : 'ws' })\n const httpTunnelUrl: string = utils.url.format({\n ...parsedTunnelUrl,\n protocol: isSecured ? 'https' : 'http',\n path: `/${tunnelId}`,\n })\n\n let worker: Worker | undefined = undefined\n\n const supervisor = new utils.tunnel.TunnelSupervisor(wsTunnelUrl, tunnelId, this.logger)\n supervisor.events.on('connected', ({ tunnel }) => {\n // prevents the tunnel from closing due to inactivity\n const timer = setInterval(() => tunnel.hello(), TUNNEL_HELLO_INTERVAL)\n tunnel.events.on('close', () => clearInterval(timer))\n\n tunnel.events.on('request', (req) => {\n if (!worker) {\n this.logger.debug('Worker not ready yet, ignoring request')\n tunnel.send({ requestId: req.id, status: 503, body: 'Worker not ready yet' })\n return\n }\n\n void this._forwardTunnelRequest(`http://localhost:${port}`, req)\n .then((res) => {\n tunnel.send(res)\n })\n .catch((thrown) => {\n const err = errors.BotpressCLIError.wrap(thrown, 'An error occurred while handling request')\n this.logger.error(err.message)\n tunnel.send({\n requestId: req.id,\n status: 500,\n body: err.message,\n })\n })\n })\n })\n await supervisor.start()\n\n await this._runBuild()\n await this._deploy(api, httpTunnelUrl)\n worker = await this._spawnWorker(env, port)\n\n try {\n const watcher = await utils.filewatcher.FileWatcher.watch(\n this.argv.workDir,\n async (events) => {\n if (!worker) {\n this.logger.debug('Worker not ready yet, ignoring file change event')\n return\n }\n\n const typescriptEvents = events.filter((e) => pathlib.extname(e.path) === '.ts')\n if (typescriptEvents.length === 0) {\n return\n }\n\n this.logger.log('Changes detected, rebuilding')\n await this._restart(api, worker, httpTunnelUrl)\n },\n {\n ignore: [this.projectPaths.abs.outDir],\n }\n )\n\n await Promise.race([worker.wait(), watcher.wait(), supervisor.wait()])\n\n if (worker.running) {\n await worker.kill()\n }\n await watcher.close()\n supervisor.close()\n } catch (thrown) {\n throw errors.BotpressCLIError.wrap(thrown, 'An error occurred while running the dev server')\n } finally {\n if (worker.running) {\n await worker.kill()\n }\n }\n }\n\n private _restart = async (api: ApiClient, worker: Worker, tunnelUrl: string) => {\n try {\n await this._runBuild()\n } catch (thrown) {\n const error = errors.BotpressCLIError.wrap(thrown, 'Build failed')\n this.logger.error(error.message)\n return\n }\n\n await this._deploy(api, tunnelUrl)\n await worker.reload()\n }\n\n private _deploy = async (api: ApiClient, tunnelUrl: string) => {\n const integrationDef = await this.readIntegrationDefinitionFromFS()\n if (integrationDef) {\n this._checkSecrets(integrationDef)\n await this._deployDevIntegration(api, tunnelUrl, integrationDef)\n } else {\n await this._deployDevBot(api, tunnelUrl)\n }\n }\n\n private _checkSecrets(integrationDef: bpsdk.IntegrationDefinition) {\n const initialSecrets = this._initialDef?.secrets ?? {}\n const currentSecrets = integrationDef.secrets ?? {}\n const newSecrets = Object.keys(currentSecrets).filter((s) => !initialSecrets[s])\n if (newSecrets.length > 0) {\n throw new errors.BotpressCLIError('Secrets were added while the server was running. A restart is required.')\n }\n }\n\n private _spawnWorker = async (env: Record<string, string>, port: number) => {\n const outfile = this.projectPaths.abs.outFile\n const importPath = utils.path.toUnix(outfile)\n const requireFrom = utils.path.rmExtension(importPath)\n const code = `require('${requireFrom}').default.start(${port})`\n const worker = await Worker.spawn(\n {\n type: 'code',\n code,\n env,\n },\n this.logger\n ).catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, 'Could not start dev worker')\n })\n\n return worker\n }\n\n private _runBuild() {\n return new BuildCommand(this.api, this.prompt, this.logger, this.argv).run()\n }\n\n private async _deployDevIntegration(\n api: ApiClient,\n externalUrl: string,\n integrationDef: bpsdk.IntegrationDefinition\n ): Promise<void> {\n const devId = await this.projectCache.get('devId')\n\n let integration: bpclient.Integration | undefined = undefined\n\n if (devId) {\n const resp = await api.client.getIntegration({ id: devId }).catch(async (thrown) => {\n const err = errors.BotpressCLIError.wrap(thrown, `Could not find existing dev integration with id \"${devId}\"`)\n this.logger.warn(err.message)\n return { integration: undefined }\n })\n\n if (resp.integration?.dev) {\n integration = resp.integration\n } else {\n await this.projectCache.rm('devId')\n }\n }\n\n const line = this.logger.line()\n line.started(`Deploying dev integration ${chalk.bold(integrationDef.name)}...`)\n\n const integrationBody: CreateIntegrationBody = {\n ...this.prepareIntegrationDefinition(integrationDef),\n url: externalUrl,\n }\n\n if (integration) {\n const updateIntegrationBody = prepareUpdateIntegrationBody(\n { ...integrationBody, id: integration.id },\n integration\n )\n\n const resp = await api.client.updateIntegration(updateIntegrationBody).catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, `Could not update dev integration \"${integrationDef.name}\"`)\n })\n integration = resp.integration\n } else {\n const resp = await api.client.createIntegration({ ...integrationBody, dev: true }).catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, `Could not deploy dev integration \"${integrationDef.name}\"`)\n })\n integration = resp.integration\n }\n\n line.success(`Dev Integration deployed with id \"${integration.id}\"`)\n line.commit()\n\n await this.projectCache.set('devId', integration.id)\n }\n\n private async _deployDevBot(api: ApiClient, externalUrl: string): Promise<void> {\n const devId = await this.projectCache.get('devId')\n\n let bot: bpclient.Bot | undefined = undefined\n\n if (devId) {\n const resp = await api.client.getBot({ id: devId }).catch(async (thrown) => {\n const err = errors.BotpressCLIError.wrap(thrown, `Could not find existing dev bot with id \"${devId}\"`)\n this.logger.warn(err.message)\n return { bot: undefined }\n })\n\n if (resp.bot?.dev) {\n bot = resp.bot\n } else {\n await this.projectCache.rm('devId')\n }\n }\n\n if (!bot) {\n const createLine = this.logger.line()\n createLine.started('Creating dev bot...')\n const resp = await api.client\n .createBot({\n dev: true,\n url: externalUrl,\n })\n .catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, 'Could not deploy dev bot')\n })\n\n bot = resp.bot\n createLine.success(`Dev Bot created with id \"${bot.id}\"`)\n createLine.commit()\n await this.projectCache.set('devId', bot.id)\n }\n\n const outfile = this.projectPaths.abs.outFile\n const { default: botImpl } = utils.require.requireJsFile<{ default: bpsdk.Bot }>(outfile)\n\n const updateLine = this.logger.line()\n updateLine.started('Deploying dev bot...')\n\n const updateBotBody = prepareUpdateBotBody(\n {\n id: bot.id,\n url: externalUrl,\n ...this.prepareBot(botImpl),\n ...(await this.prepareBotIntegrationInstances(botImpl, api)),\n },\n bot\n )\n\n const { bot: updatedBot } = await api.client.updateBot(updateBotBody).catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, 'Could not deploy dev bot')\n })\n updateLine.success(`Dev Bot deployed with id \"${updatedBot.id}\"`)\n updateLine.commit()\n\n this.displayWebhookUrls(updatedBot)\n }\n\n private _forwardTunnelRequest = async (baseUrl: string, request: TunnelRequest): Promise<TunnelResponse> => {\n const axiosConfig = {\n method: request.method,\n url: this._formatLocalUrl(baseUrl, request),\n headers: request.headers,\n data: request.body,\n responseType: 'text',\n validateStatus: () => true,\n } satisfies AxiosRequestConfig\n\n this.logger.debug(`Forwarding request to ${axiosConfig.url}`)\n const response = await axios(axiosConfig)\n this.logger.debug('Sending back response up the tunnel')\n\n return {\n requestId: request.id,\n status: response.status,\n headers: this._getHeaders(response.headers),\n body: response.data,\n }\n }\n\n private _formatLocalUrl = (baseUrl: string, req: TunnelRequest): string => {\n if (req.query) {\n return `${baseUrl}${req.path}?${req.query}`\n }\n return `${baseUrl}${req.path}`\n }\n\n private _getHeaders = (res: AxiosResponse['headers']): TunnelResponse['headers'] => {\n const headers: TunnelResponse['headers'] = {}\n for (const key in res) {\n if (typeof res[key] === 'string' || typeof res[key] === 'number') {\n headers[key] = res[key]\n }\n }\n return headers\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["chalk", "axios"]
|
|
7
7
|
}
|
|
@@ -41,6 +41,9 @@ class GetIntegrationCommand extends import_global_command.GlobalCommand {
|
|
|
41
41
|
if (!parsedRef) {
|
|
42
42
|
throw new errors.InvalidIntegrationReferenceError(this.argv.integrationRef);
|
|
43
43
|
}
|
|
44
|
+
if (parsedRef.type === "path") {
|
|
45
|
+
throw new errors.BotpressCLIError("Cannot get local integration");
|
|
46
|
+
}
|
|
44
47
|
try {
|
|
45
48
|
const integration = await api.findIntegration(parsedRef);
|
|
46
49
|
if (integration) {
|
|
@@ -77,6 +80,9 @@ class DeleteIntegrationCommand extends import_global_command.GlobalCommand {
|
|
|
77
80
|
if (!parsedRef) {
|
|
78
81
|
throw new errors.InvalidIntegrationReferenceError(this.argv.integrationRef);
|
|
79
82
|
}
|
|
83
|
+
if (parsedRef.type === "path") {
|
|
84
|
+
throw new errors.BotpressCLIError("Cannot delete local integration");
|
|
85
|
+
}
|
|
80
86
|
let integration;
|
|
81
87
|
try {
|
|
82
88
|
integration = await api.findPrivateIntegration(parsedRef);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/command-implementations/integration-commands.ts"],
|
|
4
|
-
"sourcesContent": ["import type * as bpclient from '@botpress/client'\nimport chalk from 'chalk'\nimport _ from 'lodash'\nimport type commandDefinitions from '../command-definitions'\nimport * as errors from '../errors'\nimport { parseIntegrationRef } from '../integration-ref'\nimport { GlobalCommand } from './global-command'\n\nexport type GetIntegrationCommandDefinition = typeof commandDefinitions.integrations.subcommands.get\nexport class GetIntegrationCommand extends GlobalCommand<GetIntegrationCommandDefinition> {\n public async run(): Promise<void> {\n const api = await this.ensureLoginAndCreateClient(this.argv)\n const parsedRef = parseIntegrationRef(this.argv.integrationRef)\n if (!parsedRef) {\n throw new errors.InvalidIntegrationReferenceError(this.argv.integrationRef)\n }\n\n try {\n const integration = await api.findIntegration(parsedRef)\n if (integration) {\n this.logger.success(`Integration ${chalk.bold(this.argv.integrationRef)}:`)\n this.logger.json(integration)\n return\n }\n } catch (thrown) {\n throw errors.BotpressCLIError.wrap(thrown, `Could not get integration ${this.argv.integrationRef}`)\n }\n\n throw new errors.BotpressCLIError(`Integration ${this.argv.integrationRef} not found`)\n }\n}\n\nexport type ListIntegrationsCommandDefinition = typeof commandDefinitions.integrations.subcommands.list\nexport class ListIntegrationsCommand extends GlobalCommand<ListIntegrationsCommandDefinition> {\n public async run(): Promise<void> {\n const api = await this.ensureLoginAndCreateClient(this.argv)\n\n const privateLister = (req: { nextToken?: string }) =>\n api.client.listIntegrations({ nextToken: req.nextToken, name: this.argv.name, version: this.argv.version })\n\n const publicLister = (req: { nextToken?: string }) =>\n api.client.listPublicIntegrations({ nextToken: req.nextToken, name: this.argv.name, version: this.argv.version })\n\n try {\n const privateIntegrations = await api.listAllPages(privateLister, (r) => r.integrations)\n const publicIntegrations = await api.listAllPages(publicLister, (r) => r.integrations)\n const integrations = _.uniqBy([...privateIntegrations, ...publicIntegrations], (i) => i.id)\n\n this.logger.success('Integrations:')\n this.logger.json(integrations)\n } catch (thrown) {\n throw errors.BotpressCLIError.wrap(thrown, 'Could not list integrations')\n }\n }\n}\n\nexport type DeleteIntegrationCommandDefinition = typeof commandDefinitions.integrations.subcommands.delete\nexport class DeleteIntegrationCommand extends GlobalCommand<DeleteIntegrationCommandDefinition> {\n public async run(): Promise<void> {\n const api = await this.ensureLoginAndCreateClient(this.argv)\n const parsedRef = parseIntegrationRef(this.argv.integrationRef)\n if (!parsedRef) {\n throw new errors.InvalidIntegrationReferenceError(this.argv.integrationRef)\n }\n\n let integration: bpclient.Integration | undefined\n try {\n integration = await api.findPrivateIntegration(parsedRef)\n } catch (thrown) {\n throw errors.BotpressCLIError.wrap(thrown, `Could not get integration ${this.argv.integrationRef}`)\n }\n\n if (!integration) {\n const publicIntegration = await api.findPublicIntegration(parsedRef)\n if (publicIntegration) {\n throw new errors.BotpressCLIError(`Integration ${this.argv.integrationRef} does not belong to your workspace`)\n }\n\n throw new errors.BotpressCLIError(`Integration ${this.argv.integrationRef} not found`)\n }\n\n try {\n await api.client.deleteIntegration({ id: integration.id })\n } catch (thrown) {\n throw errors.BotpressCLIError.wrap(thrown, `Could not delete integration ${this.argv.integrationRef}`)\n }\n\n this.logger.success(`Integration ${chalk.bold(this.argv.integrationRef)} deleted`)\n return\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import type * as bpclient from '@botpress/client'\nimport chalk from 'chalk'\nimport _ from 'lodash'\nimport type commandDefinitions from '../command-definitions'\nimport * as errors from '../errors'\nimport { parseIntegrationRef } from '../integration-ref'\nimport { GlobalCommand } from './global-command'\n\nexport type GetIntegrationCommandDefinition = typeof commandDefinitions.integrations.subcommands.get\nexport class GetIntegrationCommand extends GlobalCommand<GetIntegrationCommandDefinition> {\n public async run(): Promise<void> {\n const api = await this.ensureLoginAndCreateClient(this.argv)\n const parsedRef = parseIntegrationRef(this.argv.integrationRef)\n if (!parsedRef) {\n throw new errors.InvalidIntegrationReferenceError(this.argv.integrationRef)\n }\n if (parsedRef.type === 'path') {\n throw new errors.BotpressCLIError('Cannot get local integration')\n }\n\n try {\n const integration = await api.findIntegration(parsedRef)\n if (integration) {\n this.logger.success(`Integration ${chalk.bold(this.argv.integrationRef)}:`)\n this.logger.json(integration)\n return\n }\n } catch (thrown) {\n throw errors.BotpressCLIError.wrap(thrown, `Could not get integration ${this.argv.integrationRef}`)\n }\n\n throw new errors.BotpressCLIError(`Integration ${this.argv.integrationRef} not found`)\n }\n}\n\nexport type ListIntegrationsCommandDefinition = typeof commandDefinitions.integrations.subcommands.list\nexport class ListIntegrationsCommand extends GlobalCommand<ListIntegrationsCommandDefinition> {\n public async run(): Promise<void> {\n const api = await this.ensureLoginAndCreateClient(this.argv)\n\n const privateLister = (req: { nextToken?: string }) =>\n api.client.listIntegrations({ nextToken: req.nextToken, name: this.argv.name, version: this.argv.version })\n\n const publicLister = (req: { nextToken?: string }) =>\n api.client.listPublicIntegrations({ nextToken: req.nextToken, name: this.argv.name, version: this.argv.version })\n\n try {\n const privateIntegrations = await api.listAllPages(privateLister, (r) => r.integrations)\n const publicIntegrations = await api.listAllPages(publicLister, (r) => r.integrations)\n const integrations = _.uniqBy([...privateIntegrations, ...publicIntegrations], (i) => i.id)\n\n this.logger.success('Integrations:')\n this.logger.json(integrations)\n } catch (thrown) {\n throw errors.BotpressCLIError.wrap(thrown, 'Could not list integrations')\n }\n }\n}\n\nexport type DeleteIntegrationCommandDefinition = typeof commandDefinitions.integrations.subcommands.delete\nexport class DeleteIntegrationCommand extends GlobalCommand<DeleteIntegrationCommandDefinition> {\n public async run(): Promise<void> {\n const api = await this.ensureLoginAndCreateClient(this.argv)\n const parsedRef = parseIntegrationRef(this.argv.integrationRef)\n if (!parsedRef) {\n throw new errors.InvalidIntegrationReferenceError(this.argv.integrationRef)\n }\n if (parsedRef.type === 'path') {\n throw new errors.BotpressCLIError('Cannot delete local integration')\n }\n\n let integration: bpclient.Integration | undefined\n try {\n integration = await api.findPrivateIntegration(parsedRef)\n } catch (thrown) {\n throw errors.BotpressCLIError.wrap(thrown, `Could not get integration ${this.argv.integrationRef}`)\n }\n\n if (!integration) {\n const publicIntegration = await api.findPublicIntegration(parsedRef)\n if (publicIntegration) {\n throw new errors.BotpressCLIError(`Integration ${this.argv.integrationRef} does not belong to your workspace`)\n }\n\n throw new errors.BotpressCLIError(`Integration ${this.argv.integrationRef} not found`)\n }\n\n try {\n await api.client.deleteIntegration({ id: integration.id })\n } catch (thrown) {\n throw errors.BotpressCLIError.wrap(thrown, `Could not delete integration ${this.argv.integrationRef}`)\n }\n\n this.logger.success(`Integration ${chalk.bold(this.argv.integrationRef)} deleted`)\n return\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["chalk", "_"]
|
|
7
7
|
}
|
|
@@ -27,6 +27,8 @@ __export(login_command_exports, {
|
|
|
27
27
|
LoginCommand: () => LoginCommand
|
|
28
28
|
});
|
|
29
29
|
module.exports = __toCommonJS(login_command_exports);
|
|
30
|
+
var bpclient = __toESM(require("@botpress/client"));
|
|
31
|
+
var paging = __toESM(require("../api/paging"));
|
|
30
32
|
var errors = __toESM(require("../errors"));
|
|
31
33
|
var import_global_command = require("./global-command");
|
|
32
34
|
class LoginCommand extends import_global_command.GlobalCommand {
|
|
@@ -41,8 +43,8 @@ class LoginCommand extends import_global_command.GlobalCommand {
|
|
|
41
43
|
return prompted;
|
|
42
44
|
});
|
|
43
45
|
const promptedWorkspaceId = await this.globalCache.sync("workspaceId", this.argv.workspaceId, async (defaultId) => {
|
|
44
|
-
const
|
|
45
|
-
const userWorkspaces = await
|
|
46
|
+
const tmpClient = new bpclient.Client({ apiUrl: this.argv.apiUrl, token: promptedToken });
|
|
47
|
+
const userWorkspaces = await paging.listAllPages(tmpClient.listWorkspaces, (r) => r.workspaces).catch((thrown) => {
|
|
46
48
|
throw errors.BotpressCLIError.wrap(thrown, "Could not list workspaces");
|
|
47
49
|
});
|
|
48
50
|
if (userWorkspaces.length === 0) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/command-implementations/login-command.ts"],
|
|
4
|
-
"sourcesContent": ["import type commandDefinitions from '../command-definitions'\nimport * as errors from '../errors'\nimport { GlobalCommand } from './global-command'\n\nexport type LoginCommandDefinition = typeof commandDefinitions.login\nexport class LoginCommand extends GlobalCommand<LoginCommandDefinition> {\n public async run(): Promise<void> {\n const promptedToken = await this.globalCache.sync('token', this.argv.token, async (previousToken) => {\n const prompted = await this.prompt.password('Enter your Personal Access Token', {\n initial: previousToken,\n })\n\n if (!prompted) {\n throw new errors.ParamRequiredError('Personal Access Token')\n }\n\n return prompted\n })\n\n const promptedWorkspaceId = await this.globalCache.sync('workspaceId', this.argv.workspaceId, async (defaultId) => {\n const
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;
|
|
4
|
+
"sourcesContent": ["import * as bpclient from '@botpress/client'\nimport * as paging from '../api/paging'\nimport type commandDefinitions from '../command-definitions'\nimport * as errors from '../errors'\nimport { GlobalCommand } from './global-command'\n\nexport type LoginCommandDefinition = typeof commandDefinitions.login\nexport class LoginCommand extends GlobalCommand<LoginCommandDefinition> {\n public async run(): Promise<void> {\n const promptedToken = await this.globalCache.sync('token', this.argv.token, async (previousToken) => {\n const prompted = await this.prompt.password('Enter your Personal Access Token', {\n initial: previousToken,\n })\n\n if (!prompted) {\n throw new errors.ParamRequiredError('Personal Access Token')\n }\n\n return prompted\n })\n\n const promptedWorkspaceId = await this.globalCache.sync('workspaceId', this.argv.workspaceId, async (defaultId) => {\n const tmpClient = new bpclient.Client({ apiUrl: this.argv.apiUrl, token: promptedToken }) // no workspaceId yet\n const userWorkspaces = await paging\n .listAllPages(tmpClient.listWorkspaces, (r) => r.workspaces)\n .catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, 'Could not list workspaces')\n })\n\n if (userWorkspaces.length === 0) {\n throw new errors.NoWorkspacesFoundError()\n }\n\n const initial = userWorkspaces.find((ws) => ws.id === defaultId)\n\n const prompted = await this.prompt.select('Which workspace do you want to login to?', {\n initial: initial && { title: initial.name, value: initial.id },\n choices: userWorkspaces.map((ws) => ({ title: ws.name, value: ws.id })),\n })\n\n if (!prompted) {\n throw new errors.ParamRequiredError('Workspace Id')\n }\n\n return prompted\n })\n\n await this.globalCache.set('apiUrl', this.argv.apiUrl)\n\n const api = this.api.newClient(\n { apiUrl: this.argv.apiUrl, token: promptedToken, workspaceId: promptedWorkspaceId },\n this.logger\n )\n\n await api.testLogin().catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, 'Login failed. Please check your credentials')\n })\n\n this.logger.success('Logged In')\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAA0B;AAC1B,aAAwB;AAExB,aAAwB;AACxB,4BAA8B;AAGvB,MAAM,qBAAqB,oCAAsC;AAAA,EACtE,MAAa,MAAqB;AAChC,UAAM,gBAAgB,MAAM,KAAK,YAAY,KAAK,SAAS,KAAK,KAAK,OAAO,OAAO,kBAAkB;AACnG,YAAM,WAAW,MAAM,KAAK,OAAO,SAAS,oCAAoC;AAAA,QAC9E,SAAS;AAAA,MACX,CAAC;AAED,UAAI,CAAC,UAAU;AACb,cAAM,IAAI,OAAO,mBAAmB,uBAAuB;AAAA,MAC7D;AAEA,aAAO;AAAA,IACT,CAAC;AAED,UAAM,sBAAsB,MAAM,KAAK,YAAY,KAAK,eAAe,KAAK,KAAK,aAAa,OAAO,cAAc;AACjH,YAAM,YAAY,IAAI,SAAS,OAAO,EAAE,QAAQ,KAAK,KAAK,QAAQ,OAAO,cAAc,CAAC;AACxF,YAAM,iBAAiB,MAAM,OAC1B,aAAa,UAAU,gBAAgB,CAAC,MAAM,EAAE,UAAU,EAC1D,MAAM,CAAC,WAAW;AACjB,cAAM,OAAO,iBAAiB,KAAK,QAAQ,2BAA2B;AAAA,MACxE,CAAC;AAEH,UAAI,eAAe,WAAW,GAAG;AAC/B,cAAM,IAAI,OAAO,uBAAuB;AAAA,MAC1C;AAEA,YAAM,UAAU,eAAe,KAAK,CAAC,OAAO,GAAG,OAAO,SAAS;AAE/D,YAAM,WAAW,MAAM,KAAK,OAAO,OAAO,4CAA4C;AAAA,QACpF,SAAS,WAAW,EAAE,OAAO,QAAQ,MAAM,OAAO,QAAQ,GAAG;AAAA,QAC7D,SAAS,eAAe,IAAI,CAAC,QAAQ,EAAE,OAAO,GAAG,MAAM,OAAO,GAAG,GAAG,EAAE;AAAA,MACxE,CAAC;AAED,UAAI,CAAC,UAAU;AACb,cAAM,IAAI,OAAO,mBAAmB,cAAc;AAAA,MACpD;AAEA,aAAO;AAAA,IACT,CAAC;AAED,UAAM,KAAK,YAAY,IAAI,UAAU,KAAK,KAAK,MAAM;AAErD,UAAM,MAAM,KAAK,IAAI;AAAA,MACnB,EAAE,QAAQ,KAAK,KAAK,QAAQ,OAAO,eAAe,aAAa,oBAAoB;AAAA,MACnF,KAAK;AAAA,IACP;AAEA,UAAM,IAAI,UAAU,EAAE,MAAM,CAAC,WAAW;AACtC,YAAM,OAAO,iBAAiB,KAAK,QAAQ,6CAA6C;AAAA,IAC1F,CAAC;AAED,SAAK,OAAO,QAAQ,WAAW;AAAA,EACjC;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -27,6 +27,7 @@ __export(project_command_exports, {
|
|
|
27
27
|
ProjectCommand: () => ProjectCommand
|
|
28
28
|
});
|
|
29
29
|
module.exports = __toCommonJS(project_command_exports);
|
|
30
|
+
var import_bluebird = __toESM(require("bluebird"));
|
|
30
31
|
var import_chalk = __toESM(require("chalk"));
|
|
31
32
|
var import_fs = __toESM(require("fs"));
|
|
32
33
|
var import_lodash = __toESM(require("lodash"));
|
|
@@ -34,6 +35,7 @@ var import_path = __toESM(require("path"));
|
|
|
34
35
|
var codegen = __toESM(require("../code-generation"));
|
|
35
36
|
var consts = __toESM(require("../consts"));
|
|
36
37
|
var errors = __toESM(require("../errors"));
|
|
38
|
+
var import_integration_ref = require("../integration-ref");
|
|
37
39
|
var utils = __toESM(require("../utils"));
|
|
38
40
|
var import_global_command = require("./global-command");
|
|
39
41
|
class ProjectPaths extends utils.path.PathStore {
|
|
@@ -57,10 +59,37 @@ class ProjectCommand extends import_global_command.GlobalCommand {
|
|
|
57
59
|
get projectCache() {
|
|
58
60
|
return new utils.cache.FSKeyValueCache(this.projectPaths.abs.projectCacheFile);
|
|
59
61
|
}
|
|
60
|
-
|
|
62
|
+
async prepareBotIntegrationInstances(bot, api) {
|
|
63
|
+
const integrationList = (0, import_lodash.default)(bot.props.integrations).values().filter(utils.guards.is.defined).value();
|
|
64
|
+
const { apiInstances, localInstances } = this._splitApiAndLocalIntegrationInstances(integrationList);
|
|
65
|
+
const fetchedInstances = await import_bluebird.default.map(localInstances, async (instance) => {
|
|
66
|
+
const ref = { type: "name", name: instance.name, version: instance.version };
|
|
67
|
+
const integration = await api.findIntegration(ref);
|
|
68
|
+
if (!integration) {
|
|
69
|
+
const formattedRef = (0, import_integration_ref.formatIntegrationRef)(ref);
|
|
70
|
+
throw new errors.BotpressCLIError(`Integration "${formattedRef}" not found`);
|
|
71
|
+
}
|
|
72
|
+
return { ...instance, id: integration.id };
|
|
73
|
+
});
|
|
74
|
+
return {
|
|
75
|
+
integrations: (0, import_lodash.default)([...fetchedInstances, ...apiInstances]).keyBy((i) => i.id).mapValues(({ enabled, configuration }) => ({ enabled, configuration })).value()
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
_splitApiAndLocalIntegrationInstances(instances) {
|
|
79
|
+
const apiInstances = [];
|
|
80
|
+
const localInstances = [];
|
|
81
|
+
for (const { id, ...instance } of instances) {
|
|
82
|
+
if (id) {
|
|
83
|
+
apiInstances.push({ ...instance, id });
|
|
84
|
+
} else {
|
|
85
|
+
localInstances.push({ ...instance, id: null });
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return { apiInstances, localInstances };
|
|
89
|
+
}
|
|
90
|
+
prepareBot(bot) {
|
|
61
91
|
return {
|
|
62
92
|
...bot.props,
|
|
63
|
-
integrations: (0, import_lodash.default)(bot.props.integrations).values().filter(utils.guards.is.defined).keyBy((i) => i.id).mapValues(({ enabled, configuration }) => ({ enabled, configuration })).value(),
|
|
64
93
|
configuration: bot.props.configuration ? {
|
|
65
94
|
...bot.props.configuration,
|
|
66
95
|
schema: utils.schema.mapZodToJsonSchema(bot.props.configuration)
|
|
@@ -75,7 +104,7 @@ class ProjectCommand extends import_global_command.GlobalCommand {
|
|
|
75
104
|
})) : void 0
|
|
76
105
|
};
|
|
77
106
|
}
|
|
78
|
-
|
|
107
|
+
prepareIntegrationDefinition(integration) {
|
|
79
108
|
return {
|
|
80
109
|
...integration,
|
|
81
110
|
configuration: integration.configuration ? {
|
|
@@ -110,9 +139,9 @@ class ProjectCommand extends import_global_command.GlobalCommand {
|
|
|
110
139
|
})) : void 0
|
|
111
140
|
};
|
|
112
141
|
}
|
|
113
|
-
async readIntegrationDefinitionFromFS() {
|
|
114
|
-
const abs =
|
|
115
|
-
const rel =
|
|
142
|
+
async readIntegrationDefinitionFromFS(projectPaths = this.projectPaths) {
|
|
143
|
+
const abs = projectPaths.abs;
|
|
144
|
+
const rel = projectPaths.rel("workDir");
|
|
116
145
|
if (!import_fs.default.existsSync(abs.definition)) {
|
|
117
146
|
this.logger.debug(`Integration definition not found at ${rel.definition}`);
|
|
118
147
|
return;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/command-implementations/project-command.ts"],
|
|
4
|
-
"sourcesContent": ["import type * as bpclient from '@botpress/client'\nimport type * as bpsdk from '@botpress/sdk'\nimport type { YargsConfig } from '@bpinternal/yargs-extra'\nimport chalk from 'chalk'\nimport fs from 'fs'\nimport _ from 'lodash'\nimport pathlib from 'path'\nimport * as codegen from '../code-generation'\nimport type * as config from '../config'\nimport * as consts from '../consts'\nimport * as errors from '../errors'\nimport type { CommandArgv, CommandDefinition } from '../typings'\nimport * as utils from '../utils'\nimport { GlobalCommand } from './global-command'\n\nexport type ProjectCommandDefinition = CommandDefinition<typeof config.schemas.project>\nexport type ProjectCache = { botId: string; devId: string }\n\ntype ConfigurableProjectPaths = { entryPoint: string; outDir: string; workDir: string }\ntype ConstantProjectPaths = typeof consts.fromOutDir & typeof consts.fromWorkDir\ntype AllProjectPaths = ConfigurableProjectPaths & ConstantProjectPaths\n\nclass ProjectPaths extends utils.path.PathStore<keyof AllProjectPaths> {\n public constructor(argv: CommandArgv<ProjectCommandDefinition>) {\n const absWorkDir = utils.path.absoluteFrom(utils.path.cwd(), argv.workDir)\n const absEntrypoint = utils.path.absoluteFrom(absWorkDir, argv.entryPoint)\n const absOutDir = utils.path.absoluteFrom(absWorkDir, argv.outDir)\n super({\n workDir: absWorkDir,\n entryPoint: absEntrypoint,\n outDir: absOutDir,\n ..._.mapValues(consts.fromOutDir, (p) => utils.path.absoluteFrom(absOutDir, p)),\n ..._.mapValues(consts.fromWorkDir, (p) => utils.path.absoluteFrom(absWorkDir, p)),\n })\n }\n}\n\nexport abstract class ProjectCommand<C extends ProjectCommandDefinition> extends GlobalCommand<C> {\n protected get projectPaths() {\n return new ProjectPaths(this.argv)\n }\n\n protected get projectCache() {\n return new utils.cache.FSKeyValueCache<ProjectCache>(this.projectPaths.abs.projectCacheFile)\n }\n\n protected parseBot(bot: bpsdk.Bot) {\n return {\n ...bot.props,\n integrations: _(bot.props.integrations)\n .values()\n .filter(utils.guards.is.defined)\n .keyBy((i) => i.id)\n .mapValues(({ enabled, configuration }) => ({ enabled, configuration }))\n .value(),\n configuration: bot.props.configuration\n ? {\n ...bot.props.configuration,\n schema: utils.schema.mapZodToJsonSchema(bot.props.configuration),\n }\n : undefined,\n events: bot.props.events\n ? _.mapValues(bot.props.events, (event) => ({\n ...event,\n schema: utils.schema.mapZodToJsonSchema(event),\n }))\n : undefined,\n states: bot.props.states\n ? _.mapValues(bot.props.states, (state) => ({\n ...state,\n schema: utils.schema.mapZodToJsonSchema(state),\n }))\n : undefined,\n }\n }\n\n protected parseIntegrationDefinition(integration: bpsdk.IntegrationDefinition) {\n return {\n ...integration,\n configuration: integration.configuration\n ? {\n ...integration.configuration,\n schema: utils.schema.mapZodToJsonSchema(integration.configuration),\n }\n : undefined,\n events: integration.events\n ? _.mapValues(integration.events, (event) => ({\n ...event,\n schema: utils.schema.mapZodToJsonSchema(event),\n }))\n : undefined,\n actions: integration.actions\n ? _.mapValues(integration.actions, (action) => ({\n ...action,\n input: {\n ...action.input,\n schema: utils.schema.mapZodToJsonSchema(action.input),\n },\n output: {\n ...action.output,\n schema: utils.schema.mapZodToJsonSchema(action.output),\n },\n }))\n : undefined,\n channels: integration.channels\n ? _.mapValues(integration.channels, (channel) => ({\n ...channel,\n messages: _.mapValues(channel.messages, (message) => ({\n ...message,\n schema: utils.schema.mapZodToJsonSchema(message),\n })),\n }))\n : undefined,\n states: integration.states\n ? _.mapValues(integration.states, (state) => ({\n ...state,\n schema: utils.schema.mapZodToJsonSchema(state),\n }))\n : undefined,\n }\n }\n\n protected async readIntegrationDefinitionFromFS(): Promise<bpsdk.IntegrationDefinition | undefined> {\n const abs = this.projectPaths.abs\n const rel = this.projectPaths.rel('workDir')\n\n if (!fs.existsSync(abs.definition)) {\n this.logger.debug(`Integration definition not found at ${rel.definition}`)\n return\n }\n\n const { outputFiles } = await utils.esbuild.buildEntrypoint({\n cwd: abs.workDir,\n outfile: '',\n entrypoint: rel.definition,\n write: false,\n })\n\n const artifact = outputFiles[0]\n if (!artifact) {\n throw new errors.BotpressCLIError('Could not read integration definition')\n }\n\n const { default: definition } = utils.require.requireJsCode<{ default: bpsdk.IntegrationDefinition }>(artifact.text)\n return definition\n }\n\n protected async writeGeneratedFilesToOutFolder(files: codegen.File[]) {\n for (const file of files) {\n const filePath = utils.path.absoluteFrom(this.projectPaths.abs.outDir, file.path)\n const dirPath = pathlib.dirname(filePath)\n await fs.promises.mkdir(dirPath, { recursive: true })\n await fs.promises.writeFile(filePath, file.content)\n }\n }\n\n protected displayWebhookUrls(bot: bpclient.Bot) {\n if (!_.keys(bot.integrations).length) {\n this.logger.debug('No integrations in bot')\n return\n }\n\n this.logger.log('Integrations:')\n for (const integration of Object.values(bot.integrations).filter(utils.guards.is.defined)) {\n if (!integration.enabled) {\n this.logger.log(`${chalk.grey(integration.name)} ${chalk.italic('(disabled)')}: ${integration.webhookUrl}`, {\n prefix: { symbol: '\u25CB', indent: 2 },\n })\n } else {\n this.logger.log(`${chalk.bold(integration.name)} : ${integration.webhookUrl}`, {\n prefix: { symbol: '\u25CF', indent: 2 },\n })\n }\n }\n }\n\n protected async promptSecrets(\n integrationDef: bpsdk.IntegrationDefinition,\n argv: YargsConfig<typeof config.schemas.secrets>\n ): Promise<Record<string, string>> {\n const { secrets: secretDefinitions } = integrationDef\n if (!secretDefinitions) {\n return {}\n }\n\n const secretArgv = this._parseArgvSecrets(argv.secrets)\n const invalidSecret = Object.keys(secretArgv).find((s) => !secretDefinitions[s])\n if (invalidSecret) {\n throw new errors.BotpressCLIError(`Secret ${invalidSecret} is not defined in integration definition`)\n }\n\n const values: Record<string, string> = {}\n for (const [secretName, { optional }] of Object.entries(secretDefinitions)) {\n const argvSecret = secretArgv[secretName]\n if (argvSecret) {\n this.logger.debug(`Using secret \"${secretName}\" from argv`)\n values[secretName] = argvSecret\n continue\n }\n\n const mode = optional ? 'optional' : 'required'\n const prompted = await this.prompt.text(`Enter value for secret \"${secretName}\" (${mode})`)\n if (prompted) {\n values[secretName] = prompted\n continue\n }\n\n if (optional) {\n this.logger.warn(`Secret \"${secretName}\" is unassigned`)\n continue\n }\n\n throw new errors.BotpressCLIError(`Secret \"${secretName}\" is required`)\n }\n\n const envVariables = _.mapKeys(values, (_v, k) => codegen.secretEnvVariableName(k))\n return envVariables\n }\n\n private _parseArgvSecrets(argvSecrets: string[]): Record<string, string> {\n const parsed: Record<string, string> = {}\n for (const secret of argvSecrets) {\n const [key, value] = this._splitOnce(secret, '=')\n if (!value) {\n throw new errors.BotpressCLIError(\n `Secret \"${key}\" is missing a value. Expected format: \"SECRET_NAME=secretValue\"`\n )\n }\n parsed[key!] = value\n }\n\n return parsed\n }\n\n private _splitOnce = (text: string, separator: string): [string, string | undefined] => {\n const index = text.indexOf(separator)\n if (index === -1) {\n return [text, undefined]\n }\n return [text.slice(0, index), text.slice(index + 1)]\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,mBAAkB;AAClB,gBAAe;AACf,oBAAc;AACd,kBAAoB;
|
|
6
|
-
"names": ["_", "fs", "pathlib", "chalk"]
|
|
4
|
+
"sourcesContent": ["import type * as bpclient from '@botpress/client'\nimport type * as bpsdk from '@botpress/sdk'\nimport type { YargsConfig } from '@bpinternal/yargs-extra'\nimport bluebird from 'bluebird'\nimport chalk from 'chalk'\nimport fs from 'fs'\nimport _ from 'lodash'\nimport pathlib from 'path'\nimport { ApiClient } from '../api/client'\nimport * as codegen from '../code-generation'\nimport type * as config from '../config'\nimport * as consts from '../consts'\nimport * as errors from '../errors'\nimport { formatIntegrationRef, IntegrationRef } from '../integration-ref'\nimport type { CommandArgv, CommandDefinition } from '../typings'\nimport * as utils from '../utils'\nimport { GlobalCommand } from './global-command'\n\nexport type ProjectCommandDefinition = CommandDefinition<typeof config.schemas.project>\nexport type ProjectCache = { botId: string; devId: string }\n\ntype ConfigurableProjectPaths = { entryPoint: string; outDir: string; workDir: string }\ntype ConstantProjectPaths = typeof consts.fromOutDir & typeof consts.fromWorkDir\ntype AllProjectPaths = ConfigurableProjectPaths & ConstantProjectPaths\n\ntype ApiIntegrationInstance = utils.types.Merge<bpsdk.IntegrationInstance<string>, { id: string }>\ntype LocalIntegrationInstance = utils.types.Merge<bpsdk.IntegrationInstance<string>, { id: null }>\n\nclass ProjectPaths extends utils.path.PathStore<keyof AllProjectPaths> {\n public constructor(argv: CommandArgv<ProjectCommandDefinition>) {\n const absWorkDir = utils.path.absoluteFrom(utils.path.cwd(), argv.workDir)\n const absEntrypoint = utils.path.absoluteFrom(absWorkDir, argv.entryPoint)\n const absOutDir = utils.path.absoluteFrom(absWorkDir, argv.outDir)\n super({\n workDir: absWorkDir,\n entryPoint: absEntrypoint,\n outDir: absOutDir,\n ..._.mapValues(consts.fromOutDir, (p) => utils.path.absoluteFrom(absOutDir, p)),\n ..._.mapValues(consts.fromWorkDir, (p) => utils.path.absoluteFrom(absWorkDir, p)),\n })\n }\n}\n\nexport abstract class ProjectCommand<C extends ProjectCommandDefinition> extends GlobalCommand<C> {\n protected get projectPaths() {\n return new ProjectPaths(this.argv)\n }\n\n protected get projectCache() {\n return new utils.cache.FSKeyValueCache<ProjectCache>(this.projectPaths.abs.projectCacheFile)\n }\n\n protected async prepareBotIntegrationInstances(bot: bpsdk.Bot, api: ApiClient) {\n const integrationList = _(bot.props.integrations).values().filter(utils.guards.is.defined).value()\n\n const { apiInstances, localInstances } = this._splitApiAndLocalIntegrationInstances(integrationList)\n\n const fetchedInstances: ApiIntegrationInstance[] = await bluebird.map(localInstances, async (instance) => {\n const ref: IntegrationRef = { type: 'name', name: instance.name, version: instance.version }\n const integration = await api.findIntegration(ref)\n if (!integration) {\n const formattedRef = formatIntegrationRef(ref)\n throw new errors.BotpressCLIError(`Integration \"${formattedRef}\" not found`)\n }\n return { ...instance, id: integration.id }\n })\n\n return {\n integrations: _([...fetchedInstances, ...apiInstances])\n .keyBy((i) => i.id)\n .mapValues(({ enabled, configuration }) => ({ enabled, configuration }))\n .value(),\n }\n }\n\n private _splitApiAndLocalIntegrationInstances(instances: bpsdk.IntegrationInstance<string>[]): {\n apiInstances: ApiIntegrationInstance[]\n localInstances: LocalIntegrationInstance[]\n } {\n const apiInstances: ApiIntegrationInstance[] = []\n const localInstances: LocalIntegrationInstance[] = []\n for (const { id, ...instance } of instances) {\n if (id) {\n apiInstances.push({ ...instance, id })\n } else {\n localInstances.push({ ...instance, id: null })\n }\n }\n\n return { apiInstances, localInstances }\n }\n\n protected prepareBot(bot: bpsdk.Bot) {\n return {\n ...bot.props,\n configuration: bot.props.configuration\n ? {\n ...bot.props.configuration,\n schema: utils.schema.mapZodToJsonSchema(bot.props.configuration),\n }\n : undefined,\n events: bot.props.events\n ? _.mapValues(bot.props.events, (event) => ({\n ...event,\n schema: utils.schema.mapZodToJsonSchema(event),\n }))\n : undefined,\n states: bot.props.states\n ? _.mapValues(bot.props.states, (state) => ({\n ...state,\n schema: utils.schema.mapZodToJsonSchema(state),\n }))\n : undefined,\n }\n }\n\n protected prepareIntegrationDefinition(integration: bpsdk.IntegrationDefinition) {\n return {\n ...integration,\n configuration: integration.configuration\n ? {\n ...integration.configuration,\n schema: utils.schema.mapZodToJsonSchema(integration.configuration),\n }\n : undefined,\n events: integration.events\n ? _.mapValues(integration.events, (event) => ({\n ...event,\n schema: utils.schema.mapZodToJsonSchema(event),\n }))\n : undefined,\n actions: integration.actions\n ? _.mapValues(integration.actions, (action) => ({\n ...action,\n input: {\n ...action.input,\n schema: utils.schema.mapZodToJsonSchema(action.input),\n },\n output: {\n ...action.output,\n schema: utils.schema.mapZodToJsonSchema(action.output),\n },\n }))\n : undefined,\n channels: integration.channels\n ? _.mapValues(integration.channels, (channel) => ({\n ...channel,\n messages: _.mapValues(channel.messages, (message) => ({\n ...message,\n schema: utils.schema.mapZodToJsonSchema(message),\n })),\n }))\n : undefined,\n states: integration.states\n ? _.mapValues(integration.states, (state) => ({\n ...state,\n schema: utils.schema.mapZodToJsonSchema(state),\n }))\n : undefined,\n }\n }\n\n protected async readIntegrationDefinitionFromFS(\n projectPaths: utils.path.PathStore<'workDir' | 'definition'> = this.projectPaths\n ): Promise<bpsdk.IntegrationDefinition | undefined> {\n const abs = projectPaths.abs\n const rel = projectPaths.rel('workDir')\n\n if (!fs.existsSync(abs.definition)) {\n this.logger.debug(`Integration definition not found at ${rel.definition}`)\n return\n }\n\n const { outputFiles } = await utils.esbuild.buildEntrypoint({\n cwd: abs.workDir,\n outfile: '',\n entrypoint: rel.definition,\n write: false,\n })\n\n const artifact = outputFiles[0]\n if (!artifact) {\n throw new errors.BotpressCLIError('Could not read integration definition')\n }\n\n const { default: definition } = utils.require.requireJsCode<{ default: bpsdk.IntegrationDefinition }>(artifact.text)\n return definition\n }\n\n protected async writeGeneratedFilesToOutFolder(files: codegen.File[]) {\n for (const file of files) {\n const filePath = utils.path.absoluteFrom(this.projectPaths.abs.outDir, file.path)\n const dirPath = pathlib.dirname(filePath)\n await fs.promises.mkdir(dirPath, { recursive: true })\n await fs.promises.writeFile(filePath, file.content)\n }\n }\n\n protected displayWebhookUrls(bot: bpclient.Bot) {\n if (!_.keys(bot.integrations).length) {\n this.logger.debug('No integrations in bot')\n return\n }\n\n this.logger.log('Integrations:')\n for (const integration of Object.values(bot.integrations).filter(utils.guards.is.defined)) {\n if (!integration.enabled) {\n this.logger.log(`${chalk.grey(integration.name)} ${chalk.italic('(disabled)')}: ${integration.webhookUrl}`, {\n prefix: { symbol: '\u25CB', indent: 2 },\n })\n } else {\n this.logger.log(`${chalk.bold(integration.name)} : ${integration.webhookUrl}`, {\n prefix: { symbol: '\u25CF', indent: 2 },\n })\n }\n }\n }\n\n protected async promptSecrets(\n integrationDef: bpsdk.IntegrationDefinition,\n argv: YargsConfig<typeof config.schemas.secrets>\n ): Promise<Record<string, string>> {\n const { secrets: secretDefinitions } = integrationDef\n if (!secretDefinitions) {\n return {}\n }\n\n const secretArgv = this._parseArgvSecrets(argv.secrets)\n const invalidSecret = Object.keys(secretArgv).find((s) => !secretDefinitions[s])\n if (invalidSecret) {\n throw new errors.BotpressCLIError(`Secret ${invalidSecret} is not defined in integration definition`)\n }\n\n const values: Record<string, string> = {}\n for (const [secretName, { optional }] of Object.entries(secretDefinitions)) {\n const argvSecret = secretArgv[secretName]\n if (argvSecret) {\n this.logger.debug(`Using secret \"${secretName}\" from argv`)\n values[secretName] = argvSecret\n continue\n }\n\n const mode = optional ? 'optional' : 'required'\n const prompted = await this.prompt.text(`Enter value for secret \"${secretName}\" (${mode})`)\n if (prompted) {\n values[secretName] = prompted\n continue\n }\n\n if (optional) {\n this.logger.warn(`Secret \"${secretName}\" is unassigned`)\n continue\n }\n\n throw new errors.BotpressCLIError(`Secret \"${secretName}\" is required`)\n }\n\n const envVariables = _.mapKeys(values, (_v, k) => codegen.secretEnvVariableName(k))\n return envVariables\n }\n\n private _parseArgvSecrets(argvSecrets: string[]): Record<string, string> {\n const parsed: Record<string, string> = {}\n for (const secret of argvSecrets) {\n const [key, value] = this._splitOnce(secret, '=')\n if (!value) {\n throw new errors.BotpressCLIError(\n `Secret \"${key}\" is missing a value. Expected format: \"SECRET_NAME=secretValue\"`\n )\n }\n parsed[key!] = value\n }\n\n return parsed\n }\n\n private _splitOnce = (text: string, separator: string): [string, string | undefined] => {\n const index = text.indexOf(separator)\n if (index === -1) {\n return [text, undefined]\n }\n return [text.slice(0, index), text.slice(index + 1)]\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["_", "bluebird", "fs", "pathlib", "chalk"]
|
|
7
7
|
}
|
package/dist/integration-ref.js
CHANGED
|
@@ -30,17 +30,27 @@ __export(integration_ref_exports, {
|
|
|
30
30
|
module.exports = __toCommonJS(integration_ref_exports);
|
|
31
31
|
var import_semver = __toESM(require("semver"));
|
|
32
32
|
var uuid = __toESM(require("uuid"));
|
|
33
|
+
var utils = __toESM(require("./utils"));
|
|
33
34
|
const LATEST_TAG = "latest";
|
|
34
35
|
const formatIntegrationRef = (ref) => {
|
|
36
|
+
if (ref.type === "path") {
|
|
37
|
+
return ref.path;
|
|
38
|
+
}
|
|
35
39
|
if (ref.type === "id") {
|
|
36
40
|
return ref.id;
|
|
37
41
|
}
|
|
38
42
|
return `${ref.name}@${ref.version}`;
|
|
39
43
|
};
|
|
40
44
|
const parseIntegrationRef = (ref) => {
|
|
45
|
+
if (!ref) {
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
41
48
|
if (uuid.validate(ref)) {
|
|
42
49
|
return { type: "id", id: ref };
|
|
43
50
|
}
|
|
51
|
+
if (utils.path.isAbsolute(ref)) {
|
|
52
|
+
return { type: "path", path: ref };
|
|
53
|
+
}
|
|
44
54
|
if (!ref.includes("@")) {
|
|
45
55
|
return { type: "name", name: ref, version: LATEST_TAG };
|
|
46
56
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/integration-ref.ts"],
|
|
4
|
-
"sourcesContent": ["import semver from 'semver'\nimport * as uuid from 'uuid'\n\nexport type UUIDIntegrationRef = {\n type: 'id'\n id: string\n}\n\nexport type NameIntegrationRef = {\n type: 'name'\n name: string\n version: string\n}\n\nexport type
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAmB;AACnB,WAAsB;
|
|
4
|
+
"sourcesContent": ["import semver from 'semver'\nimport * as uuid from 'uuid'\nimport * as utils from './utils'\n\nexport type UUIDIntegrationRef = {\n type: 'id'\n id: string\n}\n\nexport type NameIntegrationRef = {\n type: 'name'\n name: string\n version: string\n}\n\nexport type LocalPathIntegrationRef = {\n type: 'path'\n path: utils.path.AbsolutePath\n}\n\nexport type ApiIntegrationRef = UUIDIntegrationRef | NameIntegrationRef\nexport type IntegrationRef = ApiIntegrationRef | LocalPathIntegrationRef\n\nconst LATEST_TAG = 'latest'\n\nexport const formatIntegrationRef = (ref: IntegrationRef): string => {\n if (ref.type === 'path') {\n return ref.path\n }\n if (ref.type === 'id') {\n return ref.id\n }\n return `${ref.name}@${ref.version}`\n}\n\nexport const parseIntegrationRef = (ref: string): IntegrationRef | undefined => {\n if (!ref) {\n return\n }\n\n if (uuid.validate(ref)) {\n return { type: 'id', id: ref }\n }\n\n if (utils.path.isAbsolute(ref)) {\n return { type: 'path', path: ref }\n }\n\n if (!ref.includes('@')) {\n return { type: 'name', name: ref, version: LATEST_TAG }\n }\n\n const [name, version] = ref.split('@')\n if (!name || !version) {\n return\n }\n\n const cleanedVersion = version === LATEST_TAG ? version : semver.clean(version)\n if (!cleanedVersion) {\n return\n }\n\n return { type: 'name', name, version: cleanedVersion }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oBAAmB;AACnB,WAAsB;AACtB,YAAuB;AAqBvB,MAAM,aAAa;AAEZ,MAAM,uBAAuB,CAAC,QAAgC;AACnE,MAAI,IAAI,SAAS,QAAQ;AACvB,WAAO,IAAI;AAAA,EACb;AACA,MAAI,IAAI,SAAS,MAAM;AACrB,WAAO,IAAI;AAAA,EACb;AACA,SAAO,GAAG,IAAI,QAAQ,IAAI;AAC5B;AAEO,MAAM,sBAAsB,CAAC,QAA4C;AAC9E,MAAI,CAAC,KAAK;AACR;AAAA,EACF;AAEA,MAAI,KAAK,SAAS,GAAG,GAAG;AACtB,WAAO,EAAE,MAAM,MAAM,IAAI,IAAI;AAAA,EAC/B;AAEA,MAAI,MAAM,KAAK,WAAW,GAAG,GAAG;AAC9B,WAAO,EAAE,MAAM,QAAQ,MAAM,IAAI;AAAA,EACnC;AAEA,MAAI,CAAC,IAAI,SAAS,GAAG,GAAG;AACtB,WAAO,EAAE,MAAM,QAAQ,MAAM,KAAK,SAAS,WAAW;AAAA,EACxD;AAEA,QAAM,CAAC,MAAM,OAAO,IAAI,IAAI,MAAM,GAAG;AACrC,MAAI,CAAC,QAAQ,CAAC,SAAS;AACrB;AAAA,EACF;AAEA,QAAM,iBAAiB,YAAY,aAAa,UAAU,cAAAA,QAAO,MAAM,OAAO;AAC9E,MAAI,CAAC,gBAAgB;AACnB;AAAA,EACF;AAEA,SAAO,EAAE,MAAM,QAAQ,MAAM,SAAS,eAAe;AACvD;",
|
|
6
6
|
"names": ["semver"]
|
|
7
7
|
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var import_node_test = require("node:test");
|
|
3
|
+
var import_vitest = require("vitest");
|
|
4
|
+
var import_integration_ref = require("./integration-ref");
|
|
5
|
+
const path = "/my/path";
|
|
6
|
+
const uuid = "a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a11";
|
|
7
|
+
const name = "myintegration";
|
|
8
|
+
(0, import_node_test.describe)("parseIntegrationRef", () => {
|
|
9
|
+
(0, import_vitest.test)("parse empty string should return undefined", () => {
|
|
10
|
+
const ref = "";
|
|
11
|
+
const result = (0, import_integration_ref.parseIntegrationRef)(ref);
|
|
12
|
+
(0, import_vitest.expect)(result).toBeUndefined();
|
|
13
|
+
});
|
|
14
|
+
(0, import_vitest.test)("parse with invalid version should return undefined", () => {
|
|
15
|
+
const ref0 = `${name}@lol`;
|
|
16
|
+
const ref1 = `${name}@1`;
|
|
17
|
+
const ref2 = `${name}@1.0`;
|
|
18
|
+
const result0 = (0, import_integration_ref.parseIntegrationRef)(ref0);
|
|
19
|
+
const result1 = (0, import_integration_ref.parseIntegrationRef)(ref1);
|
|
20
|
+
const result2 = (0, import_integration_ref.parseIntegrationRef)(ref2);
|
|
21
|
+
(0, import_vitest.expect)(result0).toBeUndefined();
|
|
22
|
+
(0, import_vitest.expect)(result1).toBeUndefined();
|
|
23
|
+
(0, import_vitest.expect)(result2).toBeUndefined();
|
|
24
|
+
});
|
|
25
|
+
(0, import_vitest.test)("parse with an absolute path should return path", () => {
|
|
26
|
+
const ref = path;
|
|
27
|
+
const result = (0, import_integration_ref.parseIntegrationRef)(ref);
|
|
28
|
+
const expected = { type: "path", path: ref };
|
|
29
|
+
(0, import_vitest.expect)(result).toEqual(expected);
|
|
30
|
+
});
|
|
31
|
+
(0, import_vitest.test)("parse with a uuid return uuid", () => {
|
|
32
|
+
const ref = uuid;
|
|
33
|
+
const result = (0, import_integration_ref.parseIntegrationRef)(ref);
|
|
34
|
+
const expected = { type: "id", id: ref };
|
|
35
|
+
(0, import_vitest.expect)(result).toEqual(expected);
|
|
36
|
+
});
|
|
37
|
+
(0, import_vitest.test)("parse with a name and version should return name and version", () => {
|
|
38
|
+
const version = "1.0.0";
|
|
39
|
+
const ref = `${name}@${version}`;
|
|
40
|
+
const result = (0, import_integration_ref.parseIntegrationRef)(ref);
|
|
41
|
+
const expected = { type: "name", name, version };
|
|
42
|
+
(0, import_vitest.expect)(result).toEqual(expected);
|
|
43
|
+
});
|
|
44
|
+
(0, import_vitest.test)("parse with a name and latest should return name and latest", () => {
|
|
45
|
+
const version = "latest";
|
|
46
|
+
const ref = `${name}@${version}`;
|
|
47
|
+
const result = (0, import_integration_ref.parseIntegrationRef)(ref);
|
|
48
|
+
const expected = { type: "name", name, version };
|
|
49
|
+
(0, import_vitest.expect)(result).toEqual(expected);
|
|
50
|
+
});
|
|
51
|
+
(0, import_vitest.test)("parse with only a name should return name and latest", () => {
|
|
52
|
+
const ref = name;
|
|
53
|
+
const result = (0, import_integration_ref.parseIntegrationRef)(ref);
|
|
54
|
+
const expected = { type: "name", name, version: "latest" };
|
|
55
|
+
(0, import_vitest.expect)(result).toEqual(expected);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
(0, import_node_test.describe)("formatIntegrationRef", () => {
|
|
59
|
+
(0, import_vitest.test)("format with a path should return path", () => {
|
|
60
|
+
const ref = { type: "path", path };
|
|
61
|
+
const result = (0, import_integration_ref.formatIntegrationRef)(ref);
|
|
62
|
+
(0, import_vitest.expect)(result).toEqual(ref.path);
|
|
63
|
+
});
|
|
64
|
+
(0, import_vitest.test)("format with a uuid should return uuid", () => {
|
|
65
|
+
const ref = { type: "id", id: uuid };
|
|
66
|
+
const result = (0, import_integration_ref.formatIntegrationRef)(ref);
|
|
67
|
+
(0, import_vitest.expect)(result).toEqual(ref.id);
|
|
68
|
+
});
|
|
69
|
+
(0, import_vitest.test)("format with a name and version should return name and version", () => {
|
|
70
|
+
const version = "1.0.0";
|
|
71
|
+
const ref = { type: "name", name, version };
|
|
72
|
+
const result = (0, import_integration_ref.formatIntegrationRef)(ref);
|
|
73
|
+
(0, import_vitest.expect)(result).toEqual(`${name}@${version}`);
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
//# sourceMappingURL=integration-ref.test.js.map
|