@botonic/nx-plugin 2.23.0

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 (206) hide show
  1. package/CHANGELOG.md +420 -0
  2. package/README.md +279 -0
  3. package/executors.json +55 -0
  4. package/generators.json +61 -0
  5. package/migrations.json +40 -0
  6. package/package.json +54 -0
  7. package/src/cursor-commands/update-bot.md +114 -0
  8. package/src/cursor-commands/update-botonic.md +63 -0
  9. package/src/executors/build-node-app/executor.d.ts +5 -0
  10. package/src/executors/build-node-app/executor.js +65 -0
  11. package/src/executors/build-node-app/schema.d.js +16 -0
  12. package/src/executors/build-node-app/schema.json +25 -0
  13. package/src/executors/delete-bot/executor.d.ts +5 -0
  14. package/src/executors/delete-bot/executor.js +112 -0
  15. package/src/executors/delete-bot/schema.d.js +16 -0
  16. package/src/executors/delete-bot/schema.json +35 -0
  17. package/src/executors/deploy-local-runtime/executor.d.ts +5 -0
  18. package/src/executors/deploy-local-runtime/executor.js +144 -0
  19. package/src/executors/deploy-local-runtime/schema.d.js +16 -0
  20. package/src/executors/deploy-local-runtime/schema.json +34 -0
  21. package/src/executors/deploy-netlify-snapshot/executor.d.ts +8 -0
  22. package/src/executors/deploy-netlify-snapshot/executor.js +79 -0
  23. package/src/executors/deploy-netlify-snapshot/schema.d.js +16 -0
  24. package/src/executors/deploy-netlify-snapshot/schema.json +31 -0
  25. package/src/executors/deploy-to-hubtype/executor.d.ts +5 -0
  26. package/src/executors/deploy-to-hubtype/executor.js +308 -0
  27. package/src/executors/deploy-to-hubtype/schema.d.js +16 -0
  28. package/src/executors/deploy-to-hubtype/schema.json +31 -0
  29. package/src/executors/e2e-webchat/botonic-package-publish.spec.ts +84 -0
  30. package/src/executors/e2e-webchat/executor.d.ts +5 -0
  31. package/src/executors/e2e-webchat/executor.js +134 -0
  32. package/src/executors/e2e-webchat/schema.d.js +16 -0
  33. package/src/executors/e2e-webchat/schema.json +35 -0
  34. package/src/executors/integrate-provider/executor.d.ts +5 -0
  35. package/src/executors/integrate-provider/executor.js +155 -0
  36. package/src/executors/integrate-provider/schema.d.js +16 -0
  37. package/src/executors/integrate-provider/schema.json +30 -0
  38. package/src/executors/login-to-hubtype/executor.d.ts +5 -0
  39. package/src/executors/login-to-hubtype/executor.js +79 -0
  40. package/src/executors/login-to-hubtype/schema.d.js +16 -0
  41. package/src/executors/login-to-hubtype/schema.json +25 -0
  42. package/src/executors/logout-from-hubtype/executor.d.ts +3 -0
  43. package/src/executors/logout-from-hubtype/executor.js +54 -0
  44. package/src/executors/logout-from-hubtype/schema.d.js +16 -0
  45. package/src/executors/logout-from-hubtype/schema.json +9 -0
  46. package/src/executors/run-lambda/executor.d.ts +5 -0
  47. package/src/executors/run-lambda/executor.js +65 -0
  48. package/src/executors/run-lambda/schema.d.js +16 -0
  49. package/src/executors/run-lambda/schema.json +20 -0
  50. package/src/executors/serve-bot/executor.d.ts +5 -0
  51. package/src/executors/serve-bot/executor.js +330 -0
  52. package/src/executors/serve-bot/schema.d.js +16 -0
  53. package/src/executors/serve-bot/schema.json +40 -0
  54. package/src/generators/action/files/__name__.spec.ts.template +15 -0
  55. package/src/generators/action/files/__name__.ts.template +15 -0
  56. package/src/generators/action/generator.d.ts +4 -0
  57. package/src/generators/action/generator.js +112 -0
  58. package/src/generators/action/schema.d.ts +7 -0
  59. package/src/generators/action/schema.js +16 -0
  60. package/src/generators/action/schema.json +43 -0
  61. package/src/generators/bot-app/files/.eslintrc.json.template +18 -0
  62. package/src/generators/bot-app/files/README.md.template +148 -0
  63. package/src/generators/bot-app/files/src/client/custom-messages/index.ts.template +2 -0
  64. package/src/generators/bot-app/files/src/client/webchat/index.html.template +35 -0
  65. package/src/generators/bot-app/files/src/client/webchat/index.tsx.template +107 -0
  66. package/src/generators/bot-app/files/src/client/webchat/styles.css.template +17 -0
  67. package/src/generators/bot-app/files/src/client/webchat/webchat-tokens-overrides.css.template +2 -0
  68. package/src/generators/bot-app/files/src/client/webviews/app.tsx.template +8 -0
  69. package/src/generators/bot-app/files/src/client/webviews/index.html.template +32 -0
  70. package/src/generators/bot-app/files/src/client/webviews/index.tsx.template +18 -0
  71. package/src/generators/bot-app/files/src/server/bot/actions/index.ts.template +2 -0
  72. package/src/generators/bot-app/files/src/server/bot/actions/not-found.ts.template +13 -0
  73. package/src/generators/bot-app/files/src/server/bot/actions/welcome.ts.template +13 -0
  74. package/src/generators/bot-app/files/src/server/bot/index.ts.template +43 -0
  75. package/src/generators/bot-app/files/src/server/bot/plugins/ai-agents/index.ts.template +30 -0
  76. package/src/generators/bot-app/files/src/server/bot/plugins/flow-builder/index.ts.template +28 -0
  77. package/src/generators/bot-app/files/src/server/bot/plugins/index.ts.template +11 -0
  78. package/src/generators/bot-app/files/src/server/bot/routes.ts.template +23 -0
  79. package/src/generators/bot-app/files/src/server/bot/tools/index.ts.template +5 -0
  80. package/src/generators/bot-app/files/src/server/bot/tracking.ts.template +35 -0
  81. package/src/generators/bot-app/files/src/server/bot/types.ts.template +4 -0
  82. package/src/generators/bot-app/files/src/server/bot/utils.ts.template +9 -0
  83. package/src/generators/bot-app/files/src/server/lambda/handler.js.template +24 -0
  84. package/src/generators/bot-app/files/src/server/lambda/package.json +20 -0
  85. package/src/generators/bot-app/files/src/server/lambda/template.yaml.template +20 -0
  86. package/src/generators/bot-app/files/src/shared/constants.ts.template +12 -0
  87. package/src/generators/bot-app/files/vite/base-client.config.ts.template +14 -0
  88. package/src/generators/bot-app/files/vite/base.config.ts.template +20 -0
  89. package/src/generators/bot-app/files/vite/build.config.ts.template +65 -0
  90. package/src/generators/bot-app/files/vite/node.config.ts.template +41 -0
  91. package/src/generators/bot-app/files/vite/plugins/move-html.plugin.ts.template +36 -0
  92. package/src/generators/bot-app/files/vite/webchat.config.ts.template +58 -0
  93. package/src/generators/bot-app/files/vite/webviews.config.ts.template +57 -0
  94. package/src/generators/bot-app/files/vite.config.ts.template +36 -0
  95. package/src/generators/bot-app/generator.d.ts +4 -0
  96. package/src/generators/bot-app/generator.js +294 -0
  97. package/src/generators/bot-app/schema.d.ts +6 -0
  98. package/src/generators/bot-app/schema.js +16 -0
  99. package/src/generators/bot-app/schema.json +36 -0
  100. package/src/generators/bot-app-migrations/migrate-fix-css-code-split/generator.d.ts +5 -0
  101. package/src/generators/bot-app-migrations/migrate-fix-css-code-split/generator.js +92 -0
  102. package/src/generators/bot-app-migrations/migrate-fix-css-code-split/schema.json +15 -0
  103. package/src/generators/bot-app-migrations/migrate-pnpm-compat/generator.d.ts +5 -0
  104. package/src/generators/bot-app-migrations/migrate-pnpm-compat/generator.js +97 -0
  105. package/src/generators/bot-app-migrations/migrate-pnpm-compat/schema.json +15 -0
  106. package/src/generators/bot-app-migrations/migrate-webchat-trigger/generator.d.ts +5 -0
  107. package/src/generators/bot-app-migrations/migrate-webchat-trigger/generator.js +165 -0
  108. package/src/generators/bot-app-migrations/migrate-webchat-trigger/schema.json +15 -0
  109. package/src/generators/custom-message/files/__name__-output.ts.template +21 -0
  110. package/src/generators/custom-message/files/__name__.spec.tsx.template +27 -0
  111. package/src/generators/custom-message/files/__name__.tsx.template +18 -0
  112. package/src/generators/custom-message/generator.d.ts +4 -0
  113. package/src/generators/custom-message/generator.js +235 -0
  114. package/src/generators/custom-message/schema.d.ts +7 -0
  115. package/src/generators/custom-message/schema.js +16 -0
  116. package/src/generators/custom-message/schema.json +44 -0
  117. package/src/generators/preset/files/.cursor/commands/update-bot.md +5 -0
  118. package/src/generators/preset/files/.cursor/commands/update-botonic.md +5 -0
  119. package/src/generators/preset/files/.cursor/scripts/update-bot/discover-bots.sh +67 -0
  120. package/src/generators/preset/files/.cursor/scripts/update-bot/find-migration-guides.sh +70 -0
  121. package/src/generators/preset/files/.cursor/skills/botonic-action/SKILL.md +167 -0
  122. package/src/generators/preset/files/.cursor/skills/botonic-custom-message/SKILL.md +231 -0
  123. package/src/generators/preset/files/.cursor/skills/botonic-webview/SKILL.md +179 -0
  124. package/src/generators/preset/files/.env.prod.template +2 -0
  125. package/src/generators/preset/files/.env.template +2 -0
  126. package/src/generators/preset/files/.npmrc.template +1 -0
  127. package/src/generators/preset/files/README.md.template +174 -0
  128. package/src/generators/preset/files/nx.json +66 -0
  129. package/src/generators/preset/files/package.json +26 -0
  130. package/src/generators/preset/files/tsconfig.base.json +27 -0
  131. package/src/generators/preset/files/tsconfig.base.json.template +27 -0
  132. package/src/generators/preset/files/tsconfig.json +9 -0
  133. package/src/generators/preset/generator.d.ts +4 -0
  134. package/src/generators/preset/generator.js +127 -0
  135. package/src/generators/preset/schema.d.ts +6 -0
  136. package/src/generators/preset/schema.js +16 -0
  137. package/src/generators/preset/schema.json +50 -0
  138. package/src/generators/remove-custom-message/generator.d.ts +4 -0
  139. package/src/generators/remove-custom-message/generator.js +259 -0
  140. package/src/generators/remove-custom-message/schema.d.ts +6 -0
  141. package/src/generators/remove-custom-message/schema.js +16 -0
  142. package/src/generators/remove-custom-message/schema.json +39 -0
  143. package/src/generators/shared/bot-app-utils.d.ts +25 -0
  144. package/src/generators/shared/bot-app-utils.js +209 -0
  145. package/src/generators/webview/files/__name__.spec.tsx.template +20 -0
  146. package/src/generators/webview/files/__name__.tsx.template +19 -0
  147. package/src/generators/webview/generator.d.ts +4 -0
  148. package/src/generators/webview/generator.js +179 -0
  149. package/src/generators/webview/schema.d.ts +5 -0
  150. package/src/generators/webview/schema.js +16 -0
  151. package/src/generators/webview/schema.json +34 -0
  152. package/src/index.d.ts +7 -0
  153. package/src/index.js +56 -0
  154. package/src/lib/api-service.d.ts +110 -0
  155. package/src/lib/api-service.js +591 -0
  156. package/src/lib/bot-config.d.ts +30 -0
  157. package/src/lib/bot-config.js +203 -0
  158. package/src/lib/cloudflared-tunnel.d.ts +29 -0
  159. package/src/lib/cloudflared-tunnel.js +95 -0
  160. package/src/lib/constants.d.ts +13 -0
  161. package/src/lib/constants.js +60 -0
  162. package/src/lib/credentials-handler.d.ts +40 -0
  163. package/src/lib/credentials-handler.js +115 -0
  164. package/src/lib/index.d.ts +10 -0
  165. package/src/lib/index.js +47 -0
  166. package/src/lib/interfaces.d.ts +49 -0
  167. package/src/lib/interfaces.js +16 -0
  168. package/src/lib/util/executor-helpers.d.ts +97 -0
  169. package/src/lib/util/executor-helpers.js +574 -0
  170. package/src/lib/util/file-system.d.ts +8 -0
  171. package/src/lib/util/file-system.js +65 -0
  172. package/src/lib/util/sam-container-cleanup.d.ts +11 -0
  173. package/src/lib/util/sam-container-cleanup.js +55 -0
  174. package/src/lib/util/sam-template.d.ts +9 -0
  175. package/src/lib/util/sam-template.js +71 -0
  176. package/src/lib/util/system.d.ts +1 -0
  177. package/src/lib/util/system.js +30 -0
  178. package/src/migrations/add-botonic-update-bots-skill/add-botonic-update-bots-skill.migration.d.ts +2 -0
  179. package/src/migrations/add-botonic-update-bots-skill/add-botonic-update-bots-skill.migration.js +52 -0
  180. package/src/migrations/add-botonic-update-bots-skill/add-botonic-update-bots-skill.migration.md +23 -0
  181. package/src/migrations/add-botonic-update-bots-skill/files/.cursor/commands/update-bot.md +5 -0
  182. package/src/migrations/add-botonic-update-bots-skill/files/.cursor/commands/update-botonic.md +5 -0
  183. package/src/migrations/add-botonic-update-bots-skill/files/.cursor/scripts/update-bot/discover-bots.sh +67 -0
  184. package/src/migrations/add-botonic-update-bots-skill/files/.cursor/scripts/update-bot/find-migration-guides.sh +70 -0
  185. package/src/migrations/add-botonic-update-bots-skill/schema.json +5 -0
  186. package/src/migrations/add-lilara-registry/add-lilara-registry.migration.d.ts +2 -0
  187. package/src/migrations/add-lilara-registry/add-lilara-registry.migration.js +49 -0
  188. package/src/migrations/add-lilara-registry/schema.json +5 -0
  189. package/src/migrations/fix-css-code-split/fix-css-code-split.migration.md +45 -0
  190. package/src/migrations/remove-codeartifact-registry/remove-codeartifact-registry.migration.d.ts +2 -0
  191. package/src/migrations/remove-codeartifact-registry/remove-codeartifact-registry.migration.js +59 -0
  192. package/src/migrations/remove-codeartifact-registry/schema.json +5 -0
  193. package/src/migrations/sync-pending-bot-migrations/schema.json +5 -0
  194. package/src/migrations/sync-pending-bot-migrations/sync-pending-bot-migrations.migration.d.ts +2 -0
  195. package/src/migrations/sync-pending-bot-migrations/sync-pending-bot-migrations.migration.js +137 -0
  196. package/src/migrations/sync-pending-bot-migrations/sync-pending-bot-migrations.migration.md +19 -0
  197. package/src/migrations/update-cursor-commands-to-stubs/schema.json +5 -0
  198. package/src/migrations/update-cursor-commands-to-stubs/update-cursor-commands-to-stubs.migration.d.ts +2 -0
  199. package/src/migrations/update-cursor-commands-to-stubs/update-cursor-commands-to-stubs.migration.js +61 -0
  200. package/src/migrations/update-pnpm-workspace-scripts/schema.json +4 -0
  201. package/src/migrations/update-pnpm-workspace-scripts/update-pnpm-workspace-scripts.migration.d.ts +2 -0
  202. package/src/migrations/update-pnpm-workspace-scripts/update-pnpm-workspace-scripts.migration.js +47 -0
  203. package/src/migrations/utils/migration-utils.d.ts +109 -0
  204. package/src/migrations/utils/migration-utils.js +448 -0
  205. package/src/plugin.d.ts +15 -0
  206. package/src/plugin.js +246 -0
