@botpress/cli 0.5.2 → 0.5.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.
Files changed (33) hide show
  1. package/dist/api/bot-body.js +17 -0
  2. package/dist/api/bot-body.js.map +2 -2
  3. package/dist/api/client.js +3 -3
  4. package/dist/api/client.js.map +2 -2
  5. package/dist/api/integration-body.js +36 -0
  6. package/dist/api/integration-body.js.map +2 -2
  7. package/dist/code-generation/index.js.map +1 -1
  8. package/dist/code-generation/map-integration.js.map +2 -2
  9. package/dist/command-implementations/add-command.js.map +2 -2
  10. package/dist/command-implementations/deploy-command.js +10 -8
  11. package/dist/command-implementations/deploy-command.js.map +2 -2
  12. package/dist/command-implementations/dev-command.js +9 -7
  13. package/dist/command-implementations/dev-command.js.map +2 -2
  14. package/dist/command-implementations/integration-commands.js.map +1 -1
  15. package/dist/command-implementations/login-command.js +2 -2
  16. package/dist/command-implementations/login-command.js.map +2 -2
  17. package/dist/command-implementations/project-command.js +9 -69
  18. package/dist/command-implementations/project-command.js.map +2 -2
  19. package/dist/command-implementations/serve-command.js +2 -1
  20. package/dist/command-implementations/serve-command.js.map +2 -2
  21. package/dist/sdk/validate-integration.js +68 -0
  22. package/dist/sdk/validate-integration.js.map +7 -0
  23. package/dist/utils/guard-utils.js +2 -1
  24. package/dist/utils/guard-utils.js.map +2 -2
  25. package/dist/utils/index.js +3 -0
  26. package/dist/utils/index.js.map +2 -2
  27. package/dist/utils/record-utils.js +12 -1
  28. package/dist/utils/record-utils.js.map +2 -2
  29. package/dist/utils/string-utils.js +35 -0
  30. package/dist/utils/string-utils.js.map +7 -0
  31. package/package.json +3 -3
  32. package/templates/echo-bot/package.json +2 -2
  33. package/templates/empty-integration/package.json +2 -2
@@ -24,10 +24,26 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
25
25
  var bot_body_exports = {};
26
26
  __export(bot_body_exports, {
27
+ prepareCreateBotBody: () => prepareCreateBotBody,
27
28
  prepareUpdateBotBody: () => prepareUpdateBotBody
28
29
  });
29
30
  module.exports = __toCommonJS(bot_body_exports);
30
31
  var utils = __toESM(require("../utils"));
