@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,97 @@
1
+ import type { ExecutorContext } from '@nx/devkit';
2
+ import { BotonicAPIService } from '../api-service';
3
+ import type { BotDetail } from '../interfaces';
4
+ export declare function resolveProjectPath(context: ExecutorContext): string;
5
+ export declare function askEmailPassword(): Promise<{
6
+ email: string;
7
+ password: string;
8
+ }>;
9
+ export declare function askLogin(botonicApiService: BotonicAPIService): Promise<void>;
10
+ export declare function askSignup(botonicApiService: BotonicAPIService): Promise<void>;
11
+ export declare function handleAuthentication(botonicApiService: BotonicAPIService): Promise<void>;
12
+ /**
13
+ * Logs "Working as {user} in environment '{env}' [url]" as the first line for executors that need auth.
14
+ * Call after ensuring login (so service.oauth is set). No-op if not logged in.
15
+ */
16
+ export declare function logWorkingAsAndEnvironment(botonicApiService: BotonicAPIService): Promise<void>;
17
+ export declare function getAvailableBots(botonicApiService: BotonicAPIService): Promise<any[]>;
18
+ export declare function createNewBotWithName(botonicApiService: BotonicAPIService, botName: string): Promise<void>;
19
+ export declare function getAppIdFromEnvFile(projectRoot: string, appIdKey: string): string | null;
20
+ /**
21
+ * Reads VITE_HUBTYPE_APP_ID from .env.[configuration] (e.g. .env.dev) or .env.local when configuration is 'local'.
22
+ * Use this after deploy: deploy writes to .env.[configuration], so read from there instead of .env.local to avoid overwriting with a stale value.
23
+ */
24
+ export declare function getAppIdFromEnvFileForConfig(projectRoot: string, configuration: (typeof TARGET_ENV_NAMES)[number], appIdKey?: string): string | null;
25
+ export declare function writeAppIdToLocalEnv(projectRoot: string, appId: string, appIdKey?: string): Promise<void>;
26
+ declare const TARGET_ENV_NAMES: readonly ["local", "dev", "dev2", "qa", "prod"];
27
+ /**
28
+ * Writes or updates VITE_HUBTYPE_APP_ID in .env.[targetEnv] so that when
29
+ * serving with that configuration (e.g. MODE=dev), Vite loads the correct APP_ID.
30
+ * For targetEnv === 'local' delegates to writeAppIdToLocalEnv.
31
+ */
32
+ export declare function writeAppIdToEnvFile(projectRoot: string, appId: string, targetEnv: (typeof TARGET_ENV_NAMES)[number], appIdKey?: string): Promise<void>;
33
+ /**
34
+ * Writes or updates a single env var (key=value) in .env.[targetEnv].
35
+ * Used e.g. for VITE_HUBTYPE_BOT_ID so the webchat auth URL uses the correct bot.
36
+ */
37
+ export declare function writeEnvVarToEnvFile(projectRoot: string, key: string, value: string, targetEnv: (typeof TARGET_ENV_NAMES)[number]): void;
38
+ export declare function handleExecutorError(error: any, operation: string, showHelp?: boolean): {
39
+ success: false;
40
+ reason: string;
41
+ };
42
+ /**
43
+ * Finds the configuration key that matches the given environment object
44
+ * @param configurations - The configurations object with env properties
45
+ * @param targetEnv - The environment object to match against
46
+ * @returns The configuration key if found, null otherwise
47
+ */
48
+ export declare function findMatchingConfigurationKey(configurations: Record<string, {
49
+ env?: Record<string, any>;
50
+ }>, targetEnv: Record<string, any>): string;
51
+ export declare function resolveHubtypeEnvironment(context: ExecutorContext, options: any): {
52
+ targetEnvironment: string;
53
+ environmentVariables: Record<string, any>;
54
+ };
55
+ /**
56
+ * Ensures the user is logged in to Hubtype before starting the tunnel flow.
57
+ * Run this before Lambda + cloudflared + deploy_local_runtime so the login prompt happens first.
58
+ */
59
+ export declare function ensureHubtypeLoginBeforeTunnel(context: ExecutorContext, projectRoot: string, options?: PerformDeployLocalRuntimeOptions): Promise<void>;
60
+ /**
61
+ * Ensures a local runtime bot is selected or created and persisted to .botonic.json.
62
+ * Call this after ensureHubtypeLoginBeforeTunnel and before starting the tunnel, so bot detection runs after login but before tunnel setup.
63
+ * Does not log "Working as..." (already logged by ensureHubtypeLoginBeforeTunnel).
64
+ */
65
+ export declare function ensureLocalRuntimeBotBeforeTunnel(context: ExecutorContext, projectRoot: string, options?: PerformDeployLocalRuntimeOptions): Promise<void>;
66
+ /**
67
+ * Writes the local runtime bot to .botonic.json in the app folder so the created bot is persisted per project.
68
+ */
69
+ export declare function writeLocalRuntimeBotToAppFolder(projectRoot: string, bot: BotDetail): void;
70
+ /**
71
+ * Removes the app folder .botonic.json so the next run will prompt to create/select a new bot (e.g. after 404 when bot was deleted).
72
+ */
73
+ export declare function removeAppBotonicJson(projectRoot: string): void;
74
+ /**
75
+ * Ensures a local runtime bot is set: reuses one from .botonic.json, or prompts to select an existing bot or create a new one by name.
76
+ * Used when performing deploy_local_runtime with a tunnel URL from serve-bot or serve-dev-tunnel target.
77
+ */
78
+ export declare function ensureLocalRuntimeBot(botonicApiService: BotonicAPIService): Promise<void>;
79
+ export interface PerformDeployLocalRuntimeOptions {
80
+ email?: string;
81
+ password?: string;
82
+ env?: Record<string, unknown>;
83
+ /** Explicit configuration name (e.g. 'dev') so deploy uses the right environment when Nx does not merge config. */
84
+ configuration?: string;
85
+ }
86
+ export interface PerformDeployLocalRuntimeResult {
87
+ botId: string;
88
+ targetEnvironment: string;
89
+ environmentVariables: Record<string, unknown>;
90
+ }
91
+ /**
92
+ * Performs deploy_local_runtime with the given endpoint (e.g. tunnel URL).
93
+ * Handles auth, bot creation/selection, and deploy. Returns the bot id and env for later cleanup (e.g. deleteBot on shutdown).
94
+ * Used by serve-bot (tunnel is always on).
95
+ */
96
+ export declare function performDeployLocalRuntimeWithEndpoint(context: ExecutorContext, projectRoot: string, endpoint: string, options?: PerformDeployLocalRuntimeOptions): Promise<PerformDeployLocalRuntimeResult>;
97
+ export {};
@@ -0,0 +1,574 @@
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_helpers_exports = {};
20
+ __export(executor_helpers_exports, {
21
+ askEmailPassword: () => askEmailPassword,
22
+ askLogin: () => askLogin,
23
+ askSignup: () => askSignup,
24
+ createNewBotWithName: () => createNewBotWithName,
25
+ ensureHubtypeLoginBeforeTunnel: () => ensureHubtypeLoginBeforeTunnel,
26
+ ensureLocalRuntimeBot: () => ensureLocalRuntimeBot,
27
+ ensureLocalRuntimeBotBeforeTunnel: () => ensureLocalRuntimeBotBeforeTunnel,
28
+ findMatchingConfigurationKey: () => findMatchingConfigurationKey,
29
+ getAppIdFromEnvFile: () => getAppIdFromEnvFile,
30
+ getAppIdFromEnvFileForConfig: () => getAppIdFromEnvFileForConfig,
31
+ getAvailableBots: () => getAvailableBots,
32
+ handleAuthentication: () => handleAuthentication,
33
+ handleExecutorError: () => handleExecutorError,
34
+ logWorkingAsAndEnvironment: () => logWorkingAsAndEnvironment,
35
+ performDeployLocalRuntimeWithEndpoint: () => performDeployLocalRuntimeWithEndpoint,
36
+ removeAppBotonicJson: () => removeAppBotonicJson,
37
+ resolveHubtypeEnvironment: () => resolveHubtypeEnvironment,
38
+ resolveProjectPath: () => resolveProjectPath,
39
+ writeAppIdToEnvFile: () => writeAppIdToEnvFile,
40
+ writeAppIdToLocalEnv: () => writeAppIdToLocalEnv,
41
+ writeEnvVarToEnvFile: () => writeEnvVarToEnvFile,
42
+ writeLocalRuntimeBotToAppFolder: () => writeLocalRuntimeBotToAppFolder
43
+ });
44
+ module.exports = __toCommonJS(executor_helpers_exports);
45
+ var import_enquirer = require("enquirer");
46
+ var import_fs = require("fs");
47
+ var import_path = require("path");
48
+ var import_api_service = require("../api-service");
49
+ var import_bot_config = require("../bot-config");
50
+ var import_constants = require("../constants");
51
+ var import_file_system = require("./file-system");
52
+ var import_sam_template = require("./sam-template");
53
+ function resolveProjectPath(context) {
54
+ if (!context.projectName) {
55
+ throw new Error("Project name is not defined in executor context");
56
+ }
57
+ const projectConfig = context.projectsConfigurations.projects[context.projectName];
58
+ if (!projectConfig) {
59
+ throw new Error(
60
+ `Project configuration not found for project: ${context.projectName}`
61
+ );
62
+ }
63
+ const projectRoot = projectConfig.root || `apps/${context.projectName}`;
64
+ return (0, import_path.join)(context.root, projectRoot);
65
+ }
66
+ async function askEmailPassword() {
67
+ console.log("\n\u{1F4DD} Please provide your Hubtype credentials:\n");
68
+ const emailResponse = await (0, import_enquirer.prompt)({
69
+ type: "input",
70
+ name: "email",
71
+ message: "\u{1F4E7} Email:",
72
+ validate: (input) => {
73
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
74
+ return emailRegex.test(input) ? true : "Please enter a valid email address";
75
+ }
76
+ });
77
+ const passwordResponse = await (0, import_enquirer.prompt)({
78
+ type: "password",
79
+ name: "password",
80
+ message: "\u{1F511} Password:",
81
+ validate: (input) => {
82
+ return input.length > 0 ? true : "Password cannot be empty";
83
+ }
84
+ });
85
+ return {
86
+ email: emailResponse.email,
87
+ password: passwordResponse.password
88
+ };
89
+ }
90
+ async function askLogin(botonicApiService) {
91
+ const credentials = await askEmailPassword();
92
+ console.log("\u{1F510} Authenticating with Hubtype...");
93
+ await botonicApiService.login(credentials.email, credentials.password);
94
+ botonicApiService.saveAllCredentials();
95
+ console.log("\u2705 Authentication successful!");
96
+ }
97
+ async function askSignup(botonicApiService) {
98
+ const credentials = await askEmailPassword();
99
+ console.log("\u{1F4DD} Creating your account...");
100
+ const orgName = credentials.email.split("@")[0];
101
+ const campaign = { product: "botonic" };
102
+ await botonicApiService.signup(
103
+ credentials.email,
104
+ credentials.password,
105
+ orgName,
106
+ campaign
107
+ );
108
+ console.log("\u2705 Account created successfully!");
109
+ await botonicApiService.login(credentials.email, credentials.password);
110
+ botonicApiService.saveAllCredentials();
111
+ }
112
+ async function handleAuthentication(botonicApiService) {
113
+ const response = await (0, import_enquirer.prompt)({
114
+ type: "select",
115
+ name: "signupConfirmation",
116
+ message: "\n\u{1F510} You need to login before proceeding.\nDo you have a Hubtype account already?\n",
117
+ choices: [
118
+ { name: "signup", message: "No, I need to create a new one (Signup)" },
119
+ { name: "login", message: "Yes, I do. (Login)" }
120
+ ]
121
+ });
122
+ if (response.signupConfirmation === "login") {
123
+ await askLogin(botonicApiService);
124
+ } else {
125
+ await askSignup(botonicApiService);
126
+ }
127
+ }
128
+ async function logWorkingAsAndEnvironment(botonicApiService) {
129
+ if (!botonicApiService.oauth) return;
130
+ await botonicApiService.ensureMeLoaded();
131
+ const name = botonicApiService.getDisplayName();
132
+ const env = botonicApiService.targetEnvironment ?? "local";
133
+ const url = botonicApiService.baseUrl ?? "";
134
+ console.log(`Working as ${name} in environment '${env}' [${url}]
135
+ `);
136
+ }
137
+ async function getAvailableBots(botonicApiService) {
138
+ const resp = await botonicApiService.getBots();
139
+ return resp.data.results;
140
+ }
141
+ const MAX_BOT_NAME_LENGTH = 25;
142
+ async function createNewBotWithName(botonicApiService, botName) {
143
+ if (botName.length > MAX_BOT_NAME_LENGTH) {
144
+ throw new Error(
145
+ `Bot name must be at most ${MAX_BOT_NAME_LENGTH} characters. Please choose a shorter name.`
146
+ );
147
+ }
148
+ console.log(`\u{1F916} Creating bot "${botName}"...`);
149
+ await botonicApiService.createBot(botName);
150
+ console.log(`\u2705 Bot "${botName}" created successfully!`);
151
+ }
152
+ function getAppIdFromEnvFile(projectRoot, appIdKey) {
153
+ const envFilePath = (0, import_path.join)(projectRoot, ".env.local");
154
+ if (!(0, import_fs.existsSync)(envFilePath)) {
155
+ return null;
156
+ }
157
+ try {
158
+ const envContent = (0, import_fs.readFileSync)(envFilePath, "utf8");
159
+ const lines = envContent.split("\n");
160
+ for (const line of lines) {
161
+ if (line.startsWith(`${appIdKey}=`)) {
162
+ return line.split("=")[1]?.trim();
163
+ }
164
+ }
165
+ return null;
166
+ } catch (error) {
167
+ console.warn(`\u26A0\uFE0F Could not read .env.local file: ${error.message}`);
168
+ return null;
169
+ }
170
+ }
171
+ function getAppIdFromEnvFileForConfig(projectRoot, configuration, appIdKey = APP_ID_KEY) {
172
+ const fileName = configuration === "local" ? ".env.local" : `.env.${configuration}`;
173
+ const envFilePath = (0, import_path.join)(projectRoot, fileName);
174
+ if (!(0, import_fs.existsSync)(envFilePath)) {
175
+ return null;
176
+ }
177
+ try {
178
+ const envContent = (0, import_fs.readFileSync)(envFilePath, "utf8");
179
+ const lines = envContent.split("\n");
180
+ for (const line of lines) {
181
+ if (line.startsWith(`${appIdKey}=`)) {
182
+ return line.split("=")[1]?.trim();
183
+ }
184
+ }
185
+ return null;
186
+ } catch (error) {
187
+ console.warn(
188
+ `\u26A0\uFE0F Could not read ${fileName}: ${error instanceof Error ? error.message : String(error)}`
189
+ );
190
+ return null;
191
+ }
192
+ }
193
+ async function writeAppIdToLocalEnv(projectRoot, appId, appIdKey = "VITE_HUBTYPE_APP_ID") {
194
+ const localEnvPath = (0, import_path.join)(projectRoot, ".env.local");
195
+ if (!(0, import_fs.existsSync)(localEnvPath)) {
196
+ (0, import_fs.writeFileSync)(localEnvPath, `${appIdKey}=${appId}
197
+ `, "utf8");
198
+ console.log(`\u2705 Created .env.local with ${appIdKey}`);
199
+ return;
200
+ }
201
+ try {
202
+ const existingContent = (0, import_fs.readFileSync)(localEnvPath, "utf8");
203
+ const lines = existingContent.split("\n");
204
+ let updatedContent = existingContent;
205
+ const appIdLineIndex = lines.findIndex(
206
+ (line) => line.startsWith(`${appIdKey}=`)
207
+ );
208
+ if (appIdLineIndex !== -1) {
209
+ lines[appIdLineIndex] = `${appIdKey}=${appId}`;
210
+ updatedContent = lines.join("\n");
211
+ } else {
212
+ updatedContent = existingContent + `
213
+ ${appIdKey}=${appId}
214
+ `;
215
+ }
216
+ (0, import_fs.writeFileSync)(localEnvPath, updatedContent, "utf8");
217
+ console.log(
218
+ `\u2705 ${appIdKey} has been automatically added to .env.local file!`
219
+ );
220
+ console.log(`\u{1F4DD} APP ID: ${appId}`);
221
+ } catch (error) {
222
+ console.error(
223
+ `\u274C Failed to write APP ID to .env.local file:`,
224
+ String(error)
225
+ );
226
+ console.log("\u{1F4CB} Please manually add this line to your .env.local file:");
227
+ console.log(`${appIdKey}=${appId}`);
228
+ }
229
+ }
230
+ const APP_ID_KEY = "VITE_HUBTYPE_APP_ID";
231
+ const TARGET_ENV_NAMES = ["local", "dev", "dev2", "qa", "prod"];
232
+ async function writeAppIdToEnvFile(projectRoot, appId, targetEnv, appIdKey = APP_ID_KEY) {
233
+ if (targetEnv === "local") {
234
+ await writeAppIdToLocalEnv(projectRoot, appId, appIdKey);
235
+ return;
236
+ }
237
+ const envFilePath = (0, import_path.join)(projectRoot, `.env.${targetEnv}`);
238
+ let content;
239
+ try {
240
+ content = (0, import_fs.existsSync)(envFilePath) ? (0, import_fs.readFileSync)(envFilePath, "utf8") : "";
241
+ } catch (error) {
242
+ console.warn(
243
+ `\u26A0\uFE0F Could not read .env.${targetEnv}: ${error instanceof Error ? error.message : String(error)}`
244
+ );
245
+ return;
246
+ }
247
+ const lines = content.split("\n");
248
+ const lineIndex = lines.findIndex((line) => line.startsWith(`${appIdKey}=`));
249
+ if (lineIndex !== -1) {
250
+ lines[lineIndex] = `${appIdKey}=${appId}`;
251
+ } else {
252
+ lines.push(`${appIdKey}=${appId}`);
253
+ }
254
+ try {
255
+ (0, import_fs.writeFileSync)(envFilePath, lines.join("\n"), "utf8");
256
+ console.log(
257
+ `\u2705 ${appIdKey} updated in .env.${targetEnv} (${appId.slice(0, 8)}\u2026)`
258
+ );
259
+ } catch (error) {
260
+ console.warn(
261
+ `\u26A0\uFE0F Could not write .env.${targetEnv}: ${error instanceof Error ? error.message : String(error)}`
262
+ );
263
+ }
264
+ }
265
+ function writeEnvVarToEnvFile(projectRoot, key, value, targetEnv) {
266
+ const fileName = targetEnv === "local" ? ".env.local" : `.env.${targetEnv}`;
267
+ const envFilePath = (0, import_path.join)(projectRoot, fileName);
268
+ let content;
269
+ try {
270
+ content = (0, import_fs.existsSync)(envFilePath) ? (0, import_fs.readFileSync)(envFilePath, "utf8") : "";
271
+ } catch (error) {
272
+ console.warn(
273
+ `\u26A0\uFE0F Could not read ${fileName}: ${error instanceof Error ? error.message : String(error)}`
274
+ );
275
+ return;
276
+ }
277
+ const lines = content.split("\n");
278
+ const lineIndex = lines.findIndex((line) => line.startsWith(`${key}=`));
279
+ if (lineIndex !== -1) {
280
+ lines[lineIndex] = `${key}=${value}`;
281
+ } else {
282
+ lines.push(`${key}=${value}`);
283
+ }
284
+ try {
285
+ (0, import_fs.writeFileSync)(envFilePath, lines.join("\n"), "utf8");
286
+ console.log(`\u2705 ${key} updated in ${fileName} (${value.slice(0, 8)}\u2026)`);
287
+ } catch (error) {
288
+ console.warn(
289
+ `\u26A0\uFE0F Could not write ${fileName}: ${error instanceof Error ? error.message : String(error)}`
290
+ );
291
+ }
292
+ }
293
+ function handleExecutorError(error, operation, showHelp = true) {
294
+ console.error(`\u274C ${operation} failed`);
295
+ let reason = "Unknown error";
296
+ if (error.response?.data) {
297
+ if (error.response?.data?.error_description) {
298
+ reason = error.response.data.error_description;
299
+ } else if (Array.isArray(error.response.data)) {
300
+ reason = error.response.data.join("");
301
+ } else {
302
+ reason = JSON.stringify(error.response.data);
303
+ }
304
+ } else if (error.message) {
305
+ reason = error.message;
306
+ } else {
307
+ reason = "An unexpected error occurred. Please try again.";
308
+ }
309
+ console.error(` ${reason}`);
310
+ if (showHelp) {
311
+ console.error("\n\u{1F4A1} Need help? Check your configuration and try again.");
312
+ console.error("\u{1F517} Visit https://botonic.io for support");
313
+ }
314
+ return { success: false, reason };
315
+ }
316
+ function findMatchingConfigurationKey(configurations, targetEnv) {
317
+ if (!targetEnv) {
318
+ return "local";
319
+ }
320
+ for (const [key, config] of Object.entries(configurations)) {
321
+ if (!config.env) {
322
+ continue;
323
+ }
324
+ if (areObjectsEqual(config.env, targetEnv)) {
325
+ return key;
326
+ }
327
+ }
328
+ return "local";
329
+ }
330
+ function areObjectsEqual(obj1, obj2) {
331
+ const keys1 = Object.keys(obj1);
332
+ const keys2 = Object.keys(obj2);
333
+ if (keys1.length !== keys2.length) {
334
+ return false;
335
+ }
336
+ for (const key of keys1) {
337
+ if (obj1[key] !== obj2[key]) {
338
+ return false;
339
+ }
340
+ }
341
+ return true;
342
+ }
343
+ function resolveHubtypeEnvironment(context, options) {
344
+ const explicitConfig = options.configuration && TARGET_ENV_NAMES.includes(
345
+ options.configuration
346
+ ) ? options.configuration : null;
347
+ const targetEnvironment = explicitConfig ? explicitConfig : findMatchingConfigurationKey(
348
+ context.target?.configurations || {},
349
+ options.env
350
+ );
351
+ const envFromTargetConfig = context.target?.configurations?.[targetEnvironment]?.env;
352
+ const environmentVariables = options.env || envFromTargetConfig || {
353
+ VITE_HUBTYPE_CLIENT_ID: process.env["VITE_HUBTYPE_CLIENT_ID"],
354
+ VITE_HUBTYPE_API_URL: process.env["VITE_HUBTYPE_API_URL"],
355
+ VITE_HUBTYPE_APP_ID: process.env["VITE_HUBTYPE_APP_ID"],
356
+ VITE_PUSHER_API_PREFIX: process.env["VITE_PUSHER_API_PREFIX"]
357
+ };
358
+ return {
359
+ targetEnvironment,
360
+ environmentVariables
361
+ };
362
+ }
363
+ async function ensureHubtypeLoginBeforeTunnel(context, projectRoot, options = {}) {
364
+ const { targetEnvironment, environmentVariables } = resolveHubtypeEnvironment(
365
+ context,
366
+ options
367
+ );
368
+ const botonicApiService = new import_api_service.BotonicAPIService({
369
+ isLocalRuntimeDeployment: true,
370
+ projectRoot,
371
+ workspaceRoot: (0, import_path.resolve)(context.root),
372
+ environmentVariables,
373
+ targetEnvironment
374
+ });
375
+ if (!botonicApiService.oauth) {
376
+ if (options.email && options.password) {
377
+ await botonicApiService.login(options.email, options.password);
378
+ botonicApiService.saveAllCredentials();
379
+ } else {
380
+ await handleAuthentication(botonicApiService);
381
+ }
382
+ }
383
+ await logWorkingAsAndEnvironment(botonicApiService);
384
+ }
385
+ async function ensureLocalRuntimeBotBeforeTunnel(context, projectRoot, options = {}) {
386
+ const { targetEnvironment, environmentVariables } = resolveHubtypeEnvironment(
387
+ context,
388
+ options
389
+ );
390
+ const botonicApiService = new import_api_service.BotonicAPIService({
391
+ isLocalRuntimeDeployment: true,
392
+ projectRoot,
393
+ workspaceRoot: (0, import_path.resolve)(context.root),
394
+ environmentVariables,
395
+ targetEnvironment
396
+ });
397
+ if (!botonicApiService.oauth) {
398
+ if (options.email && options.password) {
399
+ await botonicApiService.login(options.email, options.password);
400
+ botonicApiService.saveAllCredentials();
401
+ } else {
402
+ await handleAuthentication(botonicApiService);
403
+ }
404
+ }
405
+ await ensureLocalRuntimeBot(botonicApiService);
406
+ writeLocalRuntimeBotToAppFolder(projectRoot, botonicApiService.botInfo());
407
+ botonicApiService.saveAllCredentials();
408
+ }
409
+ function writeLocalRuntimeBotToAppFolder(projectRoot, bot) {
410
+ const path = (0, import_path.join)(projectRoot, import_constants.BOT_CREDENTIALS_FILENAME);
411
+ (0, import_file_system.writeJSON)(path, { bot });
412
+ }
413
+ function removeAppBotonicJson(projectRoot) {
414
+ const path = (0, import_path.join)(projectRoot, import_constants.BOT_CREDENTIALS_FILENAME);
415
+ if ((0, import_fs.existsSync)(path)) {
416
+ (0, import_fs.unlinkSync)(path);
417
+ }
418
+ }
419
+ async function ensureLocalRuntimeBot(botonicApiService) {
420
+ if (botonicApiService.hasLocalRuntimeBot()) {
421
+ return;
422
+ }
423
+ const bots = await getAvailableBots(botonicApiService);
424
+ if (bots.length === 0) {
425
+ console.log("\u{1F916} No bots yet. Let's create one for local runtime.\n");
426
+ const response2 = await (0, import_enquirer.prompt)({
427
+ type: "input",
428
+ name: "bot_name",
429
+ message: "\u{1F916} Bot name:",
430
+ validate: (input) => {
431
+ if (!input.trim()) return "Bot name cannot be empty";
432
+ if (input.length > MAX_BOT_NAME_LENGTH) {
433
+ return `Bot name must be at most ${MAX_BOT_NAME_LENGTH} characters`;
434
+ }
435
+ return true;
436
+ }
437
+ });
438
+ const name = response2.bot_name.trim();
439
+ await createNewBotWithName(botonicApiService, name);
440
+ return;
441
+ }
442
+ const CREATE_NEW_CHOICE = "__create_new__";
443
+ console.log("\u{1F4CB} Select a bot for local runtime or create a new one:\n");
444
+ const response = await (0, import_enquirer.prompt)({
445
+ type: "select",
446
+ name: "bot_id",
447
+ message: "\u{1F916} Select a bot or create new:",
448
+ choices: [
449
+ ...bots.map((bot2) => ({
450
+ name: bot2.id,
451
+ message: bot2.name
452
+ })),
453
+ { name: CREATE_NEW_CHOICE, message: "+ Create new bot" }
454
+ ]
455
+ });
456
+ if (response.bot_id === CREATE_NEW_CHOICE) {
457
+ const nameResponse = await (0, import_enquirer.prompt)({
458
+ type: "input",
459
+ name: "bot_name",
460
+ message: "\u{1F916} New bot name:",
461
+ validate: (input) => {
462
+ if (!input.trim()) return "Bot name cannot be empty";
463
+ if (input.length > MAX_BOT_NAME_LENGTH) {
464
+ return `Bot name must be at most ${MAX_BOT_NAME_LENGTH} characters`;
465
+ }
466
+ return true;
467
+ }
468
+ });
469
+ const name = nameResponse.bot_name.trim();
470
+ await createNewBotWithName(botonicApiService, name);
471
+ return;
472
+ }
473
+ const bot = bots.find((b) => b.id === response.bot_id);
474
+ if (bot) {
475
+ botonicApiService.setLocalRuntimeBot(bot);
476
+ console.log(`\u2705 Selected bot: ${bot.name}`);
477
+ } else {
478
+ throw new Error("Bot selection failed");
479
+ }
480
+ }
481
+ async function performDeployLocalRuntimeWithEndpoint(context, projectRoot, endpoint, options = {}) {
482
+ const { targetEnvironment, environmentVariables } = resolveHubtypeEnvironment(
483
+ context,
484
+ options
485
+ );
486
+ const botonicApiService = new import_api_service.BotonicAPIService({
487
+ isLocalRuntimeDeployment: true,
488
+ projectRoot,
489
+ workspaceRoot: (0, import_path.resolve)(context.root),
490
+ environmentVariables,
491
+ targetEnvironment
492
+ });
493
+ if (!botonicApiService.oauth) {
494
+ if (options.email && options.password) {
495
+ await botonicApiService.login(options.email, options.password);
496
+ botonicApiService.saveAllCredentials();
497
+ } else {
498
+ await handleAuthentication(botonicApiService);
499
+ }
500
+ }
501
+ const maxAttempts = 2;
502
+ let lastError;
503
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
504
+ try {
505
+ await ensureLocalRuntimeBot(botonicApiService);
506
+ writeLocalRuntimeBotToAppFolder(projectRoot, botonicApiService.botInfo());
507
+ const functionName = (0, import_sam_template.getLocalLambdaFunctionName)(projectRoot);
508
+ const botConfigJson = await import_bot_config.BotConfig.get(projectRoot);
509
+ await botonicApiService.deployLocalRuntime({
510
+ botConfigJson,
511
+ lambdaFunctionName: functionName,
512
+ lambdaEndpoint: endpoint
513
+ });
514
+ const providersResp = await botonicApiService.getProviders();
515
+ const appId = providersResp.data.results?.filter(
516
+ (p) => p.is_test && p.is_active
517
+ )[0]?.id;
518
+ const resolvedTargetEnv = TARGET_ENV_NAMES.includes(
519
+ targetEnvironment
520
+ ) ? targetEnvironment : "local";
521
+ if (appId) {
522
+ await writeAppIdToEnvFile(projectRoot, appId, resolvedTargetEnv);
523
+ }
524
+ botonicApiService.saveAllCredentials();
525
+ const botId = botonicApiService.botInfo().id;
526
+ writeEnvVarToEnvFile(
527
+ projectRoot,
528
+ "VITE_HUBTYPE_BOT_ID",
529
+ botId,
530
+ resolvedTargetEnv
531
+ );
532
+ return {
533
+ botId,
534
+ targetEnvironment,
535
+ environmentVariables
536
+ };
537
+ } catch (err) {
538
+ lastError = err;
539
+ const status = err?.response?.status;
540
+ if (status === 404 && attempt < maxAttempts) {
541
+ removeAppBotonicJson(projectRoot);
542
+ botonicApiService.setLocalRuntimeBot(null);
543
+ continue;
544
+ }
545
+ throw err;
546
+ }
547
+ }
548
+ throw lastError;
549
+ }
550
+ // Annotate the CommonJS export names for ESM import in node:
551
+ 0 && (module.exports = {
552
+ askEmailPassword,
553
+ askLogin,
554
+ askSignup,
555
+ createNewBotWithName,
556
+ ensureHubtypeLoginBeforeTunnel,
557
+ ensureLocalRuntimeBot,
558
+ ensureLocalRuntimeBotBeforeTunnel,
559
+ findMatchingConfigurationKey,
560
+ getAppIdFromEnvFile,
561
+ getAppIdFromEnvFileForConfig,
562
+ getAvailableBots,
563
+ handleAuthentication,
564
+ handleExecutorError,
565
+ logWorkingAsAndEnvironment,
566
+ performDeployLocalRuntimeWithEndpoint,
567
+ removeAppBotonicJson,
568
+ resolveHubtypeEnvironment,
569
+ resolveProjectPath,
570
+ writeAppIdToEnvFile,
571
+ writeAppIdToLocalEnv,
572
+ writeEnvVarToEnvFile,
573
+ writeLocalRuntimeBotToAppFolder
574
+ });
@@ -0,0 +1,8 @@
1
+ import type { JSONObject } from '../interfaces';
2
+ export declare function pathExists(path: string): boolean;
3
+ export declare function readJSON(path: string): JSONObject | undefined;
4
+ export declare function writeJSON(path: string, object: any): void;
5
+ export declare function createDir(path: string): void;
6
+ export declare function getHomeDirectory(): string;
7
+ export declare function copy(from: string, to: string): void;
8
+ export declare function removeRecursively(path: string): void;