@botpress/cli 5.4.3 → 5.5.1
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/.turbo/turbo-build.log +13 -13
- package/dist/code-generation/integration-implementation/integration-secret.d.ts +1 -0
- package/dist/code-generation/integration-implementation/integration-secret.js +5 -2
- package/dist/code-generation/integration-implementation/integration-secret.js.map +2 -2
- package/dist/command-definitions.d.ts +6 -0
- package/dist/command-implementations/dev-command.d.ts +3 -0
- package/dist/command-implementations/dev-command.js +33 -1
- package/dist/command-implementations/dev-command.js.map +2 -2
- package/dist/command-implementations/index.d.ts +6 -0
- package/dist/command-implementations/lint-command.js +13 -6
- package/dist/command-implementations/lint-command.js.map +2 -2
- package/dist/command-implementations/project-command.d.ts +3 -0
- package/dist/command-implementations/project-command.js.map +2 -2
- package/dist/config.d.ts +6 -0
- package/dist/config.js +6 -0
- package/dist/config.js.map +2 -2
- package/dist/index.d.ts +6 -0
- package/dist/linter/base-linter.d.ts +16 -2
- package/dist/linter/base-linter.js +29 -4
- package/dist/linter/base-linter.js.map +3 -3
- package/dist/linter/ruleset-functions.d.ts +8 -0
- package/dist/linter/ruleset-functions.js +75 -0
- package/dist/linter/ruleset-functions.js.map +7 -0
- package/dist/linter/ruleset-tests/common.d.ts +1 -2
- package/dist/linter/ruleset-tests/common.js.map +1 -1
- package/dist/linter/rulesets/bot.ruleset.d.ts +1 -141
- package/dist/linter/rulesets/bot.ruleset.js +29 -28
- package/dist/linter/rulesets/bot.ruleset.js.map +2 -2
- package/dist/linter/rulesets/integration.ruleset.d.ts +1 -336
- package/dist/linter/rulesets/integration.ruleset.js +63 -62
- package/dist/linter/rulesets/integration.ruleset.js.map +2 -2
- package/dist/linter/rulesets/interface.ruleset.d.ts +1 -101
- package/dist/linter/rulesets/interface.ruleset.js +21 -20
- package/dist/linter/rulesets/interface.ruleset.js.map +2 -2
- package/package.json +3 -3
- package/templates/empty-bot/package.json +2 -2
- package/templates/empty-integration/package.json +2 -2
- package/templates/empty-plugin/package.json +1 -1
- package/templates/hello-world/package.json +2 -2
- package/templates/webhook-message/package.json +2 -2
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
1
|
|
|
2
|
-
> @botpress/cli@5.
|
|
2
|
+
> @botpress/cli@5.5.1 build /home/runner/work/botpress/botpress/packages/cli
|
|
3
3
|
> pnpm run build:types && pnpm run bundle && pnpm run template:gen
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
> @botpress/cli@5.
|
|
6
|
+
> @botpress/cli@5.5.1 build:types /home/runner/work/botpress/botpress/packages/cli
|
|
7
7
|
> tsc -p ./tsconfig.build.json
|
|
8
8
|
|
|
9
9
|
|
|
10
|
-
> @botpress/cli@5.
|
|
10
|
+
> @botpress/cli@5.5.1 bundle /home/runner/work/botpress/botpress/packages/cli
|
|
11
11
|
> ts-node -T build.ts
|
|
12
12
|
|
|
13
13
|
|
|
14
|
-
> @botpress/cli@5.
|
|
14
|
+
> @botpress/cli@5.5.1 template:gen /home/runner/work/botpress/botpress/packages/cli
|
|
15
15
|
> pnpm -r --stream -F @bp-templates/* exec bp gen
|
|
16
16
|
|
|
17
|
-
🤖 Botpress CLI v5.
|
|
18
|
-
🤖 Botpress CLI v5.4.3
|
|
19
|
-
🤖 Botpress CLI v5.4.3
|
|
17
|
+
🤖 Botpress CLI v5.5.1
|
|
20
18
|
● Checking if cli is up to date
|
|
19
|
+
🤖 Botpress CLI v5.5.1
|
|
21
20
|
● Checking if cli is up to date
|
|
21
|
+
🤖 Botpress CLI v5.5.1
|
|
22
22
|
● Checking if cli is up to date
|
|
23
|
-
🤖 Botpress CLI v5.
|
|
23
|
+
🤖 Botpress CLI v5.5.1
|
|
24
24
|
● Checking if cli is up to date
|
|
25
25
|
● Checking if sdk is up to date
|
|
26
26
|
● Checking if sdk is up to date
|
|
27
27
|
● Checking if sdk is up to date
|
|
28
28
|
● Checking if sdk is up to date
|
|
29
|
-
○ Generating typings for
|
|
30
|
-
○ Generating typings for bot...
|
|
29
|
+
○ Generating typings for integration empty-integration...
|
|
31
30
|
✓ Typings available at .botpress
|
|
32
31
|
|
|
32
|
+
○ Generating typings for integration hello-world...
|
|
33
|
+
○ Generating typings for plugin empty-plugin...
|
|
34
|
+
○ Generating typings for bot...
|
|
33
35
|
✓ Typings available at .botpress
|
|
34
36
|
|
|
35
|
-
○ Generating typings for integration empty-integration...
|
|
36
37
|
✓ Typings available at .botpress
|
|
37
38
|
|
|
38
|
-
○ Generating typings for integration hello-world...
|
|
39
39
|
✓ Typings available at .botpress
|
|
40
40
|
|
|
41
|
-
🤖 Botpress CLI v5.
|
|
41
|
+
🤖 Botpress CLI v5.5.1
|
|
42
42
|
● Checking if cli is up to date
|
|
43
43
|
● Checking if sdk is up to date
|
|
44
44
|
○ Generating typings for integration webhook-message...
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { IntegrationDefinition } from '@botpress/sdk';
|
|
2
2
|
import { Module } from '../module';
|
|
3
3
|
export declare const secretEnvVariableName: (secretName: string) => string;
|
|
4
|
+
export declare const stripSecretEnvVariablePrefix: (secretName: string) => string;
|
|
4
5
|
export declare class IntegrationSecretIndexModule extends Module {
|
|
5
6
|
private _integration;
|
|
6
7
|
constructor(_integration: IntegrationDefinition);
|
|
@@ -29,13 +29,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
29
29
|
var integration_secret_exports = {};
|
|
30
30
|
__export(integration_secret_exports, {
|
|
31
31
|
IntegrationSecretIndexModule: () => IntegrationSecretIndexModule,
|
|
32
|
-
secretEnvVariableName: () => secretEnvVariableName
|
|
32
|
+
secretEnvVariableName: () => secretEnvVariableName,
|
|
33
|
+
stripSecretEnvVariablePrefix: () => stripSecretEnvVariablePrefix
|
|
33
34
|
});
|
|
34
35
|
module.exports = __toCommonJS(integration_secret_exports);
|
|
35
36
|
var import_utils = require("../../utils");
|
|
36
37
|
var consts = __toESM(require("../consts"));
|
|
37
38
|
var import_module = require("../module");
|
|
38
39
|
const secretEnvVariableName = (secretName) => `SECRET_${import_utils.casing.to.screamingSnakeCase(secretName)}`;
|
|
40
|
+
const stripSecretEnvVariablePrefix = (secretName) => secretName.replace(/^SECRET_/, "");
|
|
39
41
|
class IntegrationSecretIndexModule extends import_module.Module {
|
|
40
42
|
constructor(_integration) {
|
|
41
43
|
super({ exportName: "secrets", path: consts.INDEX_FILE });
|
|
@@ -73,6 +75,7 @@ class IntegrationSecretIndexModule extends import_module.Module {
|
|
|
73
75
|
// Annotate the CommonJS export names for ESM import in node:
|
|
74
76
|
0 && (module.exports = {
|
|
75
77
|
IntegrationSecretIndexModule,
|
|
76
|
-
secretEnvVariableName
|
|
78
|
+
secretEnvVariableName,
|
|
79
|
+
stripSecretEnvVariablePrefix
|
|
77
80
|
});
|
|
78
81
|
//# sourceMappingURL=integration-secret.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/code-generation/integration-implementation/integration-secret.ts"],
|
|
4
|
-
"sourcesContent": ["import { IntegrationDefinition } from '@botpress/sdk'\nimport { casing } from '../../utils'\nimport * as consts from '../consts'\nimport { Module } from '../module'\n\nexport const secretEnvVariableName = (secretName: string) => `SECRET_${casing.to.screamingSnakeCase(secretName)}`\n\nexport class IntegrationSecretIndexModule extends Module {\n public constructor(private _integration: IntegrationDefinition) {\n super({ exportName: 'secrets', path: consts.INDEX_FILE })\n }\n\n public async getContent() {\n let content = consts.GENERATED_HEADER\n content += 'class Secrets {\\n'\n for (const [secretName, { optional }] of Object.entries(this._integration.secrets ?? {})) {\n const envVariableName = secretEnvVariableName(secretName)\n const fieldName = casing.to.screamingSnakeCase(secretName)\n\n if (optional) {\n content += ` public get ${fieldName}(): string | undefined {\\n`\n content += ` const envVarValue = process.env.${envVariableName}\\n`\n content += ' return envVarValue\\n'\n content += ' }\\n'\n } else {\n content += ` public get ${fieldName}(): string {\\n`\n content += ` const envVarValue = process.env.${envVariableName}\\n`\n content += ` if (!envVarValue) throw new Error('Missing required secret \"${secretName}\"')\\n`\n content += ' return envVarValue\\n'\n content += ' }\\n'\n }\n }\n content += '}\\n'\n content += 'export const secrets = new Secrets()\\n'\n return content\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAAuB;AACvB,aAAwB;AACxB,oBAAuB;AAEhB,MAAM,wBAAwB,CAAC,eAAuB,UAAU,oBAAO,GAAG,mBAAmB,UAAU,CAAC;
|
|
4
|
+
"sourcesContent": ["import { IntegrationDefinition } from '@botpress/sdk'\nimport { casing } from '../../utils'\nimport * as consts from '../consts'\nimport { Module } from '../module'\n\nexport const secretEnvVariableName = (secretName: string) => `SECRET_${casing.to.screamingSnakeCase(secretName)}`\nexport const stripSecretEnvVariablePrefix = (secretName: string) => secretName.replace(/^SECRET_/, '')\n\nexport class IntegrationSecretIndexModule extends Module {\n public constructor(private _integration: IntegrationDefinition) {\n super({ exportName: 'secrets', path: consts.INDEX_FILE })\n }\n\n public async getContent() {\n let content = consts.GENERATED_HEADER\n content += 'class Secrets {\\n'\n for (const [secretName, { optional }] of Object.entries(this._integration.secrets ?? {})) {\n const envVariableName = secretEnvVariableName(secretName)\n const fieldName = casing.to.screamingSnakeCase(secretName)\n\n if (optional) {\n content += ` public get ${fieldName}(): string | undefined {\\n`\n content += ` const envVarValue = process.env.${envVariableName}\\n`\n content += ' return envVarValue\\n'\n content += ' }\\n'\n } else {\n content += ` public get ${fieldName}(): string {\\n`\n content += ` const envVarValue = process.env.${envVariableName}\\n`\n content += ` if (!envVarValue) throw new Error('Missing required secret \"${secretName}\"')\\n`\n content += ' return envVarValue\\n'\n content += ' }\\n'\n }\n }\n content += '}\\n'\n content += 'export const secrets = new Secrets()\\n'\n return content\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAAuB;AACvB,aAAwB;AACxB,oBAAuB;AAEhB,MAAM,wBAAwB,CAAC,eAAuB,UAAU,oBAAO,GAAG,mBAAmB,UAAU,CAAC;AACxG,MAAM,+BAA+B,CAAC,eAAuB,WAAW,QAAQ,YAAY,EAAE;AAE9F,MAAM,qCAAqC,qBAAO;AAAA,EAChD,YAAoB,cAAqC;AAC9D,UAAM,EAAE,YAAY,WAAW,MAAM,OAAO,WAAW,CAAC;AAD/B;AAAA,EAE3B;AAAA,EAEA,MAAa,aAAa;AACxB,QAAI,UAAU,OAAO;AACrB,eAAW;AACX,eAAW,CAAC,YAAY,EAAE,SAAS,CAAC,KAAK,OAAO,QAAQ,KAAK,aAAa,WAAW,CAAC,CAAC,GAAG;AACxF,YAAM,kBAAkB,sBAAsB,UAAU;AACxD,YAAM,YAAY,oBAAO,GAAG,mBAAmB,UAAU;AAEzD,UAAI,UAAU;AACZ,mBAAW,gBAAgB,SAAS;AAAA;AACpC,mBAAW,uCAAuC,eAAe;AAAA;AACjE,mBAAW;AACX,mBAAW;AAAA,MACb,OAAO;AACL,mBAAW,gBAAgB,SAAS;AAAA;AACpC,mBAAW,uCAAuC,eAAe;AAAA;AACjE,mBAAW,mEAAmE,UAAU;AAAA;AACxF,mBAAW;AACX,mBAAW;AAAA,MACb;AAAA,IACF;AACA,eAAW;AACX,eAAW;AACX,WAAO;AAAA,EACT;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1293,6 +1293,12 @@ declare const _default: {
|
|
|
1293
1293
|
type: "string";
|
|
1294
1294
|
description: string;
|
|
1295
1295
|
};
|
|
1296
|
+
noSecretCaching: {
|
|
1297
|
+
type: "boolean";
|
|
1298
|
+
description: string;
|
|
1299
|
+
default: boolean;
|
|
1300
|
+
alias: string;
|
|
1301
|
+
};
|
|
1296
1302
|
secrets: {
|
|
1297
1303
|
type: "string";
|
|
1298
1304
|
description: string;
|
|
@@ -9,6 +9,9 @@ export declare class DevCommand extends ProjectCommand<DevCommandDefinition> {
|
|
|
9
9
|
run(): Promise<void>;
|
|
10
10
|
private _restart;
|
|
11
11
|
private _deploy;
|
|
12
|
+
private _writeKnownSecretsToCache;
|
|
13
|
+
private _readKnownSecretsFromCache;
|
|
14
|
+
private _applyPrefixToSecrets;
|
|
12
15
|
private _checkSecrets;
|
|
13
16
|
private _spawnWorker;
|
|
14
17
|
private _runBuild;
|
|
@@ -37,6 +37,7 @@ var import_lodash = require("lodash");
|
|
|
37
37
|
var pathlib = __toESM(require("path"));
|
|
38
38
|
var uuid = __toESM(require("uuid"));
|
|
39
39
|
var apiUtils = __toESM(require("../api"));
|
|
40
|
+
var import_integration_secret = require("../code-generation/integration-implementation/integration-secret");
|
|
40
41
|
var errors = __toESM(require("../errors"));
|
|
41
42
|
var tables = __toESM(require("../tables"));
|
|
42
43
|
var utils = __toESM(require("../utils"));
|
|
@@ -72,8 +73,16 @@ class DevCommand extends import_project_command.ProjectCommand {
|
|
|
72
73
|
let defaultPort = DEFAULT_BOT_PORT;
|
|
73
74
|
if (this._initialDef.type === "integration") {
|
|
74
75
|
defaultPort = DEFAULT_INTEGRATION_PORT;
|
|
75
|
-
const
|
|
76
|
+
const knownSecrets = await this._readKnownSecretsFromCache();
|
|
77
|
+
let secretEnvVariables = await this.promptSecrets(this._initialDef.definition, this.argv, {
|
|
78
|
+
knownSecrets: Object.keys(knownSecrets),
|
|
79
|
+
formatEnv: true
|
|
80
|
+
});
|
|
81
|
+
secretEnvVariables = { ...this._applyPrefixToSecrets(knownSecrets), ...secretEnvVariables };
|
|
76
82
|
const nonNullSecretEnvVariables = utils.records.filterValues(secretEnvVariables, utils.guards.is.notNull);
|
|
83
|
+
if (!this.argv.noSecretCaching) {
|
|
84
|
+
await this._writeKnownSecretsToCache(secretEnvVariables);
|
|
85
|
+
}
|
|
77
86
|
env = { ...env, ...nonNullSecretEnvVariables };
|
|
78
87
|
}
|
|
79
88
|
const port = this.argv.port ?? defaultPort;
|
|
@@ -201,6 +210,29 @@ class DevCommand extends import_project_command.ProjectCommand {
|
|
|
201
210
|
}
|
|
202
211
|
throw new errors.UnsupportedProjectType();
|
|
203
212
|
};
|
|
213
|
+
async _writeKnownSecretsToCache(secretEnvVariables) {
|
|
214
|
+
const knownSecrets = {};
|
|
215
|
+
for (const [prefixedSecretName, secretValue] of Object.entries(secretEnvVariables)) {
|
|
216
|
+
const secretName = (0, import_integration_secret.stripSecretEnvVariablePrefix)(prefixedSecretName);
|
|
217
|
+
knownSecrets[secretName] = secretValue;
|
|
218
|
+
}
|
|
219
|
+
const nonNullKnownSecrets = utils.records.filterValues(knownSecrets, utils.guards.is.notNull);
|
|
220
|
+
if (Object.keys(nonNullKnownSecrets).length === 0) {
|
|
221
|
+
await this.projectCache.rm("secrets");
|
|
222
|
+
return;
|
|
223
|
+
}
|
|
224
|
+
await this.projectCache.set("secrets", nonNullKnownSecrets);
|
|
225
|
+
}
|
|
226
|
+
async _readKnownSecretsFromCache() {
|
|
227
|
+
return await this.projectCache.get("secrets") ?? {};
|
|
228
|
+
}
|
|
229
|
+
_applyPrefixToSecrets(secrets) {
|
|
230
|
+
const prefixedSecretEntries = Object.entries(secrets).map(([secretName, secretValue]) => [
|
|
231
|
+
(0, import_integration_secret.secretEnvVariableName)(secretName),
|
|
232
|
+
secretValue
|
|
233
|
+
]);
|
|
234
|
+
return Object.fromEntries(prefixedSecretEntries);
|
|
235
|
+
}
|
|
204
236
|
_checkSecrets(integrationDef) {
|
|
205
237
|
if (this._initialDef?.type !== "integration") {
|
|
206
238
|
return;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/command-implementations/dev-command.ts"],
|
|
4
|
-
"sourcesContent": ["import type * as client from '@botpress/client'\nimport type * as sdk from '@botpress/sdk'\nimport { TunnelRequest, TunnelResponse } from '@bpinternal/tunnel'\nimport axios, { AxiosRequestConfig, AxiosResponse } from 'axios'\nimport chalk from 'chalk'\nimport { isEqual } from 'lodash'\nimport * as pathlib from 'path'\nimport * as uuid from 'uuid'\nimport * as apiUtils from '../api'\nimport type commandDefinitions from '../command-definitions'\nimport * as errors from '../errors'\nimport * as tables from '../tables'\nimport * as utils from '../utils'\nimport { Worker } from '../worker'\nimport { BuildCommand } from './build-command'\nimport { ProjectCommand, ProjectDefinition } from './project-command'\n\nconst DEFAULT_BOT_PORT = 8075\nconst DEFAULT_INTEGRATION_PORT = 8076\nconst TUNNEL_HELLO_INTERVAL = 5000\nconst FILEWATCHER_DEBOUNCE_MS = 500\n\nexport type DevCommandDefinition = typeof commandDefinitions.dev\nexport class DevCommand extends ProjectCommand<DevCommandDefinition> {\n private _initialDef: ProjectDefinition | undefined = undefined\n private _cacheDevRequestBody: apiUtils.UpdateBotRequestBody | apiUtils.UpdateIntegrationRequestBody | undefined\n private _buildContext: utils.esbuild.BuildCodeContext\n\n public constructor(...args: ConstructorParameters<typeof ProjectCommand<DevCommandDefinition>>) {\n super(...args)\n this._buildContext = new utils.esbuild.BuildCodeContext()\n }\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 const { projectType, resolveProjectDefinition } = this.readProjectDefinitionFromFS()\n if (projectType === 'interface') {\n throw new errors.BotpressCLIError('This feature is not available for interfaces.')\n }\n const projectDef = await resolveProjectDefinition()\n this._initialDef = projectDef\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.type === 'integration') {\n defaultPort = DEFAULT_INTEGRATION_PORT\n // TODO: store secrets in local cache to avoid prompting every time\n const secretEnvVariables = await this.promptSecrets(this._initialDef.definition, this.argv, { formatEnv: true })\n const nonNullSecretEnvVariables = utils.records.filterValues(secretEnvVariables, utils.guards.is.notNull)\n env = { ...env, ...nonNullSecretEnvVariables }\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 cachedTunnelId = await this.projectCache.get('tunnelId')\n\n let tunnelId: string\n if (this.argv.tunnelId) {\n tunnelId = this.argv.tunnelId\n } else if (cachedTunnelId) {\n tunnelId = cachedTunnelId\n } else {\n tunnelId = uuid.v4()\n }\n\n if (cachedTunnelId !== tunnelId) {\n await this.projectCache.set('tunnelId', tunnelId)\n }\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(() => {\n if (tunnel.closed) {\n return handleClose()\n }\n tunnel.hello()\n }, TUNNEL_HELLO_INTERVAL)\n const handleClose = (): void => clearInterval(timer)\n tunnel.events.on('close', handleClose)\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\n supervisor.events.on('manuallyClosed', () => {\n this.logger.debug('Tunnel manually closed')\n })\n\n await supervisor.start()\n\n await this._runBuild()\n worker = await this._spawnWorker(env, port)\n await this._deploy(api, httpTunnelUrl)\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\n .filter((e) => !e.path.startsWith(this.projectPaths.abs.outDir))\n .filter((e) => pathlib.extname(e.path) === '.ts')\n\n const distEvents = events.filter((e) => e.path.startsWith(this.projectPaths.abs.distDir))\n\n if (typescriptEvents.length > 0) {\n this.logger.log('Changes detected, rebuilding')\n await this._restart(api, worker, httpTunnelUrl)\n } else if (distEvents.length > 0) {\n this.logger.log('Changes detected in output directory, reloading worker')\n await worker.reload()\n }\n },\n {\n debounceMs: FILEWATCHER_DEBOUNCE_MS,\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: apiUtils.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 worker.reload()\n await this._deploy(api, tunnelUrl)\n }\n\n private _deploy = async (api: apiUtils.ApiClient, tunnelUrl: string) => {\n const { projectType, resolveProjectDefinition } = this.readProjectDefinitionFromFS()\n\n if (projectType === 'interface') {\n throw new errors.BotpressCLIError('This feature is not available for interfaces.')\n }\n if (projectType === 'integration') {\n const projectDef = await resolveProjectDefinition()\n this._checkSecrets(projectDef.definition)\n return await this._deployDevIntegration(api, tunnelUrl, projectDef.definition)\n }\n if (projectType === 'bot') {\n const projectDef = await resolveProjectDefinition()\n return await this._deployDevBot(api, tunnelUrl, projectDef.definition)\n }\n throw new errors.UnsupportedProjectType()\n }\n\n private _checkSecrets(integrationDef: sdk.IntegrationDefinition) {\n if (this._initialDef?.type !== 'integration') {\n return\n }\n const initialSecrets = this._initialDef?.definition.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.outFileCJS\n const importPath = utils.path.toUnix(outfile)\n const code = `require('${importPath}').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)\n .setProjectContext(this.projectContext)\n .run(this._buildContext)\n }\n\n private async _deployDevIntegration(\n api: apiUtils.ApiClient,\n externalUrl: string,\n integrationDef: sdk.IntegrationDefinition\n ): Promise<void> {\n const devId = await this.projectCache.get('devId')\n\n let integration: client.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 createIntegrationBody = {\n ...(await this.prepareCreateIntegrationBody(integrationDef)),\n ...(await this.prepareIntegrationDependencies(integrationDef, api)),\n url: externalUrl,\n }\n\n if (integration) {\n const updateIntegrationBody = apiUtils.prepareUpdateIntegrationBody(\n { ...createIntegrationBody, 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({ ...createIntegrationBody, 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}\" at \"${externalUrl}\"`)\n line.commit()\n\n await this.projectCache.set('devId', integration.id)\n }\n\n private async _deployDevBot(api: apiUtils.ApiClient, externalUrl: string, botDef: sdk.BotDefinition): Promise<void> {\n const devId = await this.projectCache.get('devId')\n\n let bot: client.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.log('Dev Bot created')\n createLine.commit()\n await this.projectCache.set('devId', bot.id)\n }\n\n const updateBotBody = apiUtils.prepareUpdateBotBody(\n {\n ...(await apiUtils.prepareCreateBotBody(botDef)),\n ...(await this.prepareBotDependencies(botDef, api)),\n id: bot.id,\n url: externalUrl,\n },\n bot\n )\n\n if (!(await this._didDefinitionChange(updateBotBody))) {\n this.logger.log('Skipping deployment step. No changes found in bot.definition.ts')\n return\n }\n const updateLine = this.logger.line()\n updateLine.started('Deploying dev bot...')\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\n this.validateIntegrationRegistration(updatedBot, (failedIntegrations) => {\n throw new errors.BotpressCLIError(\n `Some integrations failed to register:\\n${Object.entries(failedIntegrations)\n .map(([key, int]) => `\u2022 ${key}: ${int.statusReason}`)\n .join('\\n')}`\n )\n })\n\n updateLine.success(`Dev Bot deployed with id \"${updatedBot.id}\" at \"${externalUrl}\"`)\n updateLine.commit()\n\n const tablesPublisher = new tables.TablesPublisher({ api, logger: this.logger, prompt: this.prompt })\n await tablesPublisher.deployTables({ botId: updatedBot.id, botDefinition: botDef })\n\n await this.displayIntegrationUrls({ api, bot: updatedBot })\n }\n\n private async _didDefinitionChange(body: apiUtils.UpdateBotRequestBody | apiUtils.UpdateIntegrationRequestBody) {\n const didChange = !isEqual(body, this._cacheDevRequestBody)\n this._cacheDevRequestBody = { ...body }\n return didChange\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] = String(res[key])\n }\n }\n return headers\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,mBAAyD;AACzD,mBAAkB;AAClB,oBAAwB;AACxB,cAAyB;AACzB,WAAsB;AACtB,eAA0B;
|
|
4
|
+
"sourcesContent": ["import type * as client from '@botpress/client'\nimport type * as sdk from '@botpress/sdk'\nimport { TunnelRequest, TunnelResponse } from '@bpinternal/tunnel'\nimport axios, { AxiosRequestConfig, AxiosResponse } from 'axios'\nimport chalk from 'chalk'\nimport { isEqual } from 'lodash'\nimport * as pathlib from 'path'\nimport * as uuid from 'uuid'\nimport * as apiUtils from '../api'\nimport {\n secretEnvVariableName,\n stripSecretEnvVariablePrefix,\n} from '../code-generation/integration-implementation/integration-secret'\nimport type commandDefinitions from '../command-definitions'\nimport * as errors from '../errors'\nimport * as tables from '../tables'\nimport * as utils from '../utils'\nimport { Worker } from '../worker'\nimport { BuildCommand } from './build-command'\nimport { ProjectCommand, ProjectDefinition } from './project-command'\n\nconst DEFAULT_BOT_PORT = 8075\nconst DEFAULT_INTEGRATION_PORT = 8076\nconst TUNNEL_HELLO_INTERVAL = 5000\nconst FILEWATCHER_DEBOUNCE_MS = 500\n\nexport type DevCommandDefinition = typeof commandDefinitions.dev\nexport class DevCommand extends ProjectCommand<DevCommandDefinition> {\n private _initialDef: ProjectDefinition | undefined = undefined\n private _cacheDevRequestBody: apiUtils.UpdateBotRequestBody | apiUtils.UpdateIntegrationRequestBody | undefined\n private _buildContext: utils.esbuild.BuildCodeContext\n\n public constructor(...args: ConstructorParameters<typeof ProjectCommand<DevCommandDefinition>>) {\n super(...args)\n this._buildContext = new utils.esbuild.BuildCodeContext()\n }\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 const { projectType, resolveProjectDefinition } = this.readProjectDefinitionFromFS()\n if (projectType === 'interface') {\n throw new errors.BotpressCLIError('This feature is not available for interfaces.')\n }\n const projectDef = await resolveProjectDefinition()\n this._initialDef = projectDef\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.type === 'integration') {\n defaultPort = DEFAULT_INTEGRATION_PORT\n const knownSecrets = await this._readKnownSecretsFromCache()\n let secretEnvVariables = await this.promptSecrets(this._initialDef.definition, this.argv, {\n knownSecrets: Object.keys(knownSecrets),\n formatEnv: true,\n })\n secretEnvVariables = { ...this._applyPrefixToSecrets(knownSecrets), ...secretEnvVariables }\n const nonNullSecretEnvVariables = utils.records.filterValues(secretEnvVariables, utils.guards.is.notNull)\n\n if (!this.argv.noSecretCaching) {\n await this._writeKnownSecretsToCache(secretEnvVariables)\n }\n\n env = { ...env, ...nonNullSecretEnvVariables }\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 cachedTunnelId = await this.projectCache.get('tunnelId')\n\n let tunnelId: string\n if (this.argv.tunnelId) {\n tunnelId = this.argv.tunnelId\n } else if (cachedTunnelId) {\n tunnelId = cachedTunnelId\n } else {\n tunnelId = uuid.v4()\n }\n\n if (cachedTunnelId !== tunnelId) {\n await this.projectCache.set('tunnelId', tunnelId)\n }\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(() => {\n if (tunnel.closed) {\n return handleClose()\n }\n tunnel.hello()\n }, TUNNEL_HELLO_INTERVAL)\n const handleClose = (): void => clearInterval(timer)\n tunnel.events.on('close', handleClose)\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\n supervisor.events.on('manuallyClosed', () => {\n this.logger.debug('Tunnel manually closed')\n })\n\n await supervisor.start()\n\n await this._runBuild()\n worker = await this._spawnWorker(env, port)\n await this._deploy(api, httpTunnelUrl)\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\n .filter((e) => !e.path.startsWith(this.projectPaths.abs.outDir))\n .filter((e) => pathlib.extname(e.path) === '.ts')\n\n const distEvents = events.filter((e) => e.path.startsWith(this.projectPaths.abs.distDir))\n\n if (typescriptEvents.length > 0) {\n this.logger.log('Changes detected, rebuilding')\n await this._restart(api, worker, httpTunnelUrl)\n } else if (distEvents.length > 0) {\n this.logger.log('Changes detected in output directory, reloading worker')\n await worker.reload()\n }\n },\n {\n debounceMs: FILEWATCHER_DEBOUNCE_MS,\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: apiUtils.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 worker.reload()\n await this._deploy(api, tunnelUrl)\n }\n\n private _deploy = async (api: apiUtils.ApiClient, tunnelUrl: string) => {\n const { projectType, resolveProjectDefinition } = this.readProjectDefinitionFromFS()\n\n if (projectType === 'interface') {\n throw new errors.BotpressCLIError('This feature is not available for interfaces.')\n }\n if (projectType === 'integration') {\n const projectDef = await resolveProjectDefinition()\n this._checkSecrets(projectDef.definition)\n return await this._deployDevIntegration(api, tunnelUrl, projectDef.definition)\n }\n if (projectType === 'bot') {\n const projectDef = await resolveProjectDefinition()\n return await this._deployDevBot(api, tunnelUrl, projectDef.definition)\n }\n throw new errors.UnsupportedProjectType()\n }\n\n private async _writeKnownSecretsToCache(secretEnvVariables: Record<string, string | null>) {\n const knownSecrets: Record<string, string | null> = {}\n for (const [prefixedSecretName, secretValue] of Object.entries(secretEnvVariables)) {\n const secretName = stripSecretEnvVariablePrefix(prefixedSecretName)\n knownSecrets[secretName] = secretValue\n }\n\n const nonNullKnownSecrets = utils.records.filterValues(knownSecrets, utils.guards.is.notNull)\n if (Object.keys(nonNullKnownSecrets).length === 0) {\n await this.projectCache.rm('secrets')\n return\n }\n await this.projectCache.set('secrets', nonNullKnownSecrets)\n }\n\n private async _readKnownSecretsFromCache() {\n return (await this.projectCache.get('secrets')) ?? {}\n }\n\n private _applyPrefixToSecrets(secrets: Record<string, string>): Record<string, string> {\n const prefixedSecretEntries = Object.entries(secrets).map(([secretName, secretValue]) => [\n secretEnvVariableName(secretName),\n secretValue,\n ])\n return Object.fromEntries(prefixedSecretEntries)\n }\n\n private _checkSecrets(integrationDef: sdk.IntegrationDefinition) {\n if (this._initialDef?.type !== 'integration') {\n return\n }\n const initialSecrets = this._initialDef?.definition.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.outFileCJS\n const importPath = utils.path.toUnix(outfile)\n const code = `require('${importPath}').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)\n .setProjectContext(this.projectContext)\n .run(this._buildContext)\n }\n\n private async _deployDevIntegration(\n api: apiUtils.ApiClient,\n externalUrl: string,\n integrationDef: sdk.IntegrationDefinition\n ): Promise<void> {\n const devId = await this.projectCache.get('devId')\n\n let integration: client.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 createIntegrationBody = {\n ...(await this.prepareCreateIntegrationBody(integrationDef)),\n ...(await this.prepareIntegrationDependencies(integrationDef, api)),\n url: externalUrl,\n }\n\n if (integration) {\n const updateIntegrationBody = apiUtils.prepareUpdateIntegrationBody(\n { ...createIntegrationBody, 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({ ...createIntegrationBody, 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}\" at \"${externalUrl}\"`)\n line.commit()\n\n await this.projectCache.set('devId', integration.id)\n }\n\n private async _deployDevBot(api: apiUtils.ApiClient, externalUrl: string, botDef: sdk.BotDefinition): Promise<void> {\n const devId = await this.projectCache.get('devId')\n\n let bot: client.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.log('Dev Bot created')\n createLine.commit()\n await this.projectCache.set('devId', bot.id)\n }\n\n const updateBotBody = apiUtils.prepareUpdateBotBody(\n {\n ...(await apiUtils.prepareCreateBotBody(botDef)),\n ...(await this.prepareBotDependencies(botDef, api)),\n id: bot.id,\n url: externalUrl,\n },\n bot\n )\n\n if (!(await this._didDefinitionChange(updateBotBody))) {\n this.logger.log('Skipping deployment step. No changes found in bot.definition.ts')\n return\n }\n const updateLine = this.logger.line()\n updateLine.started('Deploying dev bot...')\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\n this.validateIntegrationRegistration(updatedBot, (failedIntegrations) => {\n throw new errors.BotpressCLIError(\n `Some integrations failed to register:\\n${Object.entries(failedIntegrations)\n .map(([key, int]) => `\u2022 ${key}: ${int.statusReason}`)\n .join('\\n')}`\n )\n })\n\n updateLine.success(`Dev Bot deployed with id \"${updatedBot.id}\" at \"${externalUrl}\"`)\n updateLine.commit()\n\n const tablesPublisher = new tables.TablesPublisher({ api, logger: this.logger, prompt: this.prompt })\n await tablesPublisher.deployTables({ botId: updatedBot.id, botDefinition: botDef })\n\n await this.displayIntegrationUrls({ api, bot: updatedBot })\n }\n\n private async _didDefinitionChange(body: apiUtils.UpdateBotRequestBody | apiUtils.UpdateIntegrationRequestBody) {\n const didChange = !isEqual(body, this._cacheDevRequestBody)\n this._cacheDevRequestBody = { ...body }\n return didChange\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] = String(res[key])\n }\n }\n return headers\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["chalk", "axios"]
|
|
7
7
|
}
|
|
@@ -1338,6 +1338,12 @@ declare const _default: {
|
|
|
1338
1338
|
type: "string";
|
|
1339
1339
|
description: string;
|
|
1340
1340
|
};
|
|
1341
|
+
noSecretCaching: {
|
|
1342
|
+
type: "boolean";
|
|
1343
|
+
description: string;
|
|
1344
|
+
default: boolean;
|
|
1345
|
+
alias: string;
|
|
1346
|
+
};
|
|
1341
1347
|
secrets: {
|
|
1342
1348
|
type: "string";
|
|
1343
1349
|
description: string;
|
|
@@ -38,6 +38,10 @@ var import_bot_linter = require("../linter/bot-linter");
|
|
|
38
38
|
var import_integration_linter = require("../linter/integration-linter");
|
|
39
39
|
var import_interface_linter = require("../linter/interface-linter");
|
|
40
40
|
var import_project_command = require("./project-command");
|
|
41
|
+
const _getIssuesDetectedMessage = (linter, nonEmptyPrefix = "") => {
|
|
42
|
+
const message = linter.getIssuesCountBySeverity().map(({ name, count }) => `${count} ${name}(s)`).join(", ");
|
|
43
|
+
return message.length > 0 ? `${nonEmptyPrefix}${message}` : "";
|
|
44
|
+
};
|
|
41
45
|
class LintCommand extends import_project_command.ProjectCommand {
|
|
42
46
|
async run() {
|
|
43
47
|
const { projectType, resolveProjectDefinition } = this.readProjectDefinitionFromFS();
|
|
@@ -76,10 +80,11 @@ class LintCommand extends import_project_command.ProjectCommand {
|
|
|
76
80
|
const linter = new import_interface_linter.InterfaceLinter(parsedInterfaceDefinition, this.logger);
|
|
77
81
|
await linter.lint();
|
|
78
82
|
linter.logResults(this.logger);
|
|
83
|
+
const issueCountsSuffix = _getIssuesDetectedMessage(linter, " - ");
|
|
79
84
|
if (linter.hasErrors()) {
|
|
80
|
-
throw new errors.BotpressCLIError(
|
|
85
|
+
throw new errors.BotpressCLIError(`Interface definition contains linting errors${issueCountsSuffix}`);
|
|
81
86
|
}
|
|
82
|
-
this.logger.success(
|
|
87
|
+
this.logger.success(`Interface definition is valid${issueCountsSuffix}`);
|
|
83
88
|
}
|
|
84
89
|
async _runLintForBot(definition) {
|
|
85
90
|
const strippedDefinition = this._stripAutoGeneratedContentFromBot(definition);
|
|
@@ -87,10 +92,11 @@ class LintCommand extends import_project_command.ProjectCommand {
|
|
|
87
92
|
const linter = new import_bot_linter.BotLinter(parsedBotDefinition, this.logger);
|
|
88
93
|
await linter.lint();
|
|
89
94
|
linter.logResults(this.logger);
|
|
95
|
+
const issueCountsSuffix = _getIssuesDetectedMessage(linter, " - ");
|
|
90
96
|
if (linter.hasErrors()) {
|
|
91
|
-
throw new errors.BotpressCLIError(
|
|
97
|
+
throw new errors.BotpressCLIError(`Bot definition contains linting errors${issueCountsSuffix}`);
|
|
92
98
|
}
|
|
93
|
-
this.logger.success(
|
|
99
|
+
this.logger.success(`Bot definition is valid${issueCountsSuffix}`);
|
|
94
100
|
}
|
|
95
101
|
_stripAutoGeneratedContentFromBot(definition) {
|
|
96
102
|
return {
|
|
@@ -107,10 +113,11 @@ class LintCommand extends import_project_command.ProjectCommand {
|
|
|
107
113
|
);
|
|
108
114
|
await linter.lint();
|
|
109
115
|
linter.logResults(this.logger);
|
|
116
|
+
const issueCountsSuffix = _getIssuesDetectedMessage(linter, " - ");
|
|
110
117
|
if (linter.hasErrors()) {
|
|
111
|
-
throw new errors.BotpressCLIError(
|
|
118
|
+
throw new errors.BotpressCLIError(`Integration definition contains linting errors${issueCountsSuffix}`);
|
|
112
119
|
}
|
|
113
|
-
this.logger.success(
|
|
120
|
+
this.logger.success(`Integration definition is valid${issueCountsSuffix}`);
|
|
114
121
|
}
|
|
115
122
|
_stripAutoGeneratedContentFromIntegration(definition) {
|
|
116
123
|
const { actionNames, eventNames } = this._getAutoGeneratedContentOfIntegration(definition);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/command-implementations/lint-command.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n type IntegrationDefinition,\n type BotDefinition,\n type InterfaceDefinition,\n ActionDefinition,\n z,\n EventDefinition,\n} from '@botpress/sdk'\nimport * as apiUtils from '../api'\nimport type commandDefinitions from '../command-definitions'\nimport * as errors from '../errors'\nimport { BotLinter } from '../linter/bot-linter'\nimport { IntegrationLinter } from '../linter/integration-linter'\nimport { InterfaceLinter } from '../linter/interface-linter'\nimport { ProjectCommand } from './project-command'\n\nexport type LintCommandDefinition = typeof commandDefinitions.lint\nexport class LintCommand extends ProjectCommand<LintCommandDefinition> {\n public async run(): Promise<void> {\n const { projectType, resolveProjectDefinition } = this.readProjectDefinitionFromFS()\n const projectDef = await resolveProjectDefinition()\n if (projectDef.bpLintDisabled) {\n this.logger.warn(\n 'Linting is disabled for this project because of a bplint directive. To enable linting, remove the \"bplint-disable\" directive from the project definition file'\n )\n return\n }\n\n switch (projectType) {\n case 'integration': {\n const projectDef = await resolveProjectDefinition()\n return this._runLintForIntegration(projectDef.definition)\n }\n case 'bot': {\n const projectDef = await resolveProjectDefinition()\n return this._runLintForBot(projectDef.definition)\n }\n case 'interface': {\n const projectDef = await resolveProjectDefinition()\n return this._runLintForInterface(projectDef.definition)\n }\n default:\n throw new errors.UnsupportedProjectType()\n }\n }\n\n private async _runLintForInterface(definition: InterfaceDefinition): Promise<void> {\n for (const [actionName, actionDef] of Object.entries(definition.actions)) {\n definition.actions[actionName] = this._dereferenceActionDefinition(actionDef)\n }\n\n for (const [eventName, eventDef] of Object.entries(definition.events)) {\n definition.events[eventName] = this._dereferenceEventDefinition(eventDef)\n }\n\n const parsedInterfaceDefinition = await apiUtils.prepareCreateInterfaceBody(definition)\n const linter = new InterfaceLinter(parsedInterfaceDefinition, this.logger)\n\n await linter.lint()\n linter.logResults(this.logger)\n\n if (linter.hasErrors()) {\n throw new errors.BotpressCLIError(
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAOO;AACP,eAA0B;AAE1B,aAAwB;
|
|
4
|
+
"sourcesContent": ["import {\n type IntegrationDefinition,\n type BotDefinition,\n type InterfaceDefinition,\n ActionDefinition,\n z,\n EventDefinition,\n} from '@botpress/sdk'\nimport * as apiUtils from '../api'\nimport type commandDefinitions from '../command-definitions'\nimport * as errors from '../errors'\nimport { BaseLinter } from '../linter/base-linter'\nimport { BotLinter } from '../linter/bot-linter'\nimport { IntegrationLinter } from '../linter/integration-linter'\nimport { InterfaceLinter } from '../linter/interface-linter'\nimport { ProjectCommand } from './project-command'\n\nconst _getIssuesDetectedMessage = (linter: BaseLinter<unknown>, nonEmptyPrefix: string = '') => {\n const message = linter\n .getIssuesCountBySeverity()\n .map(({ name, count }) => `${count} ${name}(s)`)\n .join(', ')\n\n return message.length > 0 ? `${nonEmptyPrefix}${message}` : ''\n}\n\nexport type LintCommandDefinition = typeof commandDefinitions.lint\nexport class LintCommand extends ProjectCommand<LintCommandDefinition> {\n public async run(): Promise<void> {\n const { projectType, resolveProjectDefinition } = this.readProjectDefinitionFromFS()\n const projectDef = await resolveProjectDefinition()\n if (projectDef.bpLintDisabled) {\n this.logger.warn(\n 'Linting is disabled for this project because of a bplint directive. To enable linting, remove the \"bplint-disable\" directive from the project definition file'\n )\n return\n }\n\n switch (projectType) {\n case 'integration': {\n const projectDef = await resolveProjectDefinition()\n return this._runLintForIntegration(projectDef.definition)\n }\n case 'bot': {\n const projectDef = await resolveProjectDefinition()\n return this._runLintForBot(projectDef.definition)\n }\n case 'interface': {\n const projectDef = await resolveProjectDefinition()\n return this._runLintForInterface(projectDef.definition)\n }\n default:\n throw new errors.UnsupportedProjectType()\n }\n }\n\n private async _runLintForInterface(definition: InterfaceDefinition): Promise<void> {\n for (const [actionName, actionDef] of Object.entries(definition.actions)) {\n definition.actions[actionName] = this._dereferenceActionDefinition(actionDef)\n }\n\n for (const [eventName, eventDef] of Object.entries(definition.events)) {\n definition.events[eventName] = this._dereferenceEventDefinition(eventDef)\n }\n\n const parsedInterfaceDefinition = await apiUtils.prepareCreateInterfaceBody(definition)\n const linter = new InterfaceLinter(parsedInterfaceDefinition, this.logger)\n\n await linter.lint()\n linter.logResults(this.logger)\n\n const issueCountsSuffix = _getIssuesDetectedMessage(linter, ' - ')\n\n if (linter.hasErrors()) {\n throw new errors.BotpressCLIError(`Interface definition contains linting errors${issueCountsSuffix}`)\n }\n\n this.logger.success(`Interface definition is valid${issueCountsSuffix}`)\n }\n\n private async _runLintForBot(definition: BotDefinition): Promise<void> {\n const strippedDefinition = this._stripAutoGeneratedContentFromBot(definition)\n const parsedBotDefinition = await apiUtils.prepareCreateBotBody(strippedDefinition)\n const linter = new BotLinter(parsedBotDefinition, this.logger)\n\n await linter.lint()\n linter.logResults(this.logger)\n\n const issueCountsSuffix = _getIssuesDetectedMessage(linter, ' - ')\n\n if (linter.hasErrors()) {\n throw new errors.BotpressCLIError(`Bot definition contains linting errors${issueCountsSuffix}`)\n }\n\n this.logger.success(`Bot definition is valid${issueCountsSuffix}`)\n }\n\n private _stripAutoGeneratedContentFromBot(definition: BotDefinition) {\n return {\n ...definition,\n integrations: {},\n } as BotDefinition\n }\n\n private async _runLintForIntegration(definition: IntegrationDefinition): Promise<void> {\n const strippedDefinition = this._stripAutoGeneratedContentFromIntegration(definition)\n const parsedIntegrationDefinition = await this.prepareCreateIntegrationBody(strippedDefinition)\n const linter = new IntegrationLinter(\n { ...parsedIntegrationDefinition, secrets: strippedDefinition.secrets },\n this.logger\n )\n\n await linter.lint()\n linter.logResults(this.logger)\n\n const issueCountsSuffix = _getIssuesDetectedMessage(linter, ' - ')\n\n if (linter.hasErrors()) {\n throw new errors.BotpressCLIError(`Integration definition contains linting errors${issueCountsSuffix}`)\n }\n\n this.logger.success(`Integration definition is valid${issueCountsSuffix}`)\n }\n\n private _stripAutoGeneratedContentFromIntegration(definition: IntegrationDefinition) {\n const { actionNames, eventNames } = this._getAutoGeneratedContentOfIntegration(definition)\n\n return {\n ...definition,\n actions: Object.fromEntries(Object.entries(definition.actions ?? {}).filter(([key]) => !actionNames.has(key))),\n events: Object.fromEntries(Object.entries(definition.events ?? {}).filter(([key]) => !eventNames.has(key))),\n } as IntegrationDefinition\n }\n\n private _getAutoGeneratedContentOfIntegration(definition: IntegrationDefinition) {\n const actionNames = new Set<string>()\n const eventNames = new Set<string>()\n\n const interfacesStatements = definition.interfaces ?? {}\n for (const iface of Object.values(interfacesStatements)) {\n for (const actionDefinition of Object.values(iface.actions)) {\n actionNames.add(actionDefinition.name)\n }\n for (const eventDefinition of Object.values(iface.events)) {\n eventNames.add(eventDefinition.name)\n }\n }\n\n return { actionNames, eventNames } as const\n }\n\n private _dereferenceActionDefinition = (actionDef: ActionDefinition): ActionDefinition => {\n const inputRefs = actionDef.input.schema.getReferences()\n const outputRefs = actionDef.output.schema.getReferences()\n\n const inputRefSchemas = Object.fromEntries(inputRefs.map((ref) => [ref, this._replaceRef(ref)]))\n const outputRefSchemas = Object.fromEntries(outputRefs.map((ref) => [ref, this._replaceRef(ref)]))\n\n actionDef.input.schema = actionDef.input.schema.dereference(inputRefSchemas) as z.ZodObject\n actionDef.output.schema = actionDef.output.schema.dereference(outputRefSchemas) as z.ZodObject\n\n return actionDef\n }\n\n private _dereferenceEventDefinition = (eventDef: EventDefinition): EventDefinition => {\n const refs = eventDef.schema.getReferences()\n\n const refSchemas = Object.fromEntries(refs.map((ref) => [ref, this._replaceRef(ref)]))\n\n eventDef.schema = eventDef.schema.dereference(refSchemas) as z.ZodObject\n\n return eventDef\n }\n\n private _replaceRef = (refUri: string): z.ZodObject => z.object({}).title(refUri).describe(refUri)\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["projectDef"]
|
|
7
7
|
}
|