@@ -0,0 +1,308 @@
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 __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var executor_exports = {};
20
+ __export(executor_exports, {
21
+ default: () => deployToHubtypeExecutor
22
+ });
23
+ module.exports = __toCommonJS(executor_exports);
24
+ var import_enquirer = require("enquirer");
25
+ var import_fs = require("fs");
26
+ var import_path = require("path");
27
+ var import_zip_a_folder = require("zip-a-folder");
28
+ var import_api_service = require("../../lib/api-service");
29
+ var import_bot_config = require("../../lib/bot-config");
30
+ var import_executor_helpers = require("../../lib/util/executor-helpers");
31
+ var import_file_system = require("../../lib/util/file-system");
32
+ var import_system = require("../../lib/util/system");
33
+ const BOTONIC_BUNDLE_FILE = "botonic_bundle.zip";
34
+ const BOTONIC_TEMP_DIRNAME = "tmp";
35
+ let PROJECT_ROOT;
36
+ async function deployToHubtypeExecutor(options, context) {
37
+ if (!context.projectName) {
38
+ throw new Error("Project name is not defined in executor context");
39
+ }
40
+ PROJECT_ROOT = (0, import_executor_helpers.resolveProjectPath)(context);
41
+ try {
42
+ const { targetEnvironment, environmentVariables } = (0, import_executor_helpers.resolveHubtypeEnvironment)(context, options);
43
+ const botonicApiService = new import_api_service.BotonicAPIService({
44
+ projectRoot: PROJECT_ROOT,
45
+ workspaceRoot: (0, import_path.resolve)(context.root),
46
+ environmentVariables,
47
+ targetEnvironment
48
+ });
49
+ const botName = options.botName;
50
+ if (!botonicApiService.oauth) {
51
+ if (options.email && options.password) {
52
+ await botonicApiService.login(options.email, options.password);
53
+ botonicApiService.saveAllCredentials();
54
+ } else {
55
+ await (0, import_executor_helpers.handleAuthentication)(botonicApiService);
56
+ }
57
+ }
58
+ await (0, import_executor_helpers.logWorkingAsAndEnvironment)(botonicApiService);
59
+ console.log(
60
+ `\u{1F680} Deploying to Hubtype... [${environmentVariables["VITE_HUBTYPE_API_URL"]}]
61
+ `
62
+ );
63
+ if (botName) {
64
+ await handleBotFromFlag(
65
+ botonicApiService,
66
+ botName,
67
+ options.createIfNotExists
68
+ );
69
+ } else {
70
+ await handleBotFlow(botonicApiService);
71
+ }
72
+ await deploy(botonicApiService, PROJECT_ROOT, context.projectName);
73
+ return { success: true };
74
+ } catch (error) {
75
+ return (0, import_executor_helpers.handleExecutorError)(error, "Deployment");
76
+ }
77
+ }
78
+ async function handleBotFromFlag(botonicApiService, botName, createIfNotExists) {
79
+ const bots = await (0, import_executor_helpers.getAvailableBots)(botonicApiService);
80
+ const bot = bots.find((b) => b.name === botName);
81
+ if (bot) {
82
+ botonicApiService.setCurrentBot(bot);
83
+ } else {
84
+ if (createIfNotExists) {
85
+ console.log(
86
+ `\u{1F916} Bot "${botName}" doesn't exist. Creating it automatically...`
87
+ );
88
+ await createNewBot(botonicApiService, botName);
89
+ } else {
90
+ const response = await (0, import_enquirer.prompt)({
91
+ type: "confirm",
92
+ name: "create_bot_confirm",
93
+ message: `\u{1F916} Bot "${botName}" doesn't exist. Do you want to create it?`
94
+ });
95
+ if (response.create_bot_confirm) {
96
+ await createNewBot(botonicApiService, botName);
97
+ } else {
98
+ throw new Error(`Bot "${botName}" not found`);
99
+ }
100
+ }
101
+ }
102
+ }
103
+ async function handleBotFlow(botonicApiService) {
104
+ if (!botonicApiService.bot || !Object.keys(botonicApiService.bot).length) {
105
+ await newBotFlow(botonicApiService);
106
+ } else {
107
+ const resp = await botonicApiService.getBots();
108
+ const bots = resp.data.results;
109
+ const firstId = botonicApiService.bot.id;
110
+ bots.sort(
111
+ (x, y) => x.id === firstId ? -1 : y.id === firstId ? 1 : 0
112
+ );
113
+ await selectExistentBot(botonicApiService, bots);
114
+ }
115
+ }
116
+ async function newBotFlow(botonicApiService) {
117
+ const bots = await (0, import_executor_helpers.getAvailableBots)(botonicApiService);
118
+ if (!bots.length) {
119
+ await createNewBot(botonicApiService);
120
+ } else {
121
+ const response = await (0, import_enquirer.prompt)({
122
+ type: "confirm",
123
+ name: "create_bot_confirm",
124
+ message: "\u{1F916} Do you want to create a new bot?"
125
+ });
126
+ if (response.create_bot_confirm) {
127
+ await createNewBot(botonicApiService);
128
+ } else {
129
+ await selectExistentBot(botonicApiService, bots);
130
+ }
131
+ }
132
+ }
133
+ async function createNewBot(botonicApiService, botName) {
134
+ if (botName) {
135
+ await (0, import_executor_helpers.createNewBotWithName)(botonicApiService, botName);
136
+ } else {
137
+ console.log("\u{1F916} Let's create a new bot!\n");
138
+ const response = await (0, import_enquirer.prompt)({
139
+ type: "input",
140
+ name: "bot_name",
141
+ message: "\u{1F916} Bot name:",
142
+ validate: (input) => {
143
+ return input.length > 0 ? true : "Bot name cannot be empty";
144
+ }
145
+ });
146
+ await (0, import_executor_helpers.createNewBotWithName)(botonicApiService, response.bot_name);
147
+ }
148
+ }
149
+ async function selectExistentBot(botonicApiService, bots) {
150
+ console.log("\u{1F4CB} Select a bot to deploy:\n");
151
+ const providersPromises = bots.map((b) => botonicApiService.getProviders(b.id));
152
+ const providers = await Promise.all(providersPromises);
153
+ const botsWithProviders = bots.map((bot2, index) => ({
154
+ ...bot2,
155
+ providers: providers[index].data.results
156
+ }));
157
+ const response = await (0, import_enquirer.prompt)({
158
+ type: "select",
159
+ name: "bot_name",
160
+ message: "\u{1F916} Please select a bot:",
161
+ choices: botsWithProviders.map((bot2) => {
162
+ return {
163
+ name: bot2.name,
164
+ message: bot2.name
165
+ };
166
+ })
167
+ });
168
+ const selectedBotName = response.bot_name;
169
+ const bot = botsWithProviders.find((bot2) => bot2.name === selectedBotName);
170
+ if (bot) {
171
+ botonicApiService.setCurrentBot(bot);
172
+ console.log(`\u2705 Selected bot: ${bot.name}`);
173
+ }
174
+ }
175
+ async function deploy(botonicApiService, projectRoot, projectName) {
176
+ console.log("\u{1F528} Preparing your bot for deployment...\n");
177
+ const buildOut = await botonicApiService.build({
178
+ projectRoot,
179
+ projectName
180
+ });
181
+ if (!buildOut) {
182
+ throw new Error("Build failed");
183
+ }
184
+ const botConfigJson = await import_bot_config.BotConfig.get(projectRoot);
185
+ await createBundle(projectRoot);
186
+ const { hasDeployErrors } = await deployBundle(
187
+ botonicApiService,
188
+ botConfigJson
189
+ );
190
+ await displayDeployResults(botonicApiService, { hasDeployErrors });
191
+ (0, import_fs.rmSync)((0, import_path.join)(projectRoot, BOTONIC_BUNDLE_FILE));
192
+ (0, import_file_system.removeRecursively)((0, import_path.join)(projectRoot, BOTONIC_TEMP_DIRNAME));
193
+ botonicApiService.saveAllCredentials();
194
+ }
195
+ async function createBundle(projectRoot) {
196
+ console.log("\u{1F4E6} Creating deployment bundle...");
197
+ if ((0, import_file_system.pathExists)((0, import_path.join)(projectRoot, BOTONIC_TEMP_DIRNAME))) {
198
+ (0, import_file_system.removeRecursively)((0, import_path.join)(projectRoot, BOTONIC_TEMP_DIRNAME));
199
+ }
200
+ const webchatHtmlPath = (0, import_path.join)(projectRoot, "dist", "webchat", "webchat.html");
201
+ const webchatIndexPath = (0, import_path.join)(projectRoot, "dist", "webchat", "index.html");
202
+ if ((0, import_file_system.pathExists)(webchatHtmlPath)) {
203
+ (0, import_fs.renameSync)(webchatHtmlPath, webchatIndexPath);
204
+ }
205
+ const webviewsHtmlPath = (0, import_path.join)(
206
+ projectRoot,
207
+ "dist",
208
+ "webviews",
209
+ "webviews.html"
210
+ );
211
+ const webviewsIndexPath = (0, import_path.join)(projectRoot, "dist", "webviews", "index.html");
212
+ if ((0, import_file_system.pathExists)(webviewsHtmlPath)) {
213
+ (0, import_fs.renameSync)(webviewsHtmlPath, webviewsIndexPath);
214
+ }
215
+ (0, import_file_system.createDir)((0, import_path.join)(projectRoot, BOTONIC_TEMP_DIRNAME));
216
+ (0, import_file_system.copy)(
217
+ (0, import_path.join)(projectRoot, "dist"),
218
+ (0, import_path.join)(projectRoot, BOTONIC_TEMP_DIRNAME, "dist")
219
+ );
220
+ const zipRes = await import_zip_a_folder.ZipAFolder.zip(
221
+ (0, import_path.join)(projectRoot, BOTONIC_TEMP_DIRNAME),
222
+ (0, import_path.join)(projectRoot, BOTONIC_BUNDLE_FILE)
223
+ );
224
+ if (zipRes instanceof Error) {
225
+ throw zipRes;
226
+ }
227
+ const zipStats = (0, import_fs.statSync)((0, import_path.join)(projectRoot, BOTONIC_BUNDLE_FILE));
228
+ console.log("\u2705 Bundle created successfully!");
229
+ if (zipStats.size >= 20 * 10 ** 6) {
230
+ throw new Error(
231
+ `Bundle too large: ${(zipStats.size / 1024 / 1024).toFixed(2)}MB (max: 20MB)`
232
+ );
233
+ }
234
+ }
235
+ async function deployBundle(botonicApiService, botConfigJson) {
236
+ console.log("\u{1F680} Deploying to Hubtype Cloud...");
237
+ try {
238
+ const deploy2 = await botonicApiService.deployBot(
239
+ (0, import_path.join)(PROJECT_ROOT, BOTONIC_BUNDLE_FILE),
240
+ botConfigJson
241
+ );
242
+ if (deploy2.response?.status === 403 || !deploy2.data.deploy_id) {
243
+ throw new Error(
244
+ `Deploy Botonic Error: ${String(deploy2.response?.data?.status)}`
245
+ );
246
+ }
247
+ console.log("\u23F3 Waiting for deployment to complete...");
248
+ while (true) {
249
+ await (0, import_system.sleep)(500);
250
+ const deployStatus = await botonicApiService.deployStatus(
251
+ deploy2.data.deploy_id
252
+ );
253
+ if (deployStatus.data.is_completed) {
254
+ if (deployStatus.data.status === "deploy_status_completed_ok") {
255
+ console.log("\u2705 Deployment completed successfully!");
256
+ return { hasDeployErrors: false };
257
+ } else {
258
+ throw new Error(deployStatus.data.error);
259
+ }
260
+ }
261
+ }
262
+ } catch (error) {
263
+ console.error("\u274C Deployment failed");
264
+ let reason = String(error);
265
+ if (error.response?.data) {
266
+ reason = error.response.data.join("");
267
+ }
268
+ console.error(`${reason}`);
269
+ return { hasDeployErrors: true };
270
+ }
271
+ }
272
+ async function displayDeployResults(botonicApiService, { hasDeployErrors }) {
273
+ try {
274
+ const providersRes = await botonicApiService.getProviders();
275
+ const providers = providersRes.data.results;
276
+ if (hasDeployErrors) return false;
277
+ if (!providers.length) {
278
+ const botId = botonicApiService.botInfo().id;
279
+ const accessToken = botonicApiService.getOauth().access_token;
280
+ const links = `Now, you can integrate a channel in:
281
+ https://app.hubtype.com/bots/${botId}/integrations?access_token=${accessToken}`;
282
+ console.log(links);
283
+ } else {
284
+ displayProviders(providers);
285
+ }
286
+ return true;
287
+ } catch (e) {
288
+ console.error(` There was an error getting the providers: ${String(e)}`);
289
+ return false;
290
+ }
291
+ }
292
+ function displayProviders(providers) {
293
+ console.log("\u{1F389} DEPLOYMENT SUCCESSFUL!");
294
+ console.log("\u{1F680} Your bot is now live and ready to chat!");
295
+ console.log("\u{1F4F1} Your bot is published on:");
296
+ providers.forEach((p) => {
297
+ if (p.provider === "whatsapp")
298
+ console.log(` \u{1F4AC} [WhatsApp] https://wa.me/${p.username}`);
299
+ if (p.provider === "facebook")
300
+ console.log(` \u{1F4AC} [Facebook] https://m.me/${p.username}`);
301
+ if (p.provider === "telegram")
302
+ console.log(` \u{1F4AC} [Telegram] https://t.me/${p.username}`);
303
+ if (p.provider === "twitter")
304
+ console.log(` \u{1F4AC} [Twitter] https://t.me/${p.username}`);
305
+ if (p.provider === "generic")
306
+ console.log(` \u{1F4AC} [Generic] Your app or website`);
307
+ });
308
+ }
@@ -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 schema_d_exports = {};
16
+ module.exports = __toCommonJS(schema_d_exports);
@@ -0,0 +1,31 @@
1
+ {
2
+ "$schema": "http://json-schema.org/schema",
3
+ "$id": "DeployToHubtypeExecutor",
4
+ "title": "Deploy to Hubtype executor",
5
+ "type": "object",
6
+ "properties": {
7
+ "configuration": {
8
+ "type": "string",
9
+ "enum": ["local", "dev", "dev2", "qa", "prod"],
10
+ "description": "Environment to deploy to"
11
+ },
12
+ "botName": {
13
+ "type": "string",
14
+ "description": "Name of the bot from Hubtype where you want to deploy"
15
+ },
16
+ "email": {
17
+ "type": "string",
18
+ "description": "Email from Hubtype Organization"
19
+ },
20
+ "password": {
21
+ "type": "string",
22
+ "description": "Password from Hubtype Organization"
23
+ },
24
+ "createIfNotExists": {
25
+ "type": "boolean",
26
+ "description": "Automatically create the bot if it doesn't exist (non-interactive mode for CI)",
27
+ "default": false
28
+ }
29
+ },
30
+ "additionalProperties": true
31
+ }
@@ -0,0 +1,84 @@
1
+ import { expect, test } from 'playwright/test'
2
+
3
+ test.describe('Botonic Publish E2E', () => {
4
+ test.beforeEach(async ({ page }) => {
5
+ page.on('console', msg => {
6
+ if (msg.type() === 'error') {
7
+ console.log(`[BROWSER ERROR] ${msg.text()}`)
8
+ }
9
+ })
10
+
11
+ page.on('pageerror', error => {
12
+ console.log(`[PAGE ERROR] ${error.message}`)
13
+ })
14
+
15
+ await page.goto('/')
16
+ await page.waitForLoadState('networkidle')
17
+ await page.waitForSelector('button[class*="webchat-trigger"]', {
18
+ timeout: 3000,
19
+ })
20
+ })
21
+
22
+ async function ensureWebchatOpen(page: any) {
23
+ const trigger = page.locator('button[class*="webchat-trigger"]').first()
24
+ await expect(trigger).toBeVisible({ timeout: 10000 })
25
+
26
+ const ariaExpanded = await trigger.getAttribute('aria-expanded')
27
+ if (ariaExpanded === 'false') {
28
+ await trigger.click()
29
+ await page.waitForTimeout(300)
30
+ }
31
+
32
+ const container = page
33
+ .locator('[class*="webchat-container-module"]')
34
+ .first()
35
+ await expect(container).toBeVisible({ timeout: 5000 })
36
+
37
+ return { trigger, container }
38
+ }
39
+
40
+ test('webchat trigger renders and opens webchat', async ({ page }) => {
41
+ const trigger = page.locator('button[class*="webchat-trigger"]').first()
42
+ await expect(trigger).toBeVisible({ timeout: 10000 })
43
+
44
+ const ariaExpanded = await trigger.getAttribute('aria-expanded')
45
+ if (ariaExpanded === 'false') {
46
+ await trigger.click()
47
+ await page.waitForTimeout(300)
48
+ }
49
+
50
+ const container = page
51
+ .locator('[class*="webchat-container-module"]')
52
+ .first()
53
+ await expect(container).toBeVisible({ timeout: 5000 })
54
+ })
55
+
56
+ test('bot responds to user message', async ({ page }) => {
57
+ await ensureWebchatOpen(page)
58
+
59
+ const input = page.locator('textarea').first()
60
+ await expect(input).toBeVisible({ timeout: 5000 })
61
+
62
+ await input.fill('hello')
63
+ await input.press('Enter')
64
+
65
+ const messages = page.locator('[class*="message-module"]')
66
+ await expect(messages.first()).toBeVisible({ timeout: 15000 })
67
+ })
68
+
69
+ test('send button works', async ({ page }) => {
70
+ await ensureWebchatOpen(page)
71
+
72
+ const input = page.locator('textarea').first()
73
+ const sendButton = page.locator('button[class*="send-button"]').first()
74
+
75
+ await expect(input).toBeVisible({ timeout: 5000 })
76
+ await expect(sendButton).toBeVisible()
77
+
78
+ await input.fill('test message')
79
+ await sendButton.click()
80
+
81
+ const messages = page.locator('[class*="message-module"]')
82
+ await expect(messages.first()).toBeVisible({ timeout: 15000 })
83
+ })
84
+ })
@@ -0,0 +1,5 @@
1
+ import type { ExecutorContext } from '@nx/devkit';
2
+ import type { E2EExecutorSchema } from './schema';
3
+ export default function e2eExecutor(options: E2EExecutorSchema, context: ExecutorContext): Promise<{
4
+ success: boolean;
5
+ }>;
@@ -0,0 +1,134 @@
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
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+ var executor_exports = {};
30
+ __export(executor_exports, {
31
+ default: () => e2eExecutor
32
+ });
33
+ module.exports = __toCommonJS(executor_exports);
34
+ var import_child_process = require("child_process");
35
+ var import_fs = require("fs");
36
+ var import_path = require("path");
37
+ var import_executor = __toESM(require("../deploy-netlify-snapshot/executor"));
38
+ const WEBCHAT_OUTPUT_DIR = "dist/webchat";
39
+ async function e2eExecutor(options, context) {
40
+ const projectRoot = context.projectsConfigurations?.projects[context.projectName ?? ""]?.root ?? "";
41
+ if (!options.dir) {
42
+ console.log("\u{1F528} Step 1/3: Building webchat app...");
43
+ try {
44
+ (0, import_child_process.execSync)(`npx nx build-webchat-app ${context.projectName}`, {
45
+ stdio: "inherit",
46
+ cwd: context.root
47
+ });
48
+ } catch {
49
+ console.error("\u274C Webchat build failed \u2014 aborting e2e tests");
50
+ return { success: false };
51
+ }
52
+ }
53
+ const dir = options.dir ? (0, import_path.resolve)(context.root, projectRoot, options.dir) : (0, import_path.resolve)(context.root, projectRoot, WEBCHAT_OUTPUT_DIR);
54
+ const deployStep = options.dir ? "1/2" : "2/3";
55
+ const playwrightStep = options.dir ? "2/2" : "3/3";
56
+ console.log(`
57
+ \u{1F4E6} Step ${deployStep}: Deploying snapshot to Netlify...`);
58
+ const deployResult = await (0, import_executor.default)(
59
+ {
60
+ dir,
61
+ siteId: options.siteId,
62
+ authToken: options.authToken,
63
+ alias: options.alias || `e2e-${Date.now()}`,
64
+ prod: options.prod
65
+ },
66
+ context
67
+ );
68
+ if (!deployResult.success || !deployResult.deployUrl) {
69
+ console.error("\u274C Netlify deploy failed \u2014 aborting e2e tests");
70
+ return { success: false };
71
+ }
72
+ const snapshotUrl = deployResult.deployUrl;
73
+ const e2eTmpDir = (0, import_path.resolve)(context.root, ".botonic-e2e-tmp");
74
+ (0, import_fs.mkdirSync)(e2eTmpDir, { recursive: true });
75
+ const e2eConfigPath = (0, import_path.resolve)(e2eTmpDir, "playwright.config.js");
76
+ (0, import_fs.writeFileSync)(
77
+ e2eConfigPath,
78
+ `module.exports = {
79
+ testDir: '.',
80
+ testMatch: '*.spec.ts',
81
+ timeout: 30000,
82
+ retries: 1,
83
+ use: {
84
+ baseURL: process.env.WEBCHAT_URL || 'http://localhost:8080',
85
+ trace: 'on-first-retry',
86
+ screenshot: 'only-on-failure',
87
+ video: 'on-first-retry',
88
+ },
89
+ reporter: [['html', { outputFolder: 'playwright-report' }], ['list']],
90
+ };
91
+ `
92
+ );
93
+ const bundledSpecPath = (0, import_path.resolve)(__dirname, "botonic-package-publish.spec.ts");
94
+ const specDestPath = (0, import_path.resolve)(e2eTmpDir, "botonic-package-publish.spec.ts");
95
+ if ((0, import_fs.existsSync)(bundledSpecPath)) {
96
+ (0, import_fs.copyFileSync)(bundledSpecPath, specDestPath);
97
+ } else if (options.configPath) {
98
+ const customConfigPath = (0, import_path.resolve)(context.root, options.configPath);
99
+ console.log(
100
+ `
101
+ \u{1F3AD} Step ${playwrightStep}: Running Playwright tests against ${snapshotUrl}`
102
+ );
103
+ try {
104
+ (0, import_child_process.execSync)(`npx playwright test --config="${customConfigPath}"`, {
105
+ env: { ...process.env, WEBCHAT_URL: snapshotUrl },
106
+ stdio: "inherit",
107
+ cwd: context.root
108
+ });
109
+ console.log("\u2705 E2E tests passed!");
110
+ return { success: true };
111
+ } catch {
112
+ console.error("\u274C E2E tests failed");
113
+ return { success: false };
114
+ }
115
+ }
116
+ console.log(
117
+ `
118
+ \u{1F3AD} Step ${playwrightStep}: Running Playwright tests against ${snapshotUrl}`
119
+ );
120
+ console.log(` Config: ${e2eConfigPath}`);
121
+ console.log(` Tests dir: ${e2eTmpDir}`);
122
+ try {
123
+ (0, import_child_process.execSync)(`npx playwright test --config="${e2eConfigPath}"`, {
124
+ env: { ...process.env, WEBCHAT_URL: snapshotUrl },
125
+ stdio: "inherit",
126
+ cwd: context.root
127
+ });
128
+ console.log("\u2705 E2E tests passed!");
129
+ return { success: true };
130
+ } catch {
131
+ console.error("\u274C E2E tests failed");
132
+ return { success: false };
133
+ }
134
+ }
@@ -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 schema_d_exports = {};
16
+ module.exports = __toCommonJS(schema_d_exports);
@@ -0,0 +1,35 @@
1
+ {
2
+ "$schema": "http://json-schema.org/schema",
3
+ "$id": "E2EExecutor",
4
+ "title": "Botonic E2E executor",
5
+ "type": "object",
6
+ "properties": {
7
+ "dir": {
8
+ "type": "string",
9
+ "description": "Directory of static files to deploy. If omitted, builds the webchat app first and uses dist/webchat"
10
+ },
11
+ "siteId": {
12
+ "type": "string",
13
+ "description": "Netlify site API ID. Falls back to BOTONIC_E2E_NETLIFY_SITE_ID env var"
14
+ },
15
+ "authToken": {
16
+ "type": "string",
17
+ "description": "Netlify personal access token. Falls back to NETLIFY_AUTH_TOKEN env var"
18
+ },
19
+ "alias": {
20
+ "type": "string",
21
+ "description": "Deploy alias for a unique snapshot URL. Defaults to a timestamp"
22
+ },
23
+ "prod": {
24
+ "type": "boolean",
25
+ "description": "Deploy to production Netlify URL instead of a preview",
26
+ "default": false
27
+ },
28
+ "configPath": {
29
+ "type": "string",
30
+ "description": "Path to a custom Playwright config file. Defaults to the built-in botonic webchat config"
31
+ }
32
+ },
33
+ "required": [],
34
+ "additionalProperties": false
35
+ }
@@ -0,0 +1,5 @@
1
+ import type { ExecutorContext } from '@nx/devkit';
2
+ import type { IntegrateProviderExecutorSchema } from './schema';
3
+ export default function integrateProviderExecutor(options: IntegrateProviderExecutorSchema, context: ExecutorContext): Promise<{
4
+ success: boolean;
5
+ }>;