@botpress/cli 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build.ts +12 -0
- package/dist/app/api-utils.js +105 -0
- package/dist/app/base.js +35 -0
- package/dist/app/cache.js +95 -0
- package/dist/app/errors.js +145 -0
- package/dist/app/esbuild.js +89 -0
- package/dist/app/generator/action.js +76 -0
- package/dist/app/generator/channel.js +51 -0
- package/dist/app/generator/configuration.js +40 -0
- package/dist/app/generator/const.js +31 -0
- package/dist/app/generator/event.js +47 -0
- package/dist/app/generator/index.js +83 -0
- package/dist/app/generator/integration-impl.js +147 -0
- package/dist/app/generator/integration-instance.js +85 -0
- package/dist/app/generator/message.js +47 -0
- package/dist/app/generator/module.js +115 -0
- package/dist/app/generator/strings.js +38 -0
- package/dist/app/generator/typings.js +16 -0
- package/dist/app/index.js +68 -0
- package/dist/app/integration-ref.js +61 -0
- package/dist/app/project.js +502 -0
- package/dist/app/typings.js +16 -0
- package/dist/app/user.js +198 -0
- package/dist/config.js +245 -0
- package/dist/const.js +87 -0
- package/dist/index.js +276 -0
- package/dist/index.js.map +7 -0
- package/dist/init.js +45 -0
- package/dist/init.js.map +7 -0
- package/dist/logger/base-logger.js +159 -0
- package/dist/logger/index.js +79 -0
- package/dist/paths.js +69 -0
- package/dist/requires.js +49 -0
- package/dist/type-utils.js +16 -0
- package/dist/worker/child-entrypoint.js +61 -0
- package/dist/worker/config.js +58 -0
- package/dist/worker/index.js +55 -0
- package/dist/worker/is-child.js +52 -0
- package/dist/worker/listen-child.js +89 -0
- package/init.js +1 -0
- package/package.json +54 -0
- package/readme.md +24 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
25
|
+
var integration_ref_exports = {};
|
|
26
|
+
__export(integration_ref_exports, {
|
|
27
|
+
formatIntegrationRef: () => formatIntegrationRef,
|
|
28
|
+
parseIntegrationRef: () => parseIntegrationRef
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(integration_ref_exports);
|
|
31
|
+
var import_semver = __toESM(require("semver"));
|
|
32
|
+
var uuid = __toESM(require("uuid"));
|
|
33
|
+
const LATEST_TAG = "latest";
|
|
34
|
+
const formatIntegrationRef = (ref) => {
|
|
35
|
+
if (ref.type === "id") {
|
|
36
|
+
return ref.id;
|
|
37
|
+
}
|
|
38
|
+
return `${ref.name}@${ref.version}`;
|
|
39
|
+
};
|
|
40
|
+
const parseIntegrationRef = (ref) => {
|
|
41
|
+
if (uuid.validate(ref)) {
|
|
42
|
+
return { type: "id", id: ref };
|
|
43
|
+
}
|
|
44
|
+
if (!ref.includes("@")) {
|
|
45
|
+
return { type: "name", name: ref, version: LATEST_TAG };
|
|
46
|
+
}
|
|
47
|
+
const [name, version] = ref.split("@");
|
|
48
|
+
if (!name || !version) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const cleanedVersion = version === LATEST_TAG ? version : import_semver.default.clean(version);
|
|
52
|
+
if (!cleanedVersion) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
return { type: "name", name, version: cleanedVersion };
|
|
56
|
+
};
|
|
57
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
58
|
+
0 && (module.exports = {
|
|
59
|
+
formatIntegrationRef,
|
|
60
|
+
parseIntegrationRef
|
|
61
|
+
});
|
|
@@ -0,0 +1,502 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
25
|
+
var project_exports = {};
|
|
26
|
+
__export(project_exports, {
|
|
27
|
+
ProjectCommands: () => ProjectCommands,
|
|
28
|
+
ProjectPaths: () => ProjectPaths
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(project_exports);
|
|
31
|
+
var bpclient = __toESM(require("@botpress/client"));
|
|
32
|
+
var import_bluebird = __toESM(require("bluebird"));
|
|
33
|
+
var import_chalk = __toESM(require("chalk"));
|
|
34
|
+
var import_fs = __toESM(require("fs"));
|
|
35
|
+
var import_lodash = __toESM(require("lodash"));
|
|
36
|
+
var import_path = __toESM(require("path"));
|
|
37
|
+
var import_prompts = __toESM(require("prompts"));
|
|
38
|
+
var consts = __toESM(require("../const"));
|
|
39
|
+
var pathutils = __toESM(require("../paths"));
|
|
40
|
+
var requireutils = __toESM(require("../requires"));
|
|
41
|
+
var import_worker = require("../worker");
|
|
42
|
+
var import_api_utils = require("./api-utils");
|
|
43
|
+
var import_base = require("./base");
|
|
44
|
+
var errors = __toESM(require("./errors"));
|
|
45
|
+
var esbuild = __toESM(require("./esbuild"));
|
|
46
|
+
var generator = __toESM(require("./generator"));
|
|
47
|
+
var import_integration_ref = require("./integration-ref");
|
|
48
|
+
class ProjectPaths {
|
|
49
|
+
abs;
|
|
50
|
+
rel;
|
|
51
|
+
static from(paths, overrides) {
|
|
52
|
+
const rel = { ...paths.rel, ...overrides };
|
|
53
|
+
return new ProjectPaths(rel);
|
|
54
|
+
}
|
|
55
|
+
constructor({ workDir, definition, entryPoint: entrypoint, outDir }) {
|
|
56
|
+
const absWorkdir = pathutils.absoluteFrom(pathutils.cwd(), workDir);
|
|
57
|
+
const absDefinition = pathutils.absoluteFrom(absWorkdir, definition);
|
|
58
|
+
const absEntrypoint = pathutils.absoluteFrom(absWorkdir, entrypoint);
|
|
59
|
+
const absOutdir = pathutils.absoluteFrom(absWorkdir, outDir);
|
|
60
|
+
this.abs = { workDir: absWorkdir, definition: absDefinition, entryPoint: absEntrypoint, outDir: absOutdir };
|
|
61
|
+
const relDefinition = pathutils.relativeFrom(this.abs.workDir, this.abs.definition);
|
|
62
|
+
const relEntrypoint = pathutils.relativeFrom(this.abs.workDir, this.abs.entryPoint);
|
|
63
|
+
const relOutdir = pathutils.relativeFrom(this.abs.workDir, this.abs.outDir);
|
|
64
|
+
const relWorkdir = ".";
|
|
65
|
+
this.rel = { workDir: relWorkdir, definition: relDefinition, entryPoint: relEntrypoint, outDir: relOutdir };
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
const ENTRY_CODE = (entrypoint) => {
|
|
69
|
+
const unixPath = pathutils.toUnix(entrypoint);
|
|
70
|
+
const importFrom = pathutils.rmExtension(unixPath);
|
|
71
|
+
return `
|
|
72
|
+
import x from './${importFrom}'
|
|
73
|
+
export default x
|
|
74
|
+
export const handler = x.handler
|
|
75
|
+
`;
|
|
76
|
+
};
|
|
77
|
+
class ProjectCommands extends import_base.BaseCommands {
|
|
78
|
+
constructor(_props, _paths, _projectCache, _userCache, logger) {
|
|
79
|
+
super(logger);
|
|
80
|
+
this._props = _props;
|
|
81
|
+
this._paths = _paths;
|
|
82
|
+
this._projectCache = _projectCache;
|
|
83
|
+
this._userCache = _userCache;
|
|
84
|
+
}
|
|
85
|
+
async installIntegration(integrationRef, argv) {
|
|
86
|
+
const integrationDef = await this._readIntegrationDefinitionFromFS();
|
|
87
|
+
if (integrationDef) {
|
|
88
|
+
throw new errors.ExclusiveBotFeatureError();
|
|
89
|
+
}
|
|
90
|
+
const api = await this._ensureLoginAndCreateClient(argv);
|
|
91
|
+
const parsedRef = (0, import_integration_ref.parseIntegrationRef)(integrationRef);
|
|
92
|
+
if (!parsedRef) {
|
|
93
|
+
throw new errors.InvalidIntegrationReferenceError(integrationRef);
|
|
94
|
+
}
|
|
95
|
+
const integration = await api.findIntegration(parsedRef);
|
|
96
|
+
if (!integration) {
|
|
97
|
+
throw new errors.BotpressCLIError(`Integration "${integrationRef}" not found`);
|
|
98
|
+
}
|
|
99
|
+
const allInstances = await this._listIntegrationInstances();
|
|
100
|
+
const existingInstance = allInstances.find((i) => i.name === integration.name);
|
|
101
|
+
if (existingInstance) {
|
|
102
|
+
this._logger.warn(`Integration with name "${integration.name}" already installed.`);
|
|
103
|
+
const res = await this._confirm("Do you want to overwrite the existing instance?");
|
|
104
|
+
if (!res) {
|
|
105
|
+
this._logger.log("Aborted");
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
await this._uninstallIntegration(existingInstance);
|
|
109
|
+
}
|
|
110
|
+
await this._generateIntegrationInstance(integration);
|
|
111
|
+
}
|
|
112
|
+
async buildProject(argv) {
|
|
113
|
+
const { abs } = this._paths;
|
|
114
|
+
const t0 = Date.now();
|
|
115
|
+
const integrationDef = await this._readIntegrationDefinitionFromFS();
|
|
116
|
+
if (integrationDef) {
|
|
117
|
+
await this._generateImplementationTypings(integrationDef);
|
|
118
|
+
await import_fs.default.promises.writeFile(consts.defDataOutfile(abs.outDir), JSON.stringify(integrationDef, void 0, 2));
|
|
119
|
+
}
|
|
120
|
+
await this.bundleProject(argv);
|
|
121
|
+
const dt = Date.now() - t0;
|
|
122
|
+
this._logger.log(`Build completed in ${dt}ms`);
|
|
123
|
+
}
|
|
124
|
+
async serveProject(argv) {
|
|
125
|
+
const { abs } = this._paths;
|
|
126
|
+
const outfile = consts.outfile(abs.outDir);
|
|
127
|
+
if (!import_fs.default.existsSync(outfile)) {
|
|
128
|
+
throw new errors.NoBundleFoundError();
|
|
129
|
+
}
|
|
130
|
+
const isIntegration = !!await this._readIntegrationDefinitionFromFS();
|
|
131
|
+
this._logger.log(`Serving ${isIntegration ? "integration" : "bot"}...`);
|
|
132
|
+
const { default: serveable } = requireutils.requireJsFile(outfile);
|
|
133
|
+
return serveable.start(argv.port);
|
|
134
|
+
}
|
|
135
|
+
async bundleProject(_argv) {
|
|
136
|
+
const integrationDef = await this._readIntegrationDefinitionFromFS();
|
|
137
|
+
const { rel, abs } = this._paths;
|
|
138
|
+
const line = this._logger.line();
|
|
139
|
+
const logLevel = this._props.verbose ? "info" : "silent";
|
|
140
|
+
try {
|
|
141
|
+
if (integrationDef) {
|
|
142
|
+
const { name } = integrationDef;
|
|
143
|
+
line.started(`Bundling integration ${import_chalk.default.bold(name)}...`);
|
|
144
|
+
} else {
|
|
145
|
+
line.started("Bundling bot...");
|
|
146
|
+
}
|
|
147
|
+
const code = ENTRY_CODE(rel.entryPoint);
|
|
148
|
+
const outfile = consts.outfile(rel.outDir);
|
|
149
|
+
line.debug(`Writing bundle to ${outfile}`);
|
|
150
|
+
await esbuild.buildCode({ code, cwd: abs.workDir, outfile, logLevel, write: true });
|
|
151
|
+
line.success(`Bundle available at ${import_chalk.default.grey(rel.outDir)}`);
|
|
152
|
+
} finally {
|
|
153
|
+
line.commit();
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
async generateTypings(_argv) {
|
|
157
|
+
const integrationDefinition = await this._readIntegrationDefinitionFromFS();
|
|
158
|
+
if (!integrationDefinition) {
|
|
159
|
+
this._logger.warn("No typings to generate for bot");
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
return this._generateImplementationTypings(integrationDefinition);
|
|
163
|
+
}
|
|
164
|
+
async deployProject(argv) {
|
|
165
|
+
const api = await this._ensureLoginAndCreateClient(argv);
|
|
166
|
+
if (api.host !== consts.defaultBotpressApi) {
|
|
167
|
+
this._logger.log(`Using custom host ${api.host}`);
|
|
168
|
+
}
|
|
169
|
+
if (!argv.noBuild) {
|
|
170
|
+
await this.buildProject(argv);
|
|
171
|
+
}
|
|
172
|
+
const integrationDef = await this._readIntegrationDefinitionFromFS();
|
|
173
|
+
if (integrationDef) {
|
|
174
|
+
return this._deployIntegration(api, integrationDef);
|
|
175
|
+
}
|
|
176
|
+
return this._deployBot(api, argv.botId);
|
|
177
|
+
}
|
|
178
|
+
async devProject(argv) {
|
|
179
|
+
this._logger.warn("This command is experimental and subject to breaking changes without notice.");
|
|
180
|
+
const { abs } = this._paths;
|
|
181
|
+
const outfile = consts.outfile(abs.outDir);
|
|
182
|
+
if (!import_fs.default.existsSync(outfile)) {
|
|
183
|
+
throw new errors.NoBundleFoundError();
|
|
184
|
+
}
|
|
185
|
+
if (!argv.noBuild) {
|
|
186
|
+
await this.buildProject(argv);
|
|
187
|
+
}
|
|
188
|
+
const api = await this._ensureLoginAndCreateClient(argv);
|
|
189
|
+
const integrationDef = await this._readIntegrationDefinitionFromFS();
|
|
190
|
+
const { cleanup } = await this._createDevRessource(api, argv.url, integrationDef);
|
|
191
|
+
try {
|
|
192
|
+
const importPath = pathutils.toUnix(outfile);
|
|
193
|
+
const code = `require('${importPath}').default.start(${argv.port})`;
|
|
194
|
+
await (0, import_worker.spawnChildProcess)(
|
|
195
|
+
{
|
|
196
|
+
type: "code",
|
|
197
|
+
code,
|
|
198
|
+
env: {
|
|
199
|
+
BP_API_URL: api.host,
|
|
200
|
+
BP_TOKEN: api.token
|
|
201
|
+
}
|
|
202
|
+
},
|
|
203
|
+
this._logger
|
|
204
|
+
);
|
|
205
|
+
} finally {
|
|
206
|
+
this._logger.log("Cleaning up ressources...");
|
|
207
|
+
await cleanup();
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
async _createDevRessource(api, externalUrl, integrationDef) {
|
|
211
|
+
if (integrationDef) {
|
|
212
|
+
const { integration } = await api.client.createIntegration({
|
|
213
|
+
...integrationDef,
|
|
214
|
+
dev: true,
|
|
215
|
+
url: externalUrl
|
|
216
|
+
}).catch((thrown) => {
|
|
217
|
+
throw errors.BotpressCLIError.wrap(thrown, `Could not deploy dev integration "${integrationDef.name}"`);
|
|
218
|
+
});
|
|
219
|
+
this._logger.success(`Dev Integration created with id "${integration.id}"`);
|
|
220
|
+
return {
|
|
221
|
+
cleanup: () => api.client.deleteIntegration({ id: integration.id }).then(() => {
|
|
222
|
+
}).catch((thrown) => {
|
|
223
|
+
throw errors.BotpressCLIError.wrap(thrown, `Could not delete dev integration "${integrationDef.name}"`);
|
|
224
|
+
})
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
const { abs } = this._paths;
|
|
228
|
+
const outfile = consts.outfile(abs.outDir);
|
|
229
|
+
const {
|
|
230
|
+
default: { integrations: integrationList }
|
|
231
|
+
} = requireutils.requireJsFile(outfile);
|
|
232
|
+
const { bot: createdBot } = await api.client.createBot({
|
|
233
|
+
dev: true,
|
|
234
|
+
url: externalUrl
|
|
235
|
+
}).catch((thrown) => {
|
|
236
|
+
throw errors.BotpressCLIError.wrap(thrown, "Could not deploy dev bot");
|
|
237
|
+
});
|
|
238
|
+
const integrations = (0, import_lodash.default)(integrationList ?? []).keyBy((i) => i.id).mapValues(({ enabled, configuration }) => ({ enabled, configuration })).value();
|
|
239
|
+
this._logger.debug("Bot created, updating integrations...", { integrations });
|
|
240
|
+
const { bot: updatedBot } = await api.client.updateBot({ id: createdBot.id, integrations }).catch((thrown) => {
|
|
241
|
+
throw errors.BotpressCLIError.wrap(thrown, "Could not deploy dev bot");
|
|
242
|
+
});
|
|
243
|
+
this._logger.success(`Dev Bot created with id "${updatedBot.id}"`);
|
|
244
|
+
this._displayWebhookUrls(updatedBot);
|
|
245
|
+
return {
|
|
246
|
+
cleanup: () => api.client.deleteBot({ id: updatedBot.id }).then(() => {
|
|
247
|
+
}).catch((thrown) => {
|
|
248
|
+
throw errors.BotpressCLIError.wrap(thrown, "Could not delete dev bot");
|
|
249
|
+
})
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
async _deployIntegration(api, integrationDef) {
|
|
253
|
+
const { abs } = this._paths;
|
|
254
|
+
const outfile = consts.outfile(abs.outDir);
|
|
255
|
+
const code = await import_fs.default.promises.readFile(outfile, "utf-8");
|
|
256
|
+
const { name, version } = integrationDef;
|
|
257
|
+
const integration = await api.findIntegration({ type: "name", name, version });
|
|
258
|
+
let message;
|
|
259
|
+
if (integration) {
|
|
260
|
+
this._logger.warn("Integration already exists. If you decide to deploy, it will overwrite the existing one.");
|
|
261
|
+
message = `Are you sure you want to override integration ${integrationDef.name} v${integrationDef.version}?`;
|
|
262
|
+
} else {
|
|
263
|
+
message = `Are you sure you want to deploy integration ${integrationDef.name} v${integrationDef.version}?`;
|
|
264
|
+
}
|
|
265
|
+
const confirm = await this._confirm(message);
|
|
266
|
+
if (!confirm) {
|
|
267
|
+
this._logger.log("Aborted");
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
const line = this._logger.line();
|
|
271
|
+
try {
|
|
272
|
+
line.started(`Deploying integration ${import_chalk.default.bold(integrationDef.name)} v${integrationDef.version}...`);
|
|
273
|
+
if (integration) {
|
|
274
|
+
await api.client.updateIntegration({ id: integration.id, ...integrationDef, code });
|
|
275
|
+
} else {
|
|
276
|
+
await api.client.createIntegration({ ...integrationDef, code });
|
|
277
|
+
}
|
|
278
|
+
line.success("Integration deployed");
|
|
279
|
+
} catch (thrown) {
|
|
280
|
+
const action = integration ? "update" : "create";
|
|
281
|
+
throw errors.BotpressCLIError.wrap(thrown, `Could not ${action} integration "${integrationDef.name}"`);
|
|
282
|
+
} finally {
|
|
283
|
+
line.commit();
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
async _deployBot(api, botId) {
|
|
287
|
+
const { abs } = this._paths;
|
|
288
|
+
const outfile = consts.outfile(abs.outDir);
|
|
289
|
+
const code = await import_fs.default.promises.readFile(outfile, "utf-8");
|
|
290
|
+
const { default: botImpl } = requireutils.requireJsFile(outfile);
|
|
291
|
+
const { tags, states, integrations: integrationList } = botImpl;
|
|
292
|
+
const promptedBotId = await this._projectCache.sync("botId", botId, async (defaultId) => {
|
|
293
|
+
const userBots = await api.listAllPages(api.client.listBots, "bots").catch((thrown) => {
|
|
294
|
+
throw errors.BotpressCLIError.wrap(thrown, "Could not fetch existing bots");
|
|
295
|
+
});
|
|
296
|
+
if (!userBots.length) {
|
|
297
|
+
throw new errors.NoBotsFoundError();
|
|
298
|
+
}
|
|
299
|
+
const initial = userBots.find((bot) => bot.id === defaultId);
|
|
300
|
+
const { prompted } = await (0, import_prompts.default)({
|
|
301
|
+
type: "autocomplete",
|
|
302
|
+
name: "prompted",
|
|
303
|
+
message: "Which bot do you want to deploy?",
|
|
304
|
+
initial: initial?.name,
|
|
305
|
+
choices: userBots.map((bot) => ({ title: bot.name, value: bot.id }))
|
|
306
|
+
});
|
|
307
|
+
if (!prompted) {
|
|
308
|
+
throw new errors.ParamRequiredError("Bot Id");
|
|
309
|
+
}
|
|
310
|
+
return prompted;
|
|
311
|
+
});
|
|
312
|
+
const { bot: botInfo } = await api.client.getBot({ id: promptedBotId }).catch((thrown) => {
|
|
313
|
+
throw errors.BotpressCLIError.wrap(thrown, "Could not get bot info");
|
|
314
|
+
});
|
|
315
|
+
const integrationsToUninstall = (0, import_lodash.default)(botInfo.integrations).keys().filter((key) => !integrationList?.map((i) => i.id).includes(key)).zipObject().mapValues(() => null).value();
|
|
316
|
+
const integrationsToInstall = (0, import_lodash.default)(integrationList ?? []).keyBy((i) => i.id).mapValues(({ enabled, configuration }) => ({ enabled, configuration })).value();
|
|
317
|
+
const integrations = { ...integrationsToUninstall, ...integrationsToInstall };
|
|
318
|
+
const confirm = await this._confirm(`Are you sure you want to deploy bot ${botInfo.name} ?`);
|
|
319
|
+
if (!confirm) {
|
|
320
|
+
this._logger.log("Aborted");
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
const line = this._logger.line();
|
|
324
|
+
try {
|
|
325
|
+
line.started(`Deploying bot ${import_chalk.default.bold(botInfo.name)}...`);
|
|
326
|
+
const { bot: updatedBot } = await api.client.updateBot({
|
|
327
|
+
id: promptedBotId,
|
|
328
|
+
code,
|
|
329
|
+
states,
|
|
330
|
+
tags,
|
|
331
|
+
integrations
|
|
332
|
+
});
|
|
333
|
+
line.success("Bot deployed");
|
|
334
|
+
this._displayWebhookUrls(updatedBot);
|
|
335
|
+
} catch (thrown) {
|
|
336
|
+
throw errors.BotpressCLIError.wrap(thrown, "Could not update bot");
|
|
337
|
+
} finally {
|
|
338
|
+
line.commit();
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
_displayWebhookUrls(bot) {
|
|
342
|
+
if (!import_lodash.default.keys(bot.integrations).length) {
|
|
343
|
+
this._logger.log("No integrations in bot");
|
|
344
|
+
return;
|
|
345
|
+
}
|
|
346
|
+
this._logger.log("Integrations:");
|
|
347
|
+
for (const integration of Object.values(bot.integrations)) {
|
|
348
|
+
if (!integration.enabled) {
|
|
349
|
+
this._logger.log(`${import_chalk.default.grey(integration.name)} ${import_chalk.default.italic("(disabled)")}: ${integration.webhookUrl}`, {
|
|
350
|
+
prefix: { symbol: "\u25CB", indent: 2 }
|
|
351
|
+
});
|
|
352
|
+
} else {
|
|
353
|
+
this._logger.log(`${import_chalk.default.bold(integration.name)} : ${integration.webhookUrl}`, {
|
|
354
|
+
prefix: { symbol: "\u25CF", indent: 2 }
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
async _listIntegrationInstances() {
|
|
360
|
+
const { abs } = this._paths;
|
|
361
|
+
const installPath = consts.installDir(abs.outDir);
|
|
362
|
+
if (!import_fs.default.existsSync(installPath)) {
|
|
363
|
+
this._logger.debug("Install path does not exist. Skipping listing of integration instances");
|
|
364
|
+
return [];
|
|
365
|
+
}
|
|
366
|
+
const allFiles = await import_fs.default.promises.readdir(installPath);
|
|
367
|
+
const allPaths = allFiles.map((name) => import_path.default.join(installPath, name));
|
|
368
|
+
const directories = await import_bluebird.default.filter(allPaths, async (path) => {
|
|
369
|
+
const stat = await import_fs.default.promises.stat(path);
|
|
370
|
+
return stat.isDirectory();
|
|
371
|
+
});
|
|
372
|
+
let jsons = directories.map((root) => ({ root, json: import_path.default.join(root, generator.INTEGRATION_JSON) }));
|
|
373
|
+
jsons = jsons.filter(({ json: x }) => import_fs.default.existsSync(x));
|
|
374
|
+
return import_bluebird.default.map(jsons, async ({ root, json }) => {
|
|
375
|
+
const content = await import_fs.default.promises.readFile(json, "utf-8");
|
|
376
|
+
const { name, version, id } = JSON.parse(content);
|
|
377
|
+
const dirname = import_path.default.basename(root);
|
|
378
|
+
return {
|
|
379
|
+
dirname,
|
|
380
|
+
id,
|
|
381
|
+
name,
|
|
382
|
+
version
|
|
383
|
+
};
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
async _confirm(message) {
|
|
387
|
+
if (this._props.confirm) {
|
|
388
|
+
this._logger.debug(`Confirming automatically: ${message}`);
|
|
389
|
+
return true;
|
|
390
|
+
}
|
|
391
|
+
const { confirm } = await (0, import_prompts.default)({
|
|
392
|
+
type: "confirm",
|
|
393
|
+
name: "confirm",
|
|
394
|
+
message,
|
|
395
|
+
initial: false
|
|
396
|
+
});
|
|
397
|
+
if (!confirm) {
|
|
398
|
+
return false;
|
|
399
|
+
}
|
|
400
|
+
return true;
|
|
401
|
+
}
|
|
402
|
+
async _generateImplementationTypings(integrationDef) {
|
|
403
|
+
const line = this._logger.line();
|
|
404
|
+
const { name } = integrationDef;
|
|
405
|
+
line.started(`Generating typings for integration ${import_chalk.default.bold(name)}...`);
|
|
406
|
+
const { rel } = this._paths;
|
|
407
|
+
try {
|
|
408
|
+
const typingFiles = await generator.generateIntegrationImplementationTypings(
|
|
409
|
+
integrationDef,
|
|
410
|
+
consts.relativeToOutFolder.implementationTypings
|
|
411
|
+
);
|
|
412
|
+
const indexFile = await generator.generateIntegrationIndex(consts.relativeToOutFolder.implementationTypings);
|
|
413
|
+
const generatedFiles = [...typingFiles, indexFile];
|
|
414
|
+
await this._writeFilesToOutFolder(generatedFiles);
|
|
415
|
+
line.success(`Typings available at ${import_chalk.default.grey(rel.outDir)}`);
|
|
416
|
+
} catch (thrown) {
|
|
417
|
+
throw errors.BotpressCLIError.wrap(thrown, "Could not generate typings");
|
|
418
|
+
} finally {
|
|
419
|
+
line.commit();
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
async _uninstallIntegration(instance) {
|
|
423
|
+
const { abs } = this._paths;
|
|
424
|
+
try {
|
|
425
|
+
const instancePath = import_path.default.join(consts.installDir(abs.outDir), instance.dirname);
|
|
426
|
+
await import_fs.default.promises.rm(instancePath, { recursive: true });
|
|
427
|
+
await this._generateBotIndex();
|
|
428
|
+
} catch (thrown) {
|
|
429
|
+
throw errors.BotpressCLIError.wrap(thrown, "Could not uninstall integration");
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
async _generateIntegrationInstance(integration) {
|
|
433
|
+
const line = this._logger.line();
|
|
434
|
+
const { name, version } = integration;
|
|
435
|
+
line.started(`Installing ${import_chalk.default.bold(name)} v${version}...`);
|
|
436
|
+
const { rel } = this._paths;
|
|
437
|
+
try {
|
|
438
|
+
const instanceFiles = await generator.generateIntegrationInstance(
|
|
439
|
+
integration,
|
|
440
|
+
consts.relativeToOutFolder.installDir
|
|
441
|
+
);
|
|
442
|
+
await this._writeFilesToOutFolder(instanceFiles);
|
|
443
|
+
await this._generateBotIndex();
|
|
444
|
+
line.success(`Installed integration available at ${import_chalk.default.grey(rel.outDir)}`);
|
|
445
|
+
} catch (thrown) {
|
|
446
|
+
throw errors.BotpressCLIError.wrap(thrown, "Could not install integration");
|
|
447
|
+
} finally {
|
|
448
|
+
line.commit();
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
async _generateBotIndex() {
|
|
452
|
+
const allInstances = await this._listIntegrationInstances();
|
|
453
|
+
const indexFile = await generator.generateBotIndex(
|
|
454
|
+
consts.relativeToOutFolder.installDir,
|
|
455
|
+
allInstances.map((i) => i.dirname)
|
|
456
|
+
);
|
|
457
|
+
await this._writeFilesToOutFolder([indexFile]);
|
|
458
|
+
}
|
|
459
|
+
async _writeFilesToOutFolder(files) {
|
|
460
|
+
const { abs } = this._paths;
|
|
461
|
+
for (const file of files) {
|
|
462
|
+
const filePath = pathutils.absoluteFrom(abs.outDir, file.path);
|
|
463
|
+
const dirPath = import_path.default.dirname(filePath);
|
|
464
|
+
await import_fs.default.promises.mkdir(dirPath, { recursive: true });
|
|
465
|
+
await import_fs.default.promises.writeFile(filePath, file.content);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
async _readIntegrationDefinitionFromFS() {
|
|
469
|
+
const { abs, rel } = this._paths;
|
|
470
|
+
if (!import_fs.default.existsSync(abs.definition)) {
|
|
471
|
+
this._logger.debug(`Integration definition not found at ${rel.definition}`);
|
|
472
|
+
return;
|
|
473
|
+
}
|
|
474
|
+
const { outputFiles } = await esbuild.buildEntrypoint({
|
|
475
|
+
cwd: abs.workDir,
|
|
476
|
+
outfile: "",
|
|
477
|
+
entrypoint: rel.definition,
|
|
478
|
+
write: false
|
|
479
|
+
});
|
|
480
|
+
const artifact = outputFiles[0];
|
|
481
|
+
if (!artifact) {
|
|
482
|
+
throw new errors.BotpressCLIError("Could not read integration definition");
|
|
483
|
+
}
|
|
484
|
+
const { default: definition } = requireutils.requireJsCode(artifact.text);
|
|
485
|
+
return definition;
|
|
486
|
+
}
|
|
487
|
+
async _ensureLoginAndCreateClient(argv) {
|
|
488
|
+
const token = await this._userCache.get("token");
|
|
489
|
+
const workspaceId = argv.workspaceId ?? await this._userCache.get("workspaceId");
|
|
490
|
+
const host = argv.host ?? await this._userCache.get("host");
|
|
491
|
+
if (!(token && workspaceId && host)) {
|
|
492
|
+
throw new errors.NotLoggedInError();
|
|
493
|
+
}
|
|
494
|
+
const client = new bpclient.Client({ host, token, workspaceId });
|
|
495
|
+
return new import_api_utils.ApiUtils(client, host, token, workspaceId, this._logger);
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
499
|
+
0 && (module.exports = {
|
|
500
|
+
ProjectCommands,
|
|
501
|
+
ProjectPaths
|
|
502
|
+
});
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __copyProps = (to, from, except, desc) => {
|
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
+
for (let key of __getOwnPropNames(from))
|
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
}
|
|
12
|
+
return to;
|
|
13
|
+
};
|
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
var typings_exports = {};
|
|
16
|
+
module.exports = __toCommonJS(typings_exports);
|