32
+ const prepareCreateBotBody = (bot) => ({
33
+ ...bot.props,
34
+ configuration: bot.props.configuration ? {
35
+ ...bot.props.configuration,
36
+ schema: utils.schema.mapZodToJsonSchema(bot.props.configuration)
37
+ } : void 0,
38
+ events: bot.props.events ? utils.records.mapValues(bot.props.events, (event) => ({
39
+ ...event,
40
+ schema: utils.schema.mapZodToJsonSchema(event)
41
+ })) : void 0,
42
+ states: bot.props.states ? utils.records.mapValues(bot.props.states, (state) => ({
43
+ ...state,
44
+ schema: utils.schema.mapZodToJsonSchema(state)
45
+ })) : void 0
46
+ });
31
47
  const prepareUpdateBotBody = (localBot, remoteBot) => ({
32
48
  ...localBot,
33
49
  states: utils.records.setNullOnMissingValues(localBot.states, remoteBot.states),
@@ -49,6 +65,7 @@ const prepareUpdateBotBody = (localBot, remoteBot) => ({
49
65
  });
50
66
  // Annotate the CommonJS export names for ESM import in node:
51
67
  0 && (module.exports = {
68
+ prepareCreateBotBody,
52
69
  prepareUpdateBotBody
53
70
  });
54
71
  //# sourceMappingURL=bot-body.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/api/bot-body.ts"],
4
- "sourcesContent": ["import type * as bpclient from '@botpress/client'\nimport * as utils from '../utils'\n\nexport type CreateBotBody = Parameters<bpclient.Client['createBot']>[0]\nexport type UpdateBotBody = Parameters<bpclient.Client['updateBot']>[0]\n\nexport const prepareUpdateBotBody = (localBot: UpdateBotBody, remoteBot: bpclient.Bot): UpdateBotBody => ({\n ...localBot,\n states: utils.records.setNullOnMissingValues(localBot.states, remoteBot.states),\n recurringEvents: utils.records.setNullOnMissingValues(localBot.recurringEvents, remoteBot.recurringEvents),\n events: utils.records.setNullOnMissingValues(localBot.events, remoteBot.events),\n user: {\n ...localBot.user,\n tags: utils.records.setNullOnMissingValues(localBot.user?.tags, remoteBot.user?.tags),\n },\n conversation: {\n ...localBot.conversation,\n tags: utils.records.setNullOnMissingValues(localBot.conversation?.tags, remoteBot.conversation?.tags),\n },\n message: {\n ...localBot.message,\n tags: utils.records.setNullOnMissingValues(localBot.message?.tags, remoteBot.message?.tags),\n },\n integrations: utils.records.setNullOnMissingValues(localBot.integrations, remoteBot.integrations),\n})\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AAKhB,MAAM,uBAAuB,CAAC,UAAyB,eAA4C;AAAA,EACxG,GAAG;AAAA,EACH,QAAQ,MAAM,QAAQ,uBAAuB,SAAS,QAAQ,UAAU,MAAM;AAAA,EAC9E,iBAAiB,MAAM,QAAQ,uBAAuB,SAAS,iBAAiB,UAAU,eAAe;AAAA,EACzG,QAAQ,MAAM,QAAQ,uBAAuB,SAAS,QAAQ,UAAU,MAAM;AAAA,EAC9E,MAAM;AAAA,IACJ,GAAG,SAAS;AAAA,IACZ,MAAM,MAAM,QAAQ,uBAAuB,SAAS,MAAM,MAAM,UAAU,MAAM,IAAI;AAAA,EACtF;AAAA,EACA,cAAc;AAAA,IACZ,GAAG,SAAS;AAAA,IACZ,MAAM,MAAM,QAAQ,uBAAuB,SAAS,cAAc,MAAM,UAAU,cAAc,IAAI;AAAA,EACtG;AAAA,EACA,SAAS;AAAA,IACP,GAAG,SAAS;AAAA,IACZ,MAAM,MAAM,QAAQ,uBAAuB,SAAS,SAAS,MAAM,UAAU,SAAS,IAAI;AAAA,EAC5F;AAAA,EACA,cAAc,MAAM,QAAQ,uBAAuB,SAAS,cAAc,UAAU,YAAY;AAClG;",
4
+ "sourcesContent": ["import type * as client from '@botpress/client'\nimport type * as sdk from '@botpress/sdk'\nimport * as utils from '../utils'\n\nexport type CreateBotBody = Parameters<client.Client['createBot']>[0]\nexport type UpdateBotBody = Parameters<client.Client['updateBot']>[0]\n\nexport const prepareCreateBotBody = (bot: sdk.Bot): CreateBotBody => ({\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 ? utils.records.mapValues(bot.props.events, (event) => ({\n ...event,\n schema: utils.schema.mapZodToJsonSchema(event),\n }))\n : undefined,\n states: bot.props.states\n ? utils.records.mapValues(bot.props.states, (state) => ({\n ...state,\n schema: utils.schema.mapZodToJsonSchema(state),\n }))\n : undefined,\n})\n\nexport const prepareUpdateBotBody = (localBot: UpdateBotBody, remoteBot: client.Bot): UpdateBotBody => ({\n ...localBot,\n states: utils.records.setNullOnMissingValues(localBot.states, remoteBot.states),\n recurringEvents: utils.records.setNullOnMissingValues(localBot.recurringEvents, remoteBot.recurringEvents),\n events: utils.records.setNullOnMissingValues(localBot.events, remoteBot.events),\n user: {\n ...localBot.user,\n tags: utils.records.setNullOnMissingValues(localBot.user?.tags, remoteBot.user?.tags),\n },\n conversation: {\n ...localBot.conversation,\n tags: utils.records.setNullOnMissingValues(localBot.conversation?.tags, remoteBot.conversation?.tags),\n },\n message: {\n ...localBot.message,\n tags: utils.records.setNullOnMissingValues(localBot.message?.tags, remoteBot.message?.tags),\n },\n integrations: utils.records.setNullOnMissingValues(localBot.integrations, remoteBot.integrations),\n})\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,YAAuB;AAKhB,MAAM,uBAAuB,CAAC,SAAiC;AAAA,EACpE,GAAG,IAAI;AAAA,EACP,eAAe,IAAI,MAAM,gBACrB;AAAA,IACE,GAAG,IAAI,MAAM;AAAA,IACb,QAAQ,MAAM,OAAO,mBAAmB,IAAI,MAAM,aAAa;AAAA,EACjE,IACA;AAAA,EACJ,QAAQ,IAAI,MAAM,SACd,MAAM,QAAQ,UAAU,IAAI,MAAM,QAAQ,CAAC,WAAW;AAAA,IACpD,GAAG;AAAA,IACH,QAAQ,MAAM,OAAO,mBAAmB,KAAK;AAAA,EAC/C,EAAE,IACF;AAAA,EACJ,QAAQ,IAAI,MAAM,SACd,MAAM,QAAQ,UAAU,IAAI,MAAM,QAAQ,CAAC,WAAW;AAAA,IACpD,GAAG;AAAA,IACH,QAAQ,MAAM,OAAO,mBAAmB,KAAK;AAAA,EAC/C,EAAE,IACF;AACN;AAEO,MAAM,uBAAuB,CAAC,UAAyB,eAA0C;AAAA,EACtG,GAAG;AAAA,EACH,QAAQ,MAAM,QAAQ,uBAAuB,SAAS,QAAQ,UAAU,MAAM;AAAA,EAC9E,iBAAiB,MAAM,QAAQ,uBAAuB,SAAS,iBAAiB,UAAU,eAAe;AAAA,EACzG,QAAQ,MAAM,QAAQ,uBAAuB,SAAS,QAAQ,UAAU,MAAM;AAAA,EAC9E,MAAM;AAAA,IACJ,GAAG,SAAS;AAAA,IACZ,MAAM,MAAM,QAAQ,uBAAuB,SAAS,MAAM,MAAM,UAAU,MAAM,IAAI;AAAA,EACtF;AAAA,EACA,cAAc;AAAA,IACZ,GAAG,SAAS;AAAA,IACZ,MAAM,MAAM,QAAQ,uBAAuB,SAAS,cAAc,MAAM,UAAU,cAAc,IAAI;AAAA,EACtG;AAAA,EACA,SAAS;AAAA,IACP,GAAG,SAAS;AAAA,IACZ,MAAM,MAAM,QAAQ,uBAAuB,SAAS,SAAS,MAAM,UAAU,SAAS,IAAI;AAAA,EAC5F;AAAA,EACA,cAAc,MAAM,QAAQ,uBAAuB,SAAS,cAAc,UAAU,YAAY;AAClG;",
6
6
  "names": []
7
7
  }
@@ -27,7 +27,7 @@ __export(client_exports, {
27
27
  ApiClient: () => ApiClient
28
28
  });
29
29
  module.exports = __toCommonJS(client_exports);
30
- var bpclient = __toESM(require("@botpress/client"));
30
+ var client = __toESM(require("@botpress/client"));
31
31
  var import_lodash = __toESM(require("lodash"));
32
32
  var import_integration_ref = require("../integration-ref");
33
33
  var paging = __toESM(require("./paging"));
@@ -35,7 +35,7 @@ class ApiClient {
35
35
  constructor(props, _logger) {
36
36
  this._logger = _logger;
37
37
  const { apiUrl, token, workspaceId } = props;
38
- this.client = new bpclient.Client({ apiUrl, token, workspaceId });
38
+ this.client = new client.Client({ apiUrl, token, workspaceId });
39
39
  this.url = apiUrl;
40
40
  this.token = token;
41
41
  this.workspaceId = workspaceId;
@@ -88,7 +88,7 @@ class ApiClient {
88
88
  return v;
89
89
  } catch (err) {
90
90
  const allowedStatusesArray = import_lodash.default.isArray(allowedStatuses) ? allowedStatuses : [allowedStatuses];
91
- const isAllowed = bpclient.isApiError(err) && err.code && allowedStatusesArray.includes(err.code);
91
+ const isAllowed = client.isApiError(err) && err.code && allowedStatusesArray.includes(err.code);
92
92
  if (isAllowed) {
93
93
  return;
94
94
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/api/client.ts"],
4
- "sourcesContent": ["import * as bpclient from '@botpress/client'\nimport _ from 'lodash'\nimport { formatIntegrationRef, ApiIntegrationRef as IntegrationRef } from '../integration-ref'\nimport type { Logger } from '../logger'\nimport * as paging from './paging'\n\nexport type PageLister<R extends object> = (t: { nextToken?: string }) => Promise<R & { meta: { nextToken?: string } }>\n\nexport type ApiClientProps = {\n apiUrl: string\n token: string\n workspaceId: string\n}\n\nexport type ApiClientFactory = {\n newClient: (props: ApiClientProps, logger: Logger) => ApiClient\n}\n\ntype PublicIntegration = bpclient.Integration\ntype PrivateIntegration = bpclient.Integration & { workspaceId: string }\ntype Integration = bpclient.Integration & { workspaceId?: string }\n\n/**\n * This class is used to wrap the Botpress API and provide a more convenient way to interact with it.\n */\nexport class ApiClient {\n public readonly client: bpclient.Client\n public readonly url: string\n public readonly token: string\n public readonly workspaceId: string\n\n public static newClient = (props: ApiClientProps, logger: Logger) => new ApiClient(props, logger)\n\n public constructor(props: ApiClientProps, private _logger: Logger) {\n const { apiUrl, token, workspaceId } = props\n this.client = new bpclient.Client({ apiUrl, token, workspaceId })\n this.url = apiUrl\n this.token = token\n this.workspaceId = workspaceId\n }\n\n public async findIntegration(ref: IntegrationRef): Promise<Integration | undefined> {\n const formatted = formatIntegrationRef(ref)\n\n const privateIntegration = await this.findPrivateIntegration(ref)\n if (privateIntegration) {\n this._logger.debug(`Found integration \"${formatted}\" in workspace`)\n return privateIntegration\n }\n\n const publicIntegration = await this.findPublicIntegration(ref)\n if (publicIntegration) {\n this._logger.debug(`Found integration \"${formatted}\" in hub`)\n return publicIntegration\n }\n\n return\n }\n\n public async findPrivateIntegration(ref: IntegrationRef): Promise<PrivateIntegration | undefined> {\n const { workspaceId } = this\n if (ref.type === 'id') {\n return this.validateStatus(\n () => this.client.getIntegration(ref).then((r) => ({ ...r.integration, workspaceId })),\n 404\n )\n }\n return this.validateStatus(\n () => this.client.getIntegrationByName(ref).then((r) => ({ ...r.integration, workspaceId })),\n 404\n )\n }\n\n public async findPublicIntegration(ref: IntegrationRef): Promise<PublicIntegration | undefined> {\n if (ref.type === 'id') {\n return this.validateStatus(() => this.client.getPublicIntegrationById(ref).then((r) => r.integration), 404)\n }\n return this.validateStatus(() => this.client.getPublicIntegration(ref).then((r) => r.integration), 404)\n }\n\n public async testLogin(): Promise<void> {\n await this.client.listBots({})\n }\n\n public listAllPages = paging.listAllPages\n\n public async validateStatus<V>(fn: () => Promise<V>, allowedStatuses: number | number[]): Promise<V | undefined> {\n try {\n const v = await fn()\n return v\n } catch (err) {\n const allowedStatusesArray = _.isArray(allowedStatuses) ? allowedStatuses : [allowedStatuses]\n const isAllowed = bpclient.isApiError(err) && err.code && allowedStatusesArray.includes(err.code)\n if (isAllowed) {\n return\n }\n throw err\n }\n }\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,eAA0B;AAC1B,oBAAc;AACd,6BAA0E;AAE1E,aAAwB;AAqBjB,MAAM,UAAU;AAAA,EAQd,YAAY,OAA+B,SAAiB;AAAjB;AAChD,UAAM,EAAE,QAAQ,OAAO,YAAY,IAAI;AACvC,SAAK,SAAS,IAAI,SAAS,OAAO,EAAE,QAAQ,OAAO,YAAY,CAAC;AAChE,SAAK,MAAM;AACX,SAAK,QAAQ;AACb,SAAK,cAAc;AAAA,EACrB;AAAA,EAbgB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEhB,OAAc,YAAY,CAAC,OAAuB,WAAmB,IAAI,UAAU,OAAO,MAAM;AAAA,EAUhG,MAAa,gBAAgB,KAAuD;AAClF,UAAM,gBAAY,6CAAqB,GAAG;AAE1C,UAAM,qBAAqB,MAAM,KAAK,uBAAuB,GAAG;AAChE,QAAI,oBAAoB;AACtB,WAAK,QAAQ,MAAM,sBAAsB,yBAAyB;AAClE,aAAO;AAAA,IACT;AAEA,UAAM,oBAAoB,MAAM,KAAK,sBAAsB,GAAG;AAC9D,QAAI,mBAAmB;AACrB,WAAK,QAAQ,MAAM,sBAAsB,mBAAmB;AAC5D,aAAO;AAAA,IACT;AAEA;AAAA,EACF;AAAA,EAEA,MAAa,uBAAuB,KAA8D;AAChG,UAAM,EAAE,YAAY,IAAI;AACxB,QAAI,IAAI,SAAS,MAAM;AACrB,aAAO,KAAK;AAAA,QACV,MAAM,KAAK,OAAO,eAAe,GAAG,EAAE,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,aAAa,YAAY,EAAE;AAAA,QACrF;AAAA,MACF;AAAA,IACF;AACA,WAAO,KAAK;AAAA,MACV,MAAM,KAAK,OAAO,qBAAqB,GAAG,EAAE,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,aAAa,YAAY,EAAE;AAAA,MAC3F;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAa,sBAAsB,KAA6D;AAC9F,QAAI,IAAI,SAAS,MAAM;AACrB,aAAO,KAAK,eAAe,MAAM,KAAK,OAAO,yBAAyB,GAAG,EAAE,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,GAAG;AAAA,IAC5G;AACA,WAAO,KAAK,eAAe,MAAM,KAAK,OAAO,qBAAqB,GAAG,EAAE,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,GAAG;AAAA,EACxG;AAAA,EAEA,MAAa,YAA2B;AACtC,UAAM,KAAK,OAAO,SAAS,CAAC,CAAC;AAAA,EAC/B;AAAA,EAEO,eAAe,OAAO;AAAA,EAE7B,MAAa,eAAkB,IAAsB,iBAA4D;AAC/G,QAAI;AACF,YAAM,IAAI,MAAM,GAAG;AACnB,aAAO;AAAA,IACT,SAAS,KAAP;AACA,YAAM,uBAAuB,cAAAA,QAAE,QAAQ,eAAe,IAAI,kBAAkB,CAAC,eAAe;AAC5F,YAAM,YAAY,SAAS,WAAW,GAAG,KAAK,IAAI,QAAQ,qBAAqB,SAAS,IAAI,IAAI;AAChG,UAAI,WAAW;AACb;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACF;",
4
+ "sourcesContent": ["import * as client from '@botpress/client'\nimport _ from 'lodash'\nimport { formatIntegrationRef, ApiIntegrationRef as IntegrationRef } from '../integration-ref'\nimport type { Logger } from '../logger'\nimport * as paging from './paging'\n\nexport type PageLister<R extends object> = (t: { nextToken?: string }) => Promise<R & { meta: { nextToken?: string } }>\n\nexport type ApiClientProps = {\n apiUrl: string\n token: string\n workspaceId: string\n}\n\nexport type ApiClientFactory = {\n newClient: (props: ApiClientProps, logger: Logger) => ApiClient\n}\n\ntype PublicIntegration = client.Integration\ntype PrivateIntegration = client.Integration & { workspaceId: string }\ntype Integration = client.Integration & { workspaceId?: string }\n\n/**\n * This class is used to wrap the Botpress API and provide a more convenient way to interact with it.\n */\nexport class ApiClient {\n public readonly client: client.Client\n public readonly url: string\n public readonly token: string\n public readonly workspaceId: string\n\n public static newClient = (props: ApiClientProps, logger: Logger) => new ApiClient(props, logger)\n\n public constructor(props: ApiClientProps, private _logger: Logger) {\n const { apiUrl, token, workspaceId } = props\n this.client = new client.Client({ apiUrl, token, workspaceId })\n this.url = apiUrl\n this.token = token\n this.workspaceId = workspaceId\n }\n\n public async findIntegration(ref: IntegrationRef): Promise<Integration | undefined> {\n const formatted = formatIntegrationRef(ref)\n\n const privateIntegration = await this.findPrivateIntegration(ref)\n if (privateIntegration) {\n this._logger.debug(`Found integration \"${formatted}\" in workspace`)\n return privateIntegration\n }\n\n const publicIntegration = await this.findPublicIntegration(ref)\n if (publicIntegration) {\n this._logger.debug(`Found integration \"${formatted}\" in hub`)\n return publicIntegration\n }\n\n return\n }\n\n public async findPrivateIntegration(ref: IntegrationRef): Promise<PrivateIntegration | undefined> {\n const { workspaceId } = this\n if (ref.type === 'id') {\n return this.validateStatus(\n () => this.client.getIntegration(ref).then((r) => ({ ...r.integration, workspaceId })),\n 404\n )\n }\n return this.validateStatus(\n () => this.client.getIntegrationByName(ref).then((r) => ({ ...r.integration, workspaceId })),\n 404\n )\n }\n\n public async findPublicIntegration(ref: IntegrationRef): Promise<PublicIntegration | undefined> {\n if (ref.type === 'id') {\n return this.validateStatus(() => this.client.getPublicIntegrationById(ref).then((r) => r.integration), 404)\n }\n return this.validateStatus(() => this.client.getPublicIntegration(ref).then((r) => r.integration), 404)\n }\n\n public async testLogin(): Promise<void> {\n await this.client.listBots({})\n }\n\n public listAllPages = paging.listAllPages\n\n public async validateStatus<V>(fn: () => Promise<V>, allowedStatuses: number | number[]): Promise<V | undefined> {\n try {\n const v = await fn()\n return v\n } catch (err) {\n const allowedStatusesArray = _.isArray(allowedStatuses) ? allowedStatuses : [allowedStatuses]\n const isAllowed = client.isApiError(err) && err.code && allowedStatusesArray.includes(err.code)\n if (isAllowed) {\n return\n }\n throw err\n }\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,aAAwB;AACxB,oBAAc;AACd,6BAA0E;AAE1E,aAAwB;AAqBjB,MAAM,UAAU;AAAA,EAQd,YAAY,OAA+B,SAAiB;AAAjB;AAChD,UAAM,EAAE,QAAQ,OAAO,YAAY,IAAI;AACvC,SAAK,SAAS,IAAI,OAAO,OAAO,EAAE,QAAQ,OAAO,YAAY,CAAC;AAC9D,SAAK,MAAM;AACX,SAAK,QAAQ;AACb,SAAK,cAAc;AAAA,EACrB;AAAA,EAbgB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAEhB,OAAc,YAAY,CAAC,OAAuB,WAAmB,IAAI,UAAU,OAAO,MAAM;AAAA,EAUhG,MAAa,gBAAgB,KAAuD;AAClF,UAAM,gBAAY,6CAAqB,GAAG;AAE1C,UAAM,qBAAqB,MAAM,KAAK,uBAAuB,GAAG;AAChE,QAAI,oBAAoB;AACtB,WAAK,QAAQ,MAAM,sBAAsB,yBAAyB;AAClE,aAAO;AAAA,IACT;AAEA,UAAM,oBAAoB,MAAM,KAAK,sBAAsB,GAAG;AAC9D,QAAI,mBAAmB;AACrB,WAAK,QAAQ,MAAM,sBAAsB,mBAAmB;AAC5D,aAAO;AAAA,IACT;AAEA;AAAA,EACF;AAAA,EAEA,MAAa,uBAAuB,KAA8D;AAChG,UAAM,EAAE,YAAY,IAAI;AACxB,QAAI,IAAI,SAAS,MAAM;AACrB,aAAO,KAAK;AAAA,QACV,MAAM,KAAK,OAAO,eAAe,GAAG,EAAE,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,aAAa,YAAY,EAAE;AAAA,QACrF;AAAA,MACF;AAAA,IACF;AACA,WAAO,KAAK;AAAA,MACV,MAAM,KAAK,OAAO,qBAAqB,GAAG,EAAE,KAAK,CAAC,OAAO,EAAE,GAAG,EAAE,aAAa,YAAY,EAAE;AAAA,MAC3F;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAa,sBAAsB,KAA6D;AAC9F,QAAI,IAAI,SAAS,MAAM;AACrB,aAAO,KAAK,eAAe,MAAM,KAAK,OAAO,yBAAyB,GAAG,EAAE,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,GAAG;AAAA,IAC5G;AACA,WAAO,KAAK,eAAe,MAAM,KAAK,OAAO,qBAAqB,GAAG,EAAE,KAAK,CAAC,MAAM,EAAE,WAAW,GAAG,GAAG;AAAA,EACxG;AAAA,EAEA,MAAa,YAA2B;AACtC,UAAM,KAAK,OAAO,SAAS,CAAC,CAAC;AAAA,EAC/B;AAAA,EAEO,eAAe,OAAO;AAAA,EAE7B,MAAa,eAAkB,IAAsB,iBAA4D;AAC/G,QAAI;AACF,YAAM,IAAI,MAAM,GAAG;AACnB,aAAO;AAAA,IACT,SAAS,KAAP;AACA,YAAM,uBAAuB,cAAAA,QAAE,QAAQ,eAAe,IAAI,kBAAkB,CAAC,eAAe;AAC5F,YAAM,YAAY,OAAO,WAAW,GAAG,KAAK,IAAI,QAAQ,qBAAqB,SAAS,IAAI,IAAI;AAC9F,UAAI,WAAW;AACb;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACF;",
6
6
  "names": ["_"]
7
7
  }
@@ -24,10 +24,45 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
24
24
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
25
25
  var integration_body_exports = {};
26
26
  __export(integration_body_exports, {
27
+ prepareCreateIntegrationBody: () => prepareCreateIntegrationBody,
27
28
  prepareUpdateIntegrationBody: () => prepareUpdateIntegrationBody
28
29
  });
29
30
  module.exports = __toCommonJS(integration_body_exports);
30
31
  var utils = __toESM(require("../utils"));
32
+ const prepareCreateIntegrationBody = (integration) => ({
33
+ ...integration,
34
+ secrets: void 0,
35
+ configuration: integration.configuration ? {
36
+ ...integration.configuration,
37
+ schema: utils.schema.mapZodToJsonSchema(integration.configuration)
38
+ } : void 0,
39
+ events: integration.events ? utils.records.mapValues(integration.events, (event) => ({
40
+ ...event,
41
+ schema: utils.schema.mapZodToJsonSchema(event)
42
+ })) : void 0,
43
+ actions: integration.actions ? utils.records.mapValues(integration.actions, (action) => ({
44
+ ...action,
45
+ input: {
46
+ ...action.input,
47
+ schema: utils.schema.mapZodToJsonSchema(action.input)
48
+ },
49
+ output: {
50
+ ...action.output,
51
+ schema: utils.schema.mapZodToJsonSchema(action.output)
52
+ }
53
+ })) : void 0,
54
+ channels: integration.channels ? utils.records.mapValues(integration.channels, (channel) => ({
55
+ ...channel,
56
+ messages: utils.records.mapValues(channel.messages, (message) => ({
57
+ ...message,
58
+ schema: utils.schema.mapZodToJsonSchema(message)
59
+ }))
60
+ })) : void 0,
61
+ states: integration.states ? utils.records.mapValues(integration.states, (state) => ({
62
+ ...state,
63
+ schema: utils.schema.mapZodToJsonSchema(state)
64
+ })) : void 0
65
+ });
31
66
  const prepareUpdateIntegrationBody = (localIntegration, remoteIntegration) => {
32
67
  const actions = utils.records.setNullOnMissingValues(localIntegration.actions, remoteIntegration.actions);
33
68
  const events = utils.records.setNullOnMissingValues(localIntegration.events, remoteIntegration.events);
@@ -76,6 +111,7 @@ const prepareUpdateIntegrationChannelBody = (localChannel, remoteChannel) => ({
76
111
  });
77
112
  // Annotate the CommonJS export names for ESM import in node:
78
113
  0 && (module.exports = {
114
+ prepareCreateIntegrationBody,
79
115
  prepareUpdateIntegrationBody
80
116
  });
81
117
  //# sourceMappingURL=integration-body.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/api/integration-body.ts"],
4
- "sourcesContent": ["import type { Client, Integration } from '@botpress/client'\nimport * as utils from '../utils'\n\nexport type CreateIntegrationBody = Parameters<Client['createIntegration']>[0]\nexport type UpdateIntegrationBody = Parameters<Client['updateIntegration']>[0]\n\ntype UpdateIntegrationChannelsBody = NonNullable<UpdateIntegrationBody['channels']>\ntype UpdateIntegrationChannelBody = UpdateIntegrationChannelsBody[string]\n\ntype Channels = Integration['channels']\ntype Channel = Integration['channels'][string]\n\nexport const prepareUpdateIntegrationBody = (\n localIntegration: UpdateIntegrationBody,\n remoteIntegration: Integration\n): UpdateIntegrationBody => {\n const actions = utils.records.setNullOnMissingValues(localIntegration.actions, remoteIntegration.actions)\n const events = utils.records.setNullOnMissingValues(localIntegration.events, remoteIntegration.events)\n const states = utils.records.setNullOnMissingValues(localIntegration.states, remoteIntegration.states)\n const user = {\n ...localIntegration.user,\n tags: utils.records.setNullOnMissingValues(localIntegration.user?.tags, remoteIntegration.user?.tags),\n }\n\n const channels = prepareUpdateIntegrationChannelsBody(localIntegration.channels ?? {}, remoteIntegration.channels)\n\n return {\n ...localIntegration,\n actions,\n events,\n states,\n user,\n channels,\n }\n}\n\nconst prepareUpdateIntegrationChannelsBody = (\n localChannels: UpdateIntegrationChannelsBody,\n remoteChannels: Channels\n): UpdateIntegrationChannelsBody => {\n const channelBody: UpdateIntegrationChannelsBody = {}\n\n const zipped = utils.records.zipObjects(localChannels, remoteChannels)\n for (const [channelName, [localChannel, remoteChannel]] of Object.entries(zipped)) {\n if (localChannel && remoteChannel) {\n // channel has to be updated\n channelBody[channelName] = prepareUpdateIntegrationChannelBody(localChannel, remoteChannel)\n } else if (localChannel) {\n // channel has to be created\n channelBody[channelName] = localChannel\n continue\n } else if (remoteChannel) {\n // channel has to be deleted\n channelBody[channelName] = null\n continue\n }\n }\n\n return channelBody\n}\n\nconst prepareUpdateIntegrationChannelBody = (\n localChannel: UpdateIntegrationChannelBody,\n remoteChannel: Channel\n): UpdateIntegrationChannelBody => ({\n ...localChannel,\n messages: utils.records.setNullOnMissingValues(localChannel?.messages, remoteChannel.messages),\n message: {\n ...localChannel?.message,\n tags: utils.records.setNullOnMissingValues(localChannel?.message?.tags, remoteChannel.message.tags),\n },\n conversation: {\n ...localChannel?.conversation,\n tags: utils.records.setNullOnMissingValues(localChannel?.conversation?.tags, remoteChannel.conversation.tags),\n },\n})\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,YAAuB;AAWhB,MAAM,+BAA+B,CAC1C,kBACA,sBAC0B;AAC1B,QAAM,UAAU,MAAM,QAAQ,uBAAuB,iBAAiB,SAAS,kBAAkB,OAAO;AACxG,QAAM,SAAS,MAAM,QAAQ,uBAAuB,iBAAiB,QAAQ,kBAAkB,MAAM;AACrG,QAAM,SAAS,MAAM,QAAQ,uBAAuB,iBAAiB,QAAQ,kBAAkB,MAAM;AACrG,QAAM,OAAO;AAAA,IACX,GAAG,iBAAiB;AAAA,IACpB,MAAM,MAAM,QAAQ,uBAAuB,iBAAiB,MAAM,MAAM,kBAAkB,MAAM,IAAI;AAAA,EACtG;AAEA,QAAM,WAAW,qCAAqC,iBAAiB,YAAY,CAAC,GAAG,kBAAkB,QAAQ;AAEjH,SAAO;AAAA,IACL,GAAG;AAAA,IACH;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAEA,MAAM,uCAAuC,CAC3C,eACA,mBACkC;AAClC,QAAM,cAA6C,CAAC;AAEpD,QAAM,SAAS,MAAM,QAAQ,WAAW,eAAe,cAAc;AACrE,aAAW,CAAC,aAAa,CAAC,cAAc,aAAa,CAAC,KAAK,OAAO,QAAQ,MAAM,GAAG;AACjF,QAAI,gBAAgB,eAAe;AAEjC,kBAAY,eAAe,oCAAoC,cAAc,aAAa;AAAA,IAC5F,WAAW,cAAc;AAEvB,kBAAY,eAAe;AAC3B;AAAA,IACF,WAAW,eAAe;AAExB,kBAAY,eAAe;AAC3B;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEA,MAAM,sCAAsC,CAC1C,cACA,mBACkC;AAAA,EAClC,GAAG;AAAA,EACH,UAAU,MAAM,QAAQ,uBAAuB,cAAc,UAAU,cAAc,QAAQ;AAAA,EAC7F,SAAS;AAAA,IACP,GAAG,cAAc;AAAA,IACjB,MAAM,MAAM,QAAQ,uBAAuB,cAAc,SAAS,MAAM,cAAc,QAAQ,IAAI;AAAA,EACpG;AAAA,EACA,cAAc;AAAA,IACZ,GAAG,cAAc;AAAA,IACjB,MAAM,MAAM,QAAQ,uBAAuB,cAAc,cAAc,MAAM,cAAc,aAAa,IAAI;AAAA,EAC9G;AACF;",
4
+ "sourcesContent": ["import type { Client, Integration } from '@botpress/client'\nimport * as sdk from '@botpress/sdk'\nimport * as utils from '../utils'\n\nexport type CreateIntegrationBody = Parameters<Client['createIntegration']>[0]\nexport type UpdateIntegrationBody = Parameters<Client['updateIntegration']>[0]\n\ntype UpdateIntegrationChannelsBody = NonNullable<UpdateIntegrationBody['channels']>\ntype UpdateIntegrationChannelBody = UpdateIntegrationChannelsBody[string]\n\ntype Channels = Integration['channels']\ntype Channel = Integration['channels'][string]\n\nexport const prepareCreateIntegrationBody = (integration: sdk.IntegrationDefinition): CreateIntegrationBody => ({\n ...integration,\n secrets: undefined,\n configuration: integration.configuration\n ? {\n ...integration.configuration,\n schema: utils.schema.mapZodToJsonSchema(integration.configuration),\n }\n : undefined,\n events: integration.events\n ? utils.records.mapValues(integration.events, (event) => ({\n ...event,\n schema: utils.schema.mapZodToJsonSchema(event),\n }))\n : undefined,\n actions: integration.actions\n ? utils.records.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 ? utils.records.mapValues(integration.channels, (channel) => ({\n ...channel,\n messages: utils.records.mapValues(channel.messages, (message) => ({\n ...message,\n schema: utils.schema.mapZodToJsonSchema(message),\n })),\n }))\n : undefined,\n states: integration.states\n ? utils.records.mapValues(integration.states, (state) => ({\n ...state,\n schema: utils.schema.mapZodToJsonSchema(state),\n }))\n : undefined,\n})\n\nexport const prepareUpdateIntegrationBody = (\n localIntegration: UpdateIntegrationBody,\n remoteIntegration: Integration\n): UpdateIntegrationBody => {\n const actions = utils.records.setNullOnMissingValues(localIntegration.actions, remoteIntegration.actions)\n const events = utils.records.setNullOnMissingValues(localIntegration.events, remoteIntegration.events)\n const states = utils.records.setNullOnMissingValues(localIntegration.states, remoteIntegration.states)\n const user = {\n ...localIntegration.user,\n tags: utils.records.setNullOnMissingValues(localIntegration.user?.tags, remoteIntegration.user?.tags),\n }\n\n const channels = prepareUpdateIntegrationChannelsBody(localIntegration.channels ?? {}, remoteIntegration.channels)\n\n return {\n ...localIntegration,\n actions,\n events,\n states,\n user,\n channels,\n }\n}\n\nconst prepareUpdateIntegrationChannelsBody = (\n localChannels: UpdateIntegrationChannelsBody,\n remoteChannels: Channels\n): UpdateIntegrationChannelsBody => {\n const channelBody: UpdateIntegrationChannelsBody = {}\n\n const zipped = utils.records.zipObjects(localChannels, remoteChannels)\n for (const [channelName, [localChannel, remoteChannel]] of Object.entries(zipped)) {\n if (localChannel && remoteChannel) {\n // channel has to be updated\n channelBody[channelName] = prepareUpdateIntegrationChannelBody(localChannel, remoteChannel)\n } else if (localChannel) {\n // channel has to be created\n channelBody[channelName] = localChannel\n continue\n } else if (remoteChannel) {\n // channel has to be deleted\n channelBody[channelName] = null\n continue\n }\n }\n\n return channelBody\n}\n\nconst prepareUpdateIntegrationChannelBody = (\n localChannel: UpdateIntegrationChannelBody,\n remoteChannel: Channel\n): UpdateIntegrationChannelBody => ({\n ...localChannel,\n messages: utils.records.setNullOnMissingValues(localChannel?.messages, remoteChannel.messages),\n message: {\n ...localChannel?.message,\n tags: utils.records.setNullOnMissingValues(localChannel?.message?.tags, remoteChannel.message.tags),\n },\n conversation: {\n ...localChannel?.conversation,\n tags: utils.records.setNullOnMissingValues(localChannel?.conversation?.tags, remoteChannel.conversation.tags),\n },\n})\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/code-generation/index.ts"],
4
- "sourcesContent": ["import type * as bpclient from '@botpress/client'\nimport type * as bpsdk from '@botpress/sdk'\nimport pathlib from 'path'\nimport * as utils from '../utils'\nimport { GENERATED_HEADER, INDEX_FILE } from './const'\nimport { IntegrationImplementationIndexModule } from './integration-implementation'\nimport { IntegrationInstanceIndexModule } from './integration-instance'\nimport { IntegrationSecretIndexModule } from './integration-secret'\nimport * as mapIntegration from './map-integration'\nimport type * as types from './typings'\n\nexport { File } from './typings'\nexport { secretEnvVariableName } from './integration-secret'\nexport const INTEGRATION_JSON = 'integration.json'\n\nexport const generateIntegrationImplementationTypings = async (\n sdkIntegration: bpsdk.IntegrationDefinition,\n implementationTypingsPath: string\n): Promise<types.File[]> => {\n const integration = mapIntegration.from.sdk(sdkIntegration)\n const indexModule = await IntegrationImplementationIndexModule.create(integration)\n indexModule.unshift(implementationTypingsPath)\n return indexModule.flatten()\n}\n\nexport const generateIntegrationSecrets = async (\n sdkIntegration: bpsdk.IntegrationDefinition,\n secretsPath: string\n): Promise<types.File[]> => {\n const indexModule = await IntegrationSecretIndexModule.create(sdkIntegration)\n indexModule.unshift(secretsPath)\n return indexModule.flatten()\n}\n\nexport const generateIntegrationIndex = async (\n implementationTypingsPath: string,\n implementationSecretsPath: string\n): Promise<types.File> => {\n let content = ''\n content += `export * from './${implementationTypingsPath}'\\n`\n content += `export * from './${implementationSecretsPath}'\\n`\n return {\n path: INDEX_FILE,\n content,\n }\n}\n\nexport type IntegrationInstanceJson = {\n name: string\n version: string\n id: string | null\n}\n\nexport const generateIntegrationInstance = async (\n anyIntegration: bpclient.Integration | bpsdk.IntegrationDefinition,\n installPath: string\n): Promise<types.File[]> => {\n let integration: types.IntegrationDefinition\n if ('id' in anyIntegration) {\n integration = mapIntegration.from.client(anyIntegration)\n } else {\n integration = mapIntegration.from.sdk(anyIntegration)\n }\n\n const indexModule = await IntegrationInstanceIndexModule.create(integration)\n const dirname = utils.casing.to.kebabCase(integration.name)\n indexModule.unshift(installPath, dirname)\n const files = indexModule.flatten()\n\n const { name, version, id } = integration\n const json: IntegrationInstanceJson = {\n name,\n version,\n id,\n }\n files.push({\n path: pathlib.join(installPath, dirname, INTEGRATION_JSON),\n content: JSON.stringify(json, null, 2),\n })\n\n return files\n}\n\nexport const generateBotIndex = async (installPath: string, instances: string[]): Promise<types.File> => {\n const lines: string[] = [\n GENERATED_HEADER,\n \"import * as sdk from '@botpress/sdk'\",\n ...instances.map(\n (instance) => `import * as ${utils.casing.to.camelCase(instance)} from './${installPath}/${instance}'`\n ),\n ...instances.map(\n (instance) => `export * as ${utils.casing.to.camelCase(instance)} from './${installPath}/${instance}'`\n ),\n '',\n 'type TIntegrations = {',\n ...instances.map(\n (instance) =>\n ` ${utils.casing.to.camelCase(instance)}: ${utils.casing.to.camelCase(instance)}.T${utils.casing.to.pascalCase(\n instance\n )}`\n ),\n '}',\n '',\n 'type BaseStates = sdk.Bot extends sdk.Bot<any, infer TStates, any> ? TStates : never',\n 'type BaseEvents = sdk.Bot extends sdk.Bot<any, any, infer TEvents> ? TEvents : never',\n '',\n 'export class Bot<',\n ' TStates extends BaseStates,',\n ' TEvents extends BaseEvents',\n '> extends sdk.Bot<',\n ' TIntegrations,',\n ' TStates,',\n ' TEvents',\n '> {}',\n ]\n\n return {\n path: INDEX_FILE,\n content: lines.join('\\n'),\n }\n}\n"],
4
+ "sourcesContent": ["import type * as client from '@botpress/client'\nimport type * as sdk from '@botpress/sdk'\nimport pathlib from 'path'\nimport * as utils from '../utils'\nimport { GENERATED_HEADER, INDEX_FILE } from './const'\nimport { IntegrationImplementationIndexModule } from './integration-implementation'\nimport { IntegrationInstanceIndexModule } from './integration-instance'\nimport { IntegrationSecretIndexModule } from './integration-secret'\nimport * as mapIntegration from './map-integration'\nimport type * as types from './typings'\n\nexport { File } from './typings'\nexport { secretEnvVariableName } from './integration-secret'\nexport const INTEGRATION_JSON = 'integration.json'\n\nexport const generateIntegrationImplementationTypings = async (\n sdkIntegration: sdk.IntegrationDefinition,\n implementationTypingsPath: string\n): Promise<types.File[]> => {\n const integration = mapIntegration.from.sdk(sdkIntegration)\n const indexModule = await IntegrationImplementationIndexModule.create(integration)\n indexModule.unshift(implementationTypingsPath)\n return indexModule.flatten()\n}\n\nexport const generateIntegrationSecrets = async (\n sdkIntegration: sdk.IntegrationDefinition,\n secretsPath: string\n): Promise<types.File[]> => {\n const indexModule = await IntegrationSecretIndexModule.create(sdkIntegration)\n indexModule.unshift(secretsPath)\n return indexModule.flatten()\n}\n\nexport const generateIntegrationIndex = async (\n implementationTypingsPath: string,\n implementationSecretsPath: string\n): Promise<types.File> => {\n let content = ''\n content += `export * from './${implementationTypingsPath}'\\n`\n content += `export * from './${implementationSecretsPath}'\\n`\n return {\n path: INDEX_FILE,\n content,\n }\n}\n\nexport type IntegrationInstanceJson = {\n name: string\n version: string\n id: string | null\n}\n\nexport const generateIntegrationInstance = async (\n anyIntegration: client.Integration | sdk.IntegrationDefinition,\n installPath: string\n): Promise<types.File[]> => {\n let integration: types.IntegrationDefinition\n if ('id' in anyIntegration) {\n integration = mapIntegration.from.client(anyIntegration)\n } else {\n integration = mapIntegration.from.sdk(anyIntegration)\n }\n\n const indexModule = await IntegrationInstanceIndexModule.create(integration)\n const dirname = utils.casing.to.kebabCase(integration.name)\n indexModule.unshift(installPath, dirname)\n const files = indexModule.flatten()\n\n const { name, version, id } = integration\n const json: IntegrationInstanceJson = {\n name,\n version,\n id,\n }\n files.push({\n path: pathlib.join(installPath, dirname, INTEGRATION_JSON),\n content: JSON.stringify(json, null, 2),\n })\n\n return files\n}\n\nexport const generateBotIndex = async (installPath: string, instances: string[]): Promise<types.File> => {\n const lines: string[] = [\n GENERATED_HEADER,\n \"import * as sdk from '@botpress/sdk'\",\n ...instances.map(\n (instance) => `import * as ${utils.casing.to.camelCase(instance)} from './${installPath}/${instance}'`\n ),\n ...instances.map(\n (instance) => `export * as ${utils.casing.to.camelCase(instance)} from './${installPath}/${instance}'`\n ),\n '',\n 'type TIntegrations = {',\n ...instances.map(\n (instance) =>\n ` ${utils.casing.to.camelCase(instance)}: ${utils.casing.to.camelCase(instance)}.T${utils.casing.to.pascalCase(\n instance\n )}`\n ),\n '}',\n '',\n 'type BaseStates = sdk.Bot extends sdk.Bot<any, infer TStates, any> ? TStates : never',\n 'type BaseEvents = sdk.Bot extends sdk.Bot<any, any, infer TEvents> ? TEvents : never',\n '',\n 'export class Bot<',\n ' TStates extends BaseStates,',\n ' TEvents extends BaseEvents',\n '> extends sdk.Bot<',\n ' TIntegrations,',\n ' TStates,',\n ' TEvents',\n '> {}',\n ]\n\n return {\n path: INDEX_FILE,\n content: lines.join('\\n'),\n }\n}\n"],
5
5
  "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,kBAAoB;AACpB,YAAuB;AACvB,mBAA6C;AAC7C,wCAAqD;AACrD,kCAA+C;AAC/C,gCAA6C;AAC7C,qBAAgC;AAGhC,qBAAqB;AACrB,IAAAA,6BAAsC;AAC/B,MAAM,mBAAmB;AAEzB,MAAM,2CAA2C,OACtD,gBACA,8BAC0B;AAC1B,QAAM,cAAc,eAAe,KAAK,IAAI,cAAc;AAC1D,QAAM,cAAc,MAAM,uEAAqC,OAAO,WAAW;AACjF,cAAY,QAAQ,yBAAyB;AAC7C,SAAO,YAAY,QAAQ;AAC7B;AAEO,MAAM,6BAA6B,OACxC,gBACA,gBAC0B;AAC1B,QAAM,cAAc,MAAM,uDAA6B,OAAO,cAAc;AAC5E,cAAY,QAAQ,WAAW;AAC/B,SAAO,YAAY,QAAQ;AAC7B;AAEO,MAAM,2BAA2B,OACtC,2BACA,8BACwB;AACxB,MAAI,UAAU;AACd,aAAW,oBAAoB;AAAA;AAC/B,aAAW,oBAAoB;AAAA;AAC/B,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,EACF;AACF;AAQO,MAAM,8BAA8B,OACzC,gBACA,gBAC0B;AAC1B,MAAI;AACJ,MAAI,QAAQ,gBAAgB;AAC1B,kBAAc,eAAe,KAAK,OAAO,cAAc;AAAA,EACzD,OAAO;AACL,kBAAc,eAAe,KAAK,IAAI,cAAc;AAAA,EACtD;AAEA,QAAM,cAAc,MAAM,2DAA+B,OAAO,WAAW;AAC3E,QAAM,UAAU,MAAM,OAAO,GAAG,UAAU,YAAY,IAAI;AAC1D,cAAY,QAAQ,aAAa,OAAO;AACxC,QAAM,QAAQ,YAAY,QAAQ;AAElC,QAAM,EAAE,MAAM,SAAS,GAAG,IAAI;AAC9B,QAAM,OAAgC;AAAA,IACpC;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,KAAK;AAAA,IACT,MAAM,YAAAC,QAAQ,KAAK,aAAa,SAAS,gBAAgB;AAAA,IACzD,SAAS,KAAK,UAAU,MAAM,MAAM,CAAC;AAAA,EACvC,CAAC;AAED,SAAO;AACT;AAEO,MAAM,mBAAmB,OAAO,aAAqB,cAA6C;AACvG,QAAM,QAAkB;AAAA,IACtB;AAAA,IACA;AAAA,IACA,GAAG,UAAU;AAAA,MACX,CAAC,aAAa,eAAe,MAAM,OAAO,GAAG,UAAU,QAAQ,aAAa,eAAe;AAAA,IAC7F;AAAA,IACA,GAAG,UAAU;AAAA,MACX,CAAC,aAAa,eAAe,MAAM,OAAO,GAAG,UAAU,QAAQ,aAAa,eAAe;AAAA,IAC7F;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG,UAAU;AAAA,MACX,CAAC,aACC,KAAK,MAAM,OAAO,GAAG,UAAU,QAAQ,MAAM,MAAM,OAAO,GAAG,UAAU,QAAQ,MAAM,MAAM,OAAO,GAAG;AAAA,QACnG;AAAA,MACF;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,SAAO;AAAA,IACL,MAAM;AAAA,IACN,SAAS,MAAM,KAAK,IAAI;AAAA,EAC1B;AACF;",
6
6
  "names": ["import_integration_secret", "pathlib"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/code-generation/map-integration.ts"],
4
- "sourcesContent": ["import * as bpclient from '@botpress/client'\nimport * as bpsdk from '@botpress/sdk'\nimport { z } from 'zod'\nimport * as utils from '../utils'\nimport * as types from './typings'\n\nexport namespace from {\n export const sdk = (i: bpsdk.IntegrationDefinition): types.IntegrationDefinition => ({\n id: null,\n name: i.name,\n version: i.version,\n user: {\n tags: i.user?.tags ?? {},\n creation: i.user?.creation ?? { enabled: false, requiredTags: [] },\n },\n configuration: i.configuration ? _mapSchema(i.configuration) : { schema: {} },\n events: i.events ? utils.records.mapValues(i.events, _mapSchema) : {},\n states: i.states ? utils.records.mapValues(i.states, _mapSchema) : {},\n actions: i.actions\n ? utils.records.mapValues(i.actions, (a) => ({\n input: _mapSchema(a.input),\n output: _mapSchema(a.output),\n }))\n : {},\n channels: i.channels\n ? utils.records.mapValues(i.channels, (c) => ({\n conversation: {\n tags: c.conversation?.tags ?? {},\n creation: c.conversation?.creation ?? { enabled: false, requiredTags: [] },\n },\n message: {\n tags: c.message?.tags ?? {},\n },\n messages: utils.records.mapValues(c.messages, _mapSchema),\n }))\n : {},\n })\n\n export const client = (i: bpclient.Integration): types.IntegrationDefinition => {\n const { id, name, version, configuration, channels, states, events, actions, user } = i\n return { id, name, version, configuration, channels, states, events, actions, user }\n }\n\n const _mapSchema = <T extends { schema: z.ZodObject<any> }>(\n x: T\n ): utils.types.Merge<T, { schema: ReturnType<typeof utils.schema.mapZodToJsonSchema> }> => ({\n ...x,\n schema: utils.schema.mapZodToJsonSchema(x),\n })\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,YAAuB;AAGhB,IAAU;AAAA,CAAV,CAAUA,UAAV;AACE,EAAMA,MAAA,MAAM,CAAC,OAAiE;AAAA,IACnF,IAAI;AAAA,IACJ,MAAM,EAAE;AAAA,IACR,SAAS,EAAE;AAAA,IACX,MAAM;AAAA,MACJ,MAAM,EAAE,MAAM,QAAQ,CAAC;AAAA,MACvB,UAAU,EAAE,MAAM,YAAY,EAAE,SAAS,OAAO,cAAc,CAAC,EAAE;AAAA,IACnE;AAAA,IACA,eAAe,EAAE,gBAAgB,WAAW,EAAE,aAAa,IAAI,EAAE,QAAQ,CAAC,EAAE;AAAA,IAC5E,QAAQ,EAAE,SAAS,MAAM,QAAQ,UAAU,EAAE,QAAQ,UAAU,IAAI,CAAC;AAAA,IACpE,QAAQ,EAAE,SAAS,MAAM,QAAQ,UAAU,EAAE,QAAQ,UAAU,IAAI,CAAC;AAAA,IACpE,SAAS,EAAE,UACP,MAAM,QAAQ,UAAU,EAAE,SAAS,CAAC,OAAO;AAAA,MACzC,OAAO,WAAW,EAAE,KAAK;AAAA,MACzB,QAAQ,WAAW,EAAE,MAAM;AAAA,IAC7B,EAAE,IACF,CAAC;AAAA,IACL,UAAU,EAAE,WACR,MAAM,QAAQ,UAAU,EAAE,UAAU,CAAC,OAAO;AAAA,MAC1C,cAAc;AAAA,QACZ,MAAM,EAAE,cAAc,QAAQ,CAAC;AAAA,QAC/B,UAAU,EAAE,cAAc,YAAY,EAAE,SAAS,OAAO,cAAc,CAAC,EAAE;AAAA,MAC3E;AAAA,MACA,SAAS;AAAA,QACP,MAAM,EAAE,SAAS,QAAQ,CAAC;AAAA,MAC5B;AAAA,MACA,UAAU,MAAM,QAAQ,UAAU,EAAE,UAAU,UAAU;AAAA,IAC1D,EAAE,IACF,CAAC;AAAA,EACP;AAEO,EAAMA,MAAA,SAAS,CAAC,MAAyD;AAC9E,UAAM,EAAE,IAAI,MAAM,SAAS,eAAe,UAAU,QAAQ,QAAQ,SAAS,KAAK,IAAI;AACtF,WAAO,EAAE,IAAI,MAAM,SAAS,eAAe,UAAU,QAAQ,QAAQ,SAAS,KAAK;AAAA,EACrF;AAEA,QAAM,aAAa,CACjB,OAC0F;AAAA,IAC1F,GAAG;AAAA,IACH,QAAQ,MAAM,OAAO,mBAAmB,CAAC;AAAA,EAC3C;AAAA,GA1Ce;",
4
+ "sourcesContent": ["import * as client from '@botpress/client'\nimport * as sdk from '@botpress/sdk'\nimport { z } from 'zod'\nimport * as utils from '../utils'\nimport * as types from './typings'\n\nexport namespace from {\n export const sdk = (i: sdk.IntegrationDefinition): types.IntegrationDefinition => ({\n id: null,\n name: i.name,\n version: i.version,\n user: {\n tags: i.user?.tags ?? {},\n creation: i.user?.creation ?? { enabled: false, requiredTags: [] },\n },\n configuration: i.configuration ? _mapSchema(i.configuration) : { schema: {} },\n events: i.events ? utils.records.mapValues(i.events, _mapSchema) : {},\n states: i.states ? utils.records.mapValues(i.states, _mapSchema) : {},\n actions: i.actions\n ? utils.records.mapValues(i.actions, (a) => ({\n input: _mapSchema(a.input),\n output: _mapSchema(a.output),\n }))\n : {},\n channels: i.channels\n ? utils.records.mapValues(i.channels, (c) => ({\n conversation: {\n tags: c.conversation?.tags ?? {},\n creation: c.conversation?.creation ?? { enabled: false, requiredTags: [] },\n },\n message: {\n tags: c.message?.tags ?? {},\n },\n messages: utils.records.mapValues(c.messages, _mapSchema),\n }))\n : {},\n })\n\n export const client = (i: client.Integration): types.IntegrationDefinition => {\n const { id, name, version, configuration, channels, states, events, actions, user } = i\n return { id, name, version, configuration, channels, states, events, actions, user }\n }\n\n const _mapSchema = <T extends { schema: z.ZodObject<any> }>(\n x: T\n ): utils.types.Merge<T, { schema: ReturnType<typeof utils.schema.mapZodToJsonSchema> }> => ({\n ...x,\n schema: utils.schema.mapZodToJsonSchema(x),\n })\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAGA,YAAuB;AAGhB,IAAU;AAAA,CAAV,CAAUA,UAAV;AACE,EAAMA,MAAA,MAAM,CAAC,OAA+D;AAAA,IACjF,IAAI;AAAA,IACJ,MAAM,EAAE;AAAA,IACR,SAAS,EAAE;AAAA,IACX,MAAM;AAAA,MACJ,MAAM,EAAE,MAAM,QAAQ,CAAC;AAAA,MACvB,UAAU,EAAE,MAAM,YAAY,EAAE,SAAS,OAAO,cAAc,CAAC,EAAE;AAAA,IACnE;AAAA,IACA,eAAe,EAAE,gBAAgB,WAAW,EAAE,aAAa,IAAI,EAAE,QAAQ,CAAC,EAAE;AAAA,IAC5E,QAAQ,EAAE,SAAS,MAAM,QAAQ,UAAU,EAAE,QAAQ,UAAU,IAAI,CAAC;AAAA,IACpE,QAAQ,EAAE,SAAS,MAAM,QAAQ,UAAU,EAAE,QAAQ,UAAU,IAAI,CAAC;AAAA,IACpE,SAAS,EAAE,UACP,MAAM,QAAQ,UAAU,EAAE,SAAS,CAAC,OAAO;AAAA,MACzC,OAAO,WAAW,EAAE,KAAK;AAAA,MACzB,QAAQ,WAAW,EAAE,MAAM;AAAA,IAC7B,EAAE,IACF,CAAC;AAAA,IACL,UAAU,EAAE,WACR,MAAM,QAAQ,UAAU,EAAE,UAAU,CAAC,OAAO;AAAA,MAC1C,cAAc;AAAA,QACZ,MAAM,EAAE,cAAc,QAAQ,CAAC;AAAA,QAC/B,UAAU,EAAE,cAAc,YAAY,EAAE,SAAS,OAAO,cAAc,CAAC,EAAE;AAAA,MAC3E;AAAA,MACA,SAAS;AAAA,QACP,MAAM,EAAE,SAAS,QAAQ,CAAC;AAAA,MAC5B;AAAA,MACA,UAAU,MAAM,QAAQ,UAAU,EAAE,UAAU,UAAU;AAAA,IAC1D,EAAE,IACF,CAAC;AAAA,EACP;AAEO,EAAMA,MAAA,SAAS,CAAC,MAAuD;AAC5E,UAAM,EAAE,IAAI,MAAM,SAAS,eAAe,UAAU,QAAQ,QAAQ,SAAS,KAAK,IAAI;AACtF,WAAO,EAAE,IAAI,MAAM,SAAS,eAAe,UAAU,QAAQ,QAAQ,SAAS,KAAK;AAAA,EACrF;AAEA,QAAM,aAAa,CACjB,OAC0F;AAAA,IAC1F,GAAG;AAAA,IACH,QAAQ,MAAM,OAAO,mBAAmB,CAAC;AAAA,EAC3C;AAAA,GA1Ce;",
6
6
  "names": ["from"]
7
7
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/command-implementations/add-command.ts"],
4
- "sourcesContent": ["import type * as bpclient from '@botpress/client'\nimport type * as bpsdk from '@botpress/sdk'\nimport bluebird from 'bluebird'\nimport chalk from 'chalk'\nimport * as fs from 'fs'\nimport * as pathlib from 'path'\nimport * as codegen from '../code-generation'\nimport type commandDefinitions from '../command-definitions'\nimport * as consts from '../consts'\nimport * as errors from '../errors'\nimport {\n ApiIntegrationRef,\n formatIntegrationRef,\n LocalPathIntegrationRef,\n parseIntegrationRef,\n} from '../integration-ref'\nimport * as utils from '../utils'\nimport { ProjectCommand } from './project-command'\n\ntype IntegrationInstallDir = codegen.IntegrationInstanceJson & {\n dirname: string\n}\n\nexport type AddCommandDefinition = typeof commandDefinitions.add\nexport class AddCommand extends ProjectCommand<AddCommandDefinition> {\n public async run(): Promise<void> {\n const integrationDef = await this.readIntegrationDefinitionFromFS()\n if (integrationDef) {\n throw new errors.ExclusiveBotFeatureError()\n }\n\n const integrationRef = this.argv.integrationRef\n\n const parsedRef = parseIntegrationRef(integrationRef)\n if (!parsedRef) {\n throw new errors.InvalidIntegrationReferenceError(integrationRef)\n }\n\n const integration =\n parsedRef.type === 'path'\n ? await this._fetchLocalIntegration(parsedRef)\n : await this._fetchApiIntegration(parsedRef)\n\n const allInstances = await this._listIntegrationInstances()\n const existingInstance = allInstances.find((i) => i.name === integration.name)\n if (existingInstance) {\n this.logger.warn(`Integration with name \"${integration.name}\" already installed.`)\n const res = await this.prompt.confirm('Do you want to overwrite the existing instance?')\n if (!res) {\n this.logger.log('Aborted')\n return\n }\n\n await this._uninstallIntegration(existingInstance)\n }\n\n await this._generateIntegrationInstance(integration)\n }\n\n private _fetchLocalIntegration = async (\n integrationRef: LocalPathIntegrationRef\n ): Promise<bpsdk.IntegrationDefinition> => {\n this.logger.warn(\n 'Installing integration from a local path. There is no guarantee that the integration is deployed with the expected schemas.'\n )\n\n const workDir = integrationRef.path\n const pathStore = new utils.path.PathStore<'workDir' | 'definition'>({\n workDir,\n definition: utils.path.absoluteFrom(workDir, consts.fromWorkDir.definition),\n })\n const integrationDefinition = await this.readIntegrationDefinitionFromFS(pathStore)\n if (!integrationDefinition) {\n throw new errors.BotpressCLIError(`Integration definition not found at ${workDir}`)\n }\n return integrationDefinition\n }\n\n private _fetchApiIntegration = async (integrationRef: ApiIntegrationRef): Promise<bpclient.Integration> => {\n const api = await this.ensureLoginAndCreateClient(this.argv)\n const integration = await api.findIntegration(integrationRef)\n if (!integration) {\n const formattedRef = formatIntegrationRef(integrationRef)\n throw new errors.BotpressCLIError(`Integration \"${formattedRef}\" not found`)\n }\n return integration\n }\n\n private async _listIntegrationInstances(): Promise<IntegrationInstallDir[]> {\n const installPath = this.projectPaths.abs.installDir\n if (!fs.existsSync(installPath)) {\n this.logger.debug('Install path does not exist. Skipping listing of integration instances')\n return []\n }\n\n const allFiles = await fs.promises.readdir(installPath)\n const allPaths = allFiles.map((name) => pathlib.join(installPath, name))\n const directories = await bluebird.filter(allPaths, async (path) => {\n const stat = await fs.promises.stat(path)\n return stat.isDirectory()\n })\n\n let jsons = directories.map((root) => ({ root, json: pathlib.join(root, codegen.INTEGRATION_JSON) }))\n jsons = jsons.filter(({ json: x }) => fs.existsSync(x))\n\n return bluebird.map(jsons, async ({ root, json }) => {\n const content: string = await fs.promises.readFile(json, 'utf-8')\n const { name, version, id } = JSON.parse(content) as codegen.IntegrationInstanceJson\n const dirname = pathlib.basename(root)\n return {\n dirname,\n id,\n name,\n version,\n }\n })\n }\n\n private async _uninstallIntegration(instance: IntegrationInstallDir) {\n const installDir = this.projectPaths.abs.installDir\n const instancePath = pathlib.join(installDir, instance.dirname)\n await fs.promises.rm(instancePath, { recursive: true })\n await this._generateBotIndex()\n }\n\n private async _generateIntegrationInstance(integration: bpclient.Integration | bpsdk.IntegrationDefinition) {\n const line = this.logger.line()\n\n const { name, version } = integration\n line.started(`Installing ${chalk.bold(name)} v${version}...`)\n\n const instanceFiles = await codegen.generateIntegrationInstance(\n integration,\n this.projectPaths.rel('outDir').installDir\n )\n await this.writeGeneratedFilesToOutFolder(instanceFiles)\n await this._generateBotIndex()\n\n const rel = this.projectPaths.rel('workDir')\n line.success(`Installed integration available at ${chalk.grey(rel.outDir)}`)\n }\n\n private async _generateBotIndex() {\n const allInstances = await this._listIntegrationInstances()\n const indexFile = await codegen.generateBotIndex(\n this.projectPaths.rel('outDir').installDir,\n allInstances.map((i) => i.dirname)\n )\n await this.writeGeneratedFilesToOutFolder([indexFile])\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type * as client from '@botpress/client'\nimport type * as sdk from '@botpress/sdk'\nimport bluebird from 'bluebird'\nimport chalk from 'chalk'\nimport * as fs from 'fs'\nimport * as pathlib from 'path'\nimport * as codegen from '../code-generation'\nimport type commandDefinitions from '../command-definitions'\nimport * as consts from '../consts'\nimport * as errors from '../errors'\nimport {\n ApiIntegrationRef,\n formatIntegrationRef,\n LocalPathIntegrationRef,\n parseIntegrationRef,\n} from '../integration-ref'\nimport * as utils from '../utils'\nimport { ProjectCommand } from './project-command'\n\ntype IntegrationInstallDir = codegen.IntegrationInstanceJson & {\n dirname: string\n}\n\nexport type AddCommandDefinition = typeof commandDefinitions.add\nexport class AddCommand extends ProjectCommand<AddCommandDefinition> {\n public async run(): Promise<void> {\n const integrationDef = await this.readIntegrationDefinitionFromFS()\n if (integrationDef) {\n throw new errors.ExclusiveBotFeatureError()\n }\n\n const integrationRef = this.argv.integrationRef\n\n const parsedRef = parseIntegrationRef(integrationRef)\n if (!parsedRef) {\n throw new errors.InvalidIntegrationReferenceError(integrationRef)\n }\n\n const integration =\n parsedRef.type === 'path'\n ? await this._fetchLocalIntegration(parsedRef)\n : await this._fetchApiIntegration(parsedRef)\n\n const allInstances = await this._listIntegrationInstances()\n const existingInstance = allInstances.find((i) => i.name === integration.name)\n if (existingInstance) {\n this.logger.warn(`Integration with name \"${integration.name}\" already installed.`)\n const res = await this.prompt.confirm('Do you want to overwrite the existing instance?')\n if (!res) {\n this.logger.log('Aborted')\n return\n }\n\n await this._uninstallIntegration(existingInstance)\n }\n\n await this._generateIntegrationInstance(integration)\n }\n\n private _fetchLocalIntegration = async (\n integrationRef: LocalPathIntegrationRef\n ): Promise<sdk.IntegrationDefinition> => {\n this.logger.warn(\n 'Installing integration from a local path. There is no guarantee that the integration is deployed with the expected schemas.'\n )\n\n const workDir = integrationRef.path\n const pathStore = new utils.path.PathStore<'workDir' | 'definition'>({\n workDir,\n definition: utils.path.absoluteFrom(workDir, consts.fromWorkDir.definition),\n })\n const integrationDefinition = await this.readIntegrationDefinitionFromFS(pathStore)\n if (!integrationDefinition) {\n throw new errors.BotpressCLIError(`Integration definition not found at ${workDir}`)\n }\n return integrationDefinition\n }\n\n private _fetchApiIntegration = async (integrationRef: ApiIntegrationRef): Promise<client.Integration> => {\n const api = await this.ensureLoginAndCreateClient(this.argv)\n const integration = await api.findIntegration(integrationRef)\n if (!integration) {\n const formattedRef = formatIntegrationRef(integrationRef)\n throw new errors.BotpressCLIError(`Integration \"${formattedRef}\" not found`)\n }\n return integration\n }\n\n private async _listIntegrationInstances(): Promise<IntegrationInstallDir[]> {\n const installPath = this.projectPaths.abs.installDir\n if (!fs.existsSync(installPath)) {\n this.logger.debug('Install path does not exist. Skipping listing of integration instances')\n return []\n }\n\n const allFiles = await fs.promises.readdir(installPath)\n const allPaths = allFiles.map((name) => pathlib.join(installPath, name))\n const directories = await bluebird.filter(allPaths, async (path) => {\n const stat = await fs.promises.stat(path)\n return stat.isDirectory()\n })\n\n let jsons = directories.map((root) => ({ root, json: pathlib.join(root, codegen.INTEGRATION_JSON) }))\n jsons = jsons.filter(({ json: x }) => fs.existsSync(x))\n\n return bluebird.map(jsons, async ({ root, json }) => {\n const content: string = await fs.promises.readFile(json, 'utf-8')\n const { name, version, id } = JSON.parse(content) as codegen.IntegrationInstanceJson\n const dirname = pathlib.basename(root)\n return {\n dirname,\n id,\n name,\n version,\n }\n })\n }\n\n private async _uninstallIntegration(instance: IntegrationInstallDir) {\n const installDir = this.projectPaths.abs.installDir\n const instancePath = pathlib.join(installDir, instance.dirname)\n await fs.promises.rm(instancePath, { recursive: true })\n await this._generateBotIndex()\n }\n\n private async _generateIntegrationInstance(integration: client.Integration | sdk.IntegrationDefinition) {\n const line = this.logger.line()\n\n const { name, version } = integration\n line.started(`Installing ${chalk.bold(name)} v${version}...`)\n\n const instanceFiles = await codegen.generateIntegrationInstance(\n integration,\n this.projectPaths.rel('outDir').installDir\n )\n await this.writeGeneratedFilesToOutFolder(instanceFiles)\n await this._generateBotIndex()\n\n const rel = this.projectPaths.rel('workDir')\n line.success(`Installed integration available at ${chalk.grey(rel.outDir)}`)\n }\n\n private async _generateBotIndex() {\n const allInstances = await this._listIntegrationInstances()\n const indexFile = await codegen.generateBotIndex(\n this.projectPaths.rel('outDir').installDir,\n allInstances.map((i) => i.dirname)\n )\n await this.writeGeneratedFilesToOutFolder([indexFile])\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["bluebird", "chalk"]
7
7
  }
@@ -87,16 +87,16 @@ class DeployCommand extends import_project_command.ProjectCommand {
87
87
  this.logger.log("Aborted");
88
88
  return;
89
89
  }
90
- const integrationDefinition = this.prepareIntegrationDefinition(integrationDef);
91
- const createBody = {
92
- ...integrationDefinition,
90
+ let createBody = (0, import_integration_body.prepareCreateIntegrationBody)(integrationDef);
91
+ createBody = {
92
+ ...createBody,
93
93
  code,
94
94
  icon: iconFileContent,
95
95
  readme: readmeFileContent,
96
96
  configuration: {
97
- ...integrationDefinition.configuration,
97
+ ...createBody.configuration,
98
98
  identifier: {
99
- ...integrationDefinition.configuration?.identifier ?? {},
99
+ ...createBody.configuration?.identifier ?? {},
100
100
  linkTemplateScript: identifierLinkTemplateFileContent
101
101
  }
102
102
  },
@@ -125,7 +125,8 @@ class DeployCommand extends import_project_command.ProjectCommand {
125
125
  });
126
126
  line.success(successMessage);
127
127
  } else {
128
- createBody.secrets = await this.promptSecrets(integrationDef, this.argv);
128
+ const createSecrets = await this.promptSecrets(integrationDef, this.argv);
129
+ createBody.secrets = utils.records.filterValues(createSecrets, utils.guards.is.notNull);
129
130
  this._detectDeprecatedFeatures(integrationDef, this.argv);
130
131
  const line = this.logger.line();
131
132
  line.started(startedMessage);
@@ -200,12 +201,13 @@ class DeployCommand extends import_project_command.ProjectCommand {
200
201
  }
201
202
  const line = this.logger.line();
202
203
  line.started(`Deploying bot ${import_chalk.default.bold(bot.name)}...`);
204
+ const integrationInstances = await this.fetchBotIntegrationInstances(botImpl, api);
203
205
  const updateBotBody = (0, import_bot_body.prepareUpdateBotBody)(
204
206
  {
207
+ ...(0, import_bot_body.prepareCreateBotBody)(botImpl),
205
208
  id: bot.id,
206
209
  code,
207
- ...this.prepareBot(botImpl),
208
- ...await this.prepareBotIntegrationInstances(botImpl, api)
210
+ integrations: integrationInstances
209
211
  },
210
212
  bot
211
213
  );
@@ -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 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\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 const code = await fs.promises.readFile(outfile, 'utf-8')\n\n const {\n name,\n version,\n icon: iconRelativeFilePath,\n readme: readmeRelativeFilePath,\n identifier,\n configuration,\n } = integrationDef\n\n if (iconRelativeFilePath && !iconRelativeFilePath.toLowerCase().endsWith('.svg')) {\n throw new errors.BotpressCLIError('Icon must be an SVG file')\n }\n\n const iconFileContent = await this._readMediaFile('icon', iconRelativeFilePath)\n const readmeFileContent = await this._readMediaFile('readme', readmeRelativeFilePath)\n const identifierExtractScriptFileContent = await this._readFile(identifier?.extractScript)\n const fallbackHandlerScriptFileContent = await this._readFile(identifier?.fallbackHandlerScript)\n const identifierLinkTemplateFileContent = await this._readFile(configuration?.identifier?.linkTemplateScript)\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 integrationDefinition = this.prepareIntegrationDefinition(integrationDef)\n\n const createBody: CreateIntegrationBody = {\n ...integrationDefinition,\n code,\n icon: iconFileContent,\n readme: readmeFileContent,\n configuration: {\n ...integrationDefinition.configuration,\n identifier: {\n ...(integrationDefinition.configuration?.identifier ?? {}),\n linkTemplateScript: identifierLinkTemplateFileContent,\n },\n },\n identifier: {\n extractScript: identifierExtractScriptFileContent,\n fallbackHandlerScript: fallbackHandlerScriptFileContent,\n },\n }\n\n const startedMessage = `Deploying integration ${chalk.bold(integrationDef.name)} v${integrationDef.version}...`\n const successMessage = 'Integration deployed'\n if (integration) {\n const updateBody = prepareUpdateIntegrationBody(\n {\n id: integration.id,\n ...createBody,\n },\n integration\n )\n\n const { secrets: knownSecrets } = integration\n updateBody.secrets = await this.promptSecrets(integrationDef, this.argv, { knownSecrets })\n this._detectDeprecatedFeatures(integrationDef, { allowDeprecated: true })\n\n const line = this.logger.line()\n line.started(startedMessage)\n await api.client.updateIntegration(updateBody).catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, `Could not update integration \"${integrationDef.name}\"`)\n })\n line.success(successMessage)\n } else {\n createBody.secrets = await this.promptSecrets(integrationDef, this.argv)\n this._detectDeprecatedFeatures(integrationDef, this.argv)\n\n const line = this.logger.line()\n line.started(startedMessage)\n await api.client.createIntegration(createBody).catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, `Could not create integration \"${integrationDef.name}\"`)\n })\n line.success(successMessage)\n }\n }\n\n private _detectDeprecatedFeatures(\n integrationDef: bpsdk.IntegrationDefinition,\n opts: { allowDeprecated?: boolean } = {}\n ) {\n const deprecatedFields: string[] = []\n const { user, channels } = integrationDef\n if (user?.creation?.enabled) {\n deprecatedFields.push('user.creation')\n }\n\n for (const [channelName, channel] of Object.entries(channels ?? {})) {\n if (channel?.conversation?.creation?.enabled) {\n deprecatedFields.push(`channels.${channelName}.creation`)\n }\n }\n\n if (!deprecatedFields.length) {\n return\n }\n\n const errorMessage = `The following fields of the integration's definition are deprecated: ${deprecatedFields.join(\n ', '\n )}`\n\n if (opts.allowDeprecated) {\n this.logger.warn(errorMessage)\n } else {\n throw new errors.BotpressCLIError(errorMessage)\n }\n }\n\n private _readFile = async (filePath: string | undefined): 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, 'utf-8').catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, `Could not read file \"${absoluteFilePath}\"`)\n })\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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",
4
+ "sourcesContent": ["import type * as client from '@botpress/client'\nimport type * as sdk from '@botpress/sdk'\nimport chalk from 'chalk'\nimport * as fs from 'fs'\nimport { prepareCreateBotBody, prepareUpdateBotBody } from '../api/bot-body'\nimport type { ApiClient } from '../api/client'\nimport {\n prepareUpdateIntegrationBody,\n CreateIntegrationBody,\n prepareCreateIntegrationBody,\n} from '../api/integration-body'\nimport type commandDefinitions from '../command-definitions'\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\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: sdk.IntegrationDefinition) {\n const outfile = this.projectPaths.abs.outFile\n const code = await fs.promises.readFile(outfile, 'utf-8')\n\n const {\n name,\n version,\n icon: iconRelativeFilePath,\n readme: readmeRelativeFilePath,\n identifier,\n configuration,\n } = integrationDef\n\n if (iconRelativeFilePath && !iconRelativeFilePath.toLowerCase().endsWith('.svg')) {\n throw new errors.BotpressCLIError('Icon must be an SVG file')\n }\n\n const iconFileContent = await this._readMediaFile('icon', iconRelativeFilePath)\n const readmeFileContent = await this._readMediaFile('readme', readmeRelativeFilePath)\n const identifierExtractScriptFileContent = await this._readFile(identifier?.extractScript)\n const fallbackHandlerScriptFileContent = await this._readFile(identifier?.fallbackHandlerScript)\n const identifierLinkTemplateFileContent = await this._readFile(configuration?.identifier?.linkTemplateScript)\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 let createBody: CreateIntegrationBody = prepareCreateIntegrationBody(integrationDef)\n createBody = {\n ...createBody,\n code,\n icon: iconFileContent,\n readme: readmeFileContent,\n configuration: {\n ...createBody.configuration,\n identifier: {\n ...(createBody.configuration?.identifier ?? {}),\n linkTemplateScript: identifierLinkTemplateFileContent,\n },\n },\n identifier: {\n extractScript: identifierExtractScriptFileContent,\n fallbackHandlerScript: fallbackHandlerScriptFileContent,\n },\n }\n\n const startedMessage = `Deploying integration ${chalk.bold(integrationDef.name)} v${integrationDef.version}...`\n const successMessage = 'Integration deployed'\n if (integration) {\n const updateBody = prepareUpdateIntegrationBody(\n {\n id: integration.id,\n ...createBody,\n },\n integration\n )\n\n const { secrets: knownSecrets } = integration\n updateBody.secrets = await this.promptSecrets(integrationDef, this.argv, { knownSecrets })\n this._detectDeprecatedFeatures(integrationDef, { allowDeprecated: true })\n\n const line = this.logger.line()\n line.started(startedMessage)\n await api.client.updateIntegration(updateBody).catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, `Could not update integration \"${integrationDef.name}\"`)\n })\n line.success(successMessage)\n } else {\n const createSecrets = await this.promptSecrets(integrationDef, this.argv)\n createBody.secrets = utils.records.filterValues(createSecrets, utils.guards.is.notNull)\n this._detectDeprecatedFeatures(integrationDef, this.argv)\n\n const line = this.logger.line()\n line.started(startedMessage)\n await api.client.createIntegration(createBody).catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, `Could not create integration \"${integrationDef.name}\"`)\n })\n line.success(successMessage)\n }\n }\n\n private _detectDeprecatedFeatures(\n integrationDef: sdk.IntegrationDefinition,\n opts: { allowDeprecated?: boolean } = {}\n ) {\n const deprecatedFields: string[] = []\n const { user, channels } = integrationDef\n if (user?.creation?.enabled) {\n deprecatedFields.push('user.creation')\n }\n\n for (const [channelName, channel] of Object.entries(channels ?? {})) {\n if (channel?.conversation?.creation?.enabled) {\n deprecatedFields.push(`channels.${channelName}.creation`)\n }\n }\n\n if (!deprecatedFields.length) {\n return\n }\n\n const errorMessage = `The following fields of the integration's definition are deprecated: ${deprecatedFields.join(\n ', '\n )}`\n\n if (opts.allowDeprecated) {\n this.logger.warn(errorMessage)\n } else {\n throw new errors.BotpressCLIError(errorMessage)\n }\n }\n\n private _readFile = async (filePath: string | undefined): 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, 'utf-8').catch((thrown) => {\n throw errors.BotpressCLIError.wrap(thrown, `Could not read file \"${absoluteFilePath}\"`)\n })\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: sdk.Bot }>(outfile)\n\n let bot: client.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 integrationInstances = await this.fetchBotIntegrationInstances(botImpl, api)\n const updateBotBody = prepareUpdateBotBody(\n {\n ...prepareCreateBotBody(botImpl),\n id: bot.id,\n code,\n integrations: integrationInstances,\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<client.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<client.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
  }
@@ -56,7 +56,8 @@ class DevCommand extends import_project_command.ProjectCommand {
56
56
  if (this._initialDef) {
57
57
  defaultPort = DEFAULT_INTEGRATION_PORT;
58
58
  const secretEnvVariables = await this.promptSecrets(this._initialDef, this.argv, { formatEnv: true });
59
- env = { ...env, ...secretEnvVariables };
59
+ const nonNullSecretEnvVariables = utils.records.filterValues(secretEnvVariables, utils.guards.is.notNull);
60
+ env = { ...env, ...nonNullSecretEnvVariables };
60
61
  }
61
62
  const port = this.argv.port ?? defaultPort;
62
63
  const urlParseResult = utils.url.parse(this.argv.tunnelUrl);
@@ -207,13 +208,13 @@ class DevCommand extends import_project_command.ProjectCommand {
207
208
  }
208
209
  const line = this.logger.line();
209
210
  line.started(`Deploying dev integration ${import_chalk.default.bold(integrationDef.name)}...`);
210
- const integrationBody = {
211
- ...this.prepareIntegrationDefinition(integrationDef),
211
+ const createIntegrationBody = {
212
+ ...(0, import_integration_body.prepareCreateIntegrationBody)(integrationDef),
212
213
  url: externalUrl
213
214
  };
214
215
  if (integration) {
215
216
  const updateIntegrationBody = (0, import_integration_body.prepareUpdateIntegrationBody)(
216
- { ...integrationBody, id: integration.id },
217
+ { ...createIntegrationBody, id: integration.id },
217
218
  integration
218
219
  );
219
220
  const resp = await api.client.updateIntegration(updateIntegrationBody).catch((thrown) => {
@@ -221,7 +222,7 @@ class DevCommand extends import_project_command.ProjectCommand {
221
222
  });
222
223
  integration = resp.integration;
223
224
  } else {
224
- const resp = await api.client.createIntegration({ ...integrationBody, dev: true }).catch((thrown) => {
225
+ const resp = await api.client.createIntegration({ ...createIntegrationBody, dev: true }).catch((thrown) => {
225
226
  throw errors.BotpressCLIError.wrap(thrown, `Could not deploy dev integration "${integrationDef.name}"`);
226
227
  });
227
228
  integration = resp.integration;
@@ -263,12 +264,13 @@ class DevCommand extends import_project_command.ProjectCommand {
263
264
  const { default: botImpl } = utils.require.requireJsFile(outfile);
264
265
  const updateLine = this.logger.line();
265
266
  updateLine.started("Deploying dev bot...");
267
+ const integrationInstances = await this.fetchBotIntegrationInstances(botImpl, api);
266
268
  const updateBotBody = (0, import_bot_body.prepareUpdateBotBody)(
267
269
  {
270
+ ...(0, import_bot_body.prepareCreateBotBody)(botImpl),
268
271
  id: bot.id,
269
272
  url: externalUrl,
270
- ...this.prepareBot(botImpl),
271
- ...await this.prepareBotIntegrationInstances(botImpl, api)
273
+ integrations: integrationInstances
272
274
  },
273
275
  bot
274
276
  );
@@ -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 // TODO: store secrets in local cache to avoid prompting every time\n const secretEnvVariables = await this.promptSecrets(this._initialDef, this.argv, { formatEnv: true })\n env = { ...env, ...secretEnvVariables }\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(() => {\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 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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",
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 * as pathlib from 'path'\nimport * as uuid from 'uuid'\nimport { prepareCreateBotBody, prepareUpdateBotBody } from '../api/bot-body'\nimport type { ApiClient } from '../api/client'\nimport {\n prepareUpdateIntegrationBody,\n CreateIntegrationBody,\n prepareCreateIntegrationBody,\n} 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: sdk.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 // TODO: store secrets in local cache to avoid prompting every time\n const secretEnvVariables = await this.promptSecrets(this._initialDef, 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 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(() => {\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 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: sdk.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: 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: CreateIntegrationBody = {\n ...prepareCreateIntegrationBody(integrationDef),\n url: externalUrl,\n }\n\n if (integration) {\n const updateIntegrationBody = 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}\"`)\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: 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.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: sdk.Bot }>(outfile)\n\n const updateLine = this.logger.line()\n updateLine.started('Deploying dev bot...')\n\n const integrationInstances = await this.fetchBotIntegrationInstances(botImpl, api)\n const updateBotBody = prepareUpdateBotBody(\n {\n ...prepareCreateBotBody(botImpl),\n id: bot.id,\n url: externalUrl,\n integrations: integrationInstances,\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
  }