@botonic/nx-plugin 2.25.0 → 2.27.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 (74) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +4 -4
  3. package/generators.json +0 -26
  4. package/migrations.json +1 -38
  5. package/package.json +1 -1
  6. package/src/executors/e2e-webchat/botonic-package-publish.spec.ts +3 -3
  7. package/src/executors/serve-bot/executor.js +98 -16
  8. package/src/executors/serve-bot/schema.json +10 -0
  9. package/src/generators/action/files/__name__.spec.ts.template +4 -4
  10. package/src/generators/action/files/__name__.ts.template +5 -5
  11. package/src/generators/action/generator.js +1 -1
  12. package/src/generators/bot-app/files/.eslintrc.json.template +30 -1
  13. package/src/generators/bot-app/files/src/client/webchat/index.tsx.template +1 -6
  14. package/src/generators/bot-app/files/src/server/bot/actions/not-found.ts.template +7 -6
  15. package/src/generators/bot-app/files/src/server/bot/actions/welcome.ts.template +7 -6
  16. package/src/generators/bot-app/files/src/server/bot/index.ts.template +9 -11
  17. package/src/generators/bot-app/files/src/server/bot/plugins/ai-agents/index.ts.template +4 -4
  18. package/src/generators/bot-app/files/src/server/bot/plugins/flow-builder/index.ts.template +5 -5
  19. package/src/generators/bot-app/files/src/server/bot/routes.ts.template +5 -5
  20. package/src/generators/bot-app/files/src/server/bot/tracking.ts.template +4 -4
  21. package/src/generators/bot-app/files/src/server/lambda/handler.js.template +1 -6
  22. package/src/generators/bot-app/files/vite/plugins/dev-log-viewer-html.plugin.ts.template +65 -0
  23. package/src/generators/bot-app/files/vite/webchat.config.ts.template +14 -1
  24. package/src/generators/bot-app/generator.js +6 -2
  25. package/src/generators/bot-app/lilara-version.json +1 -1
  26. package/src/generators/bot-app/schema.d.ts +1 -0
  27. package/src/generators/bot-app/schema.json +4 -0
  28. package/src/generators/custom-message/files/__name__-output.ts.template +12 -10
  29. package/src/generators/custom-message/generator.js +1 -1
  30. package/src/{cursor-commands → generators/preset/files/.claude/commands}/update-bot.md +7 -7
  31. package/src/{cursor-commands → generators/preset/files/.claude/commands}/update-botonic.md +5 -3
  32. package/src/{migrations/add-botonic-update-bots-skill/files/.cursor → generators/preset/files/.claude}/scripts/update-bot/discover-bots.sh +1 -1
  33. package/src/generators/preset/files/{.cursor → .claude}/skills/botonic-action/SKILL.md +21 -21
  34. package/src/generators/preset/files/{.cursor → .claude}/skills/botonic-custom-message/SKILL.md +11 -12
  35. package/src/generators/preset/files/{.cursor → .claude}/skills/botonic-webview/SKILL.md +8 -8
  36. package/src/generators/preset/files/.cursor/commands/update-bot.md +1 -3
  37. package/src/generators/preset/files/.cursor/commands/update-botonic.md +1 -3
  38. package/src/lib/util/executor-helpers.d.ts +0 -1
  39. package/src/lib/util/executor-helpers.js +1 -8
  40. package/src/generators/bot-app-migrations/migrate-fix-css-code-split/generator.d.ts +0 -5
  41. package/src/generators/bot-app-migrations/migrate-fix-css-code-split/generator.js +0 -92
  42. package/src/generators/bot-app-migrations/migrate-fix-css-code-split/schema.json +0 -15
  43. package/src/generators/bot-app-migrations/migrate-pnpm-compat/generator.d.ts +0 -5
  44. package/src/generators/bot-app-migrations/migrate-pnpm-compat/generator.js +0 -97
  45. package/src/generators/bot-app-migrations/migrate-pnpm-compat/schema.json +0 -15
  46. package/src/generators/bot-app-migrations/migrate-webchat-trigger/generator.d.ts +0 -5
  47. package/src/generators/bot-app-migrations/migrate-webchat-trigger/generator.js +0 -165
  48. package/src/generators/bot-app-migrations/migrate-webchat-trigger/schema.json +0 -15
  49. package/src/generators/preset/files/.cursor/scripts/update-bot/discover-bots.sh +0 -67
  50. package/src/migrations/add-botonic-update-bots-skill/add-botonic-update-bots-skill.migration.d.ts +0 -2
  51. package/src/migrations/add-botonic-update-bots-skill/add-botonic-update-bots-skill.migration.js +0 -52
  52. package/src/migrations/add-botonic-update-bots-skill/add-botonic-update-bots-skill.migration.md +0 -23
  53. package/src/migrations/add-botonic-update-bots-skill/files/.cursor/commands/update-bot.md +0 -5
  54. package/src/migrations/add-botonic-update-bots-skill/files/.cursor/commands/update-botonic.md +0 -5
  55. package/src/migrations/add-botonic-update-bots-skill/files/.cursor/scripts/update-bot/find-migration-guides.sh +0 -70
  56. package/src/migrations/add-botonic-update-bots-skill/schema.json +0 -5
  57. package/src/migrations/add-lilara-registry/add-lilara-registry.migration.d.ts +0 -2
  58. package/src/migrations/add-lilara-registry/add-lilara-registry.migration.js +0 -49
  59. package/src/migrations/add-lilara-registry/schema.json +0 -5
  60. package/src/migrations/fix-css-code-split/fix-css-code-split.migration.md +0 -45
  61. package/src/migrations/remove-codeartifact-registry/remove-codeartifact-registry.migration.d.ts +0 -2
  62. package/src/migrations/remove-codeartifact-registry/remove-codeartifact-registry.migration.js +0 -59
  63. package/src/migrations/remove-codeartifact-registry/schema.json +0 -5
  64. package/src/migrations/sync-pending-bot-migrations/schema.json +0 -5
  65. package/src/migrations/sync-pending-bot-migrations/sync-pending-bot-migrations.migration.d.ts +0 -2
  66. package/src/migrations/sync-pending-bot-migrations/sync-pending-bot-migrations.migration.js +0 -137
  67. package/src/migrations/sync-pending-bot-migrations/sync-pending-bot-migrations.migration.md +0 -19
  68. package/src/migrations/update-cursor-commands-to-stubs/schema.json +0 -5
  69. package/src/migrations/update-cursor-commands-to-stubs/update-cursor-commands-to-stubs.migration.d.ts +0 -2
  70. package/src/migrations/update-cursor-commands-to-stubs/update-cursor-commands-to-stubs.migration.js +0 -61
  71. package/src/migrations/update-pnpm-workspace-scripts/schema.json +0 -4
  72. package/src/migrations/update-pnpm-workspace-scripts/update-pnpm-workspace-scripts.migration.d.ts +0 -2
  73. package/src/migrations/update-pnpm-workspace-scripts/update-pnpm-workspace-scripts.migration.js +0 -47
  74. /package/src/generators/preset/files/{.cursor → .claude}/scripts/update-bot/find-migration-guides.sh +0 -0
@@ -1,92 +0,0 @@
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 generator_exports = {};
20
- __export(generator_exports, {
21
- default: () => migrateFixCssCodeSplitGenerator
22
- });
23
- module.exports = __toCommonJS(generator_exports);
24
- var import_devkit = require("@nx/devkit");
25
- var import_migration_utils = require("../../../migrations/utils/migration-utils");
26
- const MODULE_DIR = __dirname;
27
- const WEBCHAT_CONFIG = "vite/webchat.config.ts";
28
- const WEBVIEWS_CONFIG = "vite/webviews.config.ts";
29
- function addCssCodeSplit(content) {
30
- if (content.includes("cssCodeSplit")) {
31
- return content;
32
- }
33
- return content.replace(
34
- /(reportCompressedSize:\s*true,)\s*\n(\s+)(commonjsOptions)/,
35
- "$1\n$2cssCodeSplit: false,\n$2$3"
36
- );
37
- }
38
- function processConfigFile(content, filePath) {
39
- if (content.includes("cssCodeSplit")) {
40
- return { transformed: false, newContent: content };
41
- }
42
- if (!content.includes("reportCompressedSize:")) {
43
- return { transformed: false, newContent: content };
44
- }
45
- const newContent = addCssCodeSplit(content);
46
- if (newContent === content) {
47
- return { transformed: false, newContent: content };
48
- }
49
- return {
50
- transformed: true,
51
- newContent,
52
- logMessage: `${filePath} updated with cssCodeSplit: false`
53
- };
54
- }
55
- async function migrateFixCssCodeSplitGenerator(tree, options) {
56
- const projectPath = options.project.startsWith("apps/") ? options.project : `apps/${options.project}`;
57
- const targetVersion = (0, import_migration_utils.getPluginVersion)(MODULE_DIR);
58
- import_devkit.logger.info(
59
- `\u{1F504} Adding cssCodeSplit: false to ${options.project} vite configs...`
60
- );
61
- const fileProcessor = (0, import_migration_utils.createFileProcessor)([
62
- {
63
- filePath: (p) => `${p}/${WEBCHAT_CONFIG}`,
64
- shouldProcess: (t, filePath) => {
65
- if (!t.exists(filePath)) return false;
66
- const content = t.read(filePath, "utf-8");
67
- return !!content && !content.includes("cssCodeSplit");
68
- },
69
- processFile: (_t, filePath, content) => processConfigFile(content, filePath)
70
- },
71
- {
72
- filePath: (p) => `${p}/${WEBVIEWS_CONFIG}`,
73
- shouldProcess: (t, filePath) => {
74
- if (!t.exists(filePath)) return false;
75
- const content = t.read(filePath, "utf-8");
76
- return !!content && !content.includes("cssCodeSplit");
77
- },
78
- processFile: (_t, filePath, content) => processConfigFile(content, filePath)
79
- }
80
- ]);
81
- const result = await fileProcessor(tree, projectPath, targetVersion);
82
- if (result.transformed) {
83
- (0, import_migration_utils.updateBotonicDependencies)(tree, targetVersion, projectPath);
84
- import_devkit.logger.info(
85
- `\u2705 ${options.project} vite configs updated with cssCodeSplit: false`
86
- );
87
- import_devkit.logger.info(` See migrate-fix-css-code-split.md for verification steps`);
88
- } else {
89
- import_devkit.logger.info(`\u2139\uFE0F ${options.project} already up to date \u2013 skipping`);
90
- }
91
- await (0, import_devkit.formatFiles)(tree);
92
- }
@@ -1,15 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/schema",
3
- "$id": "MigrateFixCssCodeSplit",
4
- "title": "Add cssCodeSplit: false to vite configs",
5
- "description": "Adds cssCodeSplit: false to vite webchat and webviews configs to prevent split CSS missing from index.html",
6
- "type": "object",
7
- "properties": {
8
- "project": {
9
- "type": "string",
10
- "description": "The bot project to migrate",
11
- "$default": { "$source": "argv", "index": 0 }
12
- }
13
- },
14
- "required": ["project"]
15
- }
@@ -1,5 +0,0 @@
1
- import type { Tree } from '@nx/devkit';
2
- export interface MigratePnpmCompatSchema {
3
- project: string;
4
- }
5
- export default function migratePnpmCompatGenerator(tree: Tree, options: MigratePnpmCompatSchema): Promise<void>;
@@ -1,97 +0,0 @@
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 generator_exports = {};
20
- __export(generator_exports, {
21
- default: () => migratePnpmCompatGenerator
22
- });
23
- module.exports = __toCommonJS(generator_exports);
24
- var import_devkit = require("@nx/devkit");
25
- var import_migration_utils = require("../../../migrations/utils/migration-utils");
26
- const MODULE_DIR = __dirname;
27
- const ESLINTRC_FILE = ".eslintrc.json";
28
- const README_FILE = "README.md";
29
- function addNodeModulesIgnore(content) {
30
- if (content.includes("**/node_modules/**")) {
31
- return { transformed: false, newContent: content };
32
- }
33
- try {
34
- const json = JSON.parse(content);
35
- const patterns = json.ignorePatterns || [];
36
- const insertIdx = patterns.indexOf("!**/*");
37
- patterns.splice(insertIdx + 1, 0, "**/node_modules/**");
38
- json.ignorePatterns = patterns;
39
- return {
40
- transformed: true,
41
- newContent: JSON.stringify(json, null, 2),
42
- logMessage: `${ESLINTRC_FILE} updated with **/node_modules/** ignorePattern`
43
- };
44
- } catch {
45
- return { transformed: false, newContent: content };
46
- }
47
- }
48
- function migrateReadmeNpmToPnpm(content) {
49
- if (!/(?<![p])npm run\b/.test(content) && !/(?<![p])npm install\b/.test(content)) {
50
- return { transformed: false, newContent: content };
51
- }
52
- let result = content;
53
- result = result.replace(/\bnpm run\b/g, "pnpm run");
54
- result = result.replace(/\bnpm install\b/g, "pnpm install");
55
- if (result === content) {
56
- return { transformed: false, newContent: content };
57
- }
58
- return {
59
- transformed: true,
60
- newContent: result,
61
- logMessage: `${README_FILE} updated npm references to pnpm`
62
- };
63
- }
64
- async function migratePnpmCompatGenerator(tree, options) {
65
- const projectPath = options.project.startsWith("apps/") ? options.project : `apps/${options.project}`;
66
- const targetVersion = (0, import_migration_utils.getPluginVersion)(MODULE_DIR);
67
- import_devkit.logger.info(`\u{1F504} Migrating ${options.project} for pnpm compatibility...`);
68
- const fileProcessor = (0, import_migration_utils.createFileProcessor)([
69
- {
70
- filePath: (p) => `${p}/${ESLINTRC_FILE}`,
71
- shouldProcess: (t, filePath) => {
72
- if (!t.exists(filePath)) return false;
73
- const content = t.read(filePath, "utf-8");
74
- return !!content && !content.includes("**/node_modules/**");
75
- },
76
- processFile: (_t, _filePath, content) => addNodeModulesIgnore(content)
77
- },
78
- {
79
- filePath: (p) => `${p}/${README_FILE}`,
80
- shouldProcess: (t, filePath) => {
81
- if (!t.exists(filePath)) return false;
82
- const content = t.read(filePath, "utf-8");
83
- return !!content && (/(?<![p])npm run\b/.test(content) || /(?<![p])npm install\b/.test(content));
84
- },
85
- processFile: (_t, _filePath, content) => migrateReadmeNpmToPnpm(content)
86
- }
87
- ]);
88
- const result = await fileProcessor(tree, projectPath, targetVersion);
89
- if (result.transformed) {
90
- (0, import_migration_utils.updateBotonicDependencies)(tree, targetVersion, projectPath);
91
- import_devkit.logger.info(`\u2705 ${options.project} updated for pnpm compatibility`);
92
- import_devkit.logger.info(` See migrate-pnpm-compat.md for verification steps`);
93
- } else {
94
- import_devkit.logger.info(`\u2139\uFE0F ${options.project} already up to date \u2013 skipping`);
95
- }
96
- await (0, import_devkit.formatFiles)(tree);
97
- }
@@ -1,15 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/schema",
3
- "$id": "MigratePnpmCompat",
4
- "title": "Migrate bot app for pnpm compatibility",
5
- "description": "Add **/node_modules/** to eslint ignorePatterns and update README npm references to pnpm",
6
- "type": "object",
7
- "properties": {
8
- "project": {
9
- "type": "string",
10
- "description": "The bot project to migrate",
11
- "$default": { "$source": "argv", "index": 0 }
12
- }
13
- },
14
- "required": ["project"]
15
- }
@@ -1,5 +0,0 @@
1
- import type { Tree } from '@nx/devkit';
2
- export interface MigrateWebchatTriggerSchema {
3
- project: string;
4
- }
5
- export default function migrateWebchatTriggerGenerator(tree: Tree, options: MigrateWebchatTriggerSchema): Promise<void>;
@@ -1,165 +0,0 @@
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 generator_exports = {};
20
- __export(generator_exports, {
21
- default: () => migrateWebchatTriggerGenerator
22
- });
23
- module.exports = __toCommonJS(generator_exports);
24
- var import_devkit = require("@nx/devkit");
25
- var import_migration_utils = require("../../../migrations/utils/migration-utils");
26
- const MODULE_DIR = __dirname;
27
- const WEBCHAT_FILE = "src/client/webchat/index.tsx";
28
- const REMOVED_SYMBOLS = /* @__PURE__ */ new Set([
29
- "WebchatTrigger",
30
- "WebchatProvider",
31
- "WebchatContainer",
32
- "WebchatHeader",
33
- "WebchatInput",
34
- "WebchatMessages",
35
- "useWebchatContext"
36
- ]);
37
- function rewriteImports(content) {
38
- const triggerImports = "import type { WebchatTriggerProps } from '@botonic/webchat-react/trigger'\nimport { WebchatTrigger } from '@botonic/webchat-react/trigger'";
39
- const mainImportRegex = /import\s*\{([^}]*)\}\s*from\s*['"]@botonic\/webchat-react['"]\s*;?\s*\n?/g;
40
- return content.replace(mainImportRegex, (_, inner) => {
41
- const symbols = inner.split(",").map(
42
- (s) => s.trim().replace(/\s+as\s+\w+$/, "").split(":")[0].trim()
43
- ).filter((s) => s && !REMOVED_SYMBOLS.has(s));
44
- if (symbols.length === 0) {
45
- return triggerImports + "\n";
46
- }
47
- return `import { ${symbols.join(", ")} } from '@botonic/webchat-react'
48
- ${triggerImports}
49
- `;
50
- });
51
- }
52
- function removeWebchatAppComponent(content) {
53
- const webchatAppRegex = /function\s+WebchatApp\s*\([\s\S]*?\)\s*\{[\s\S]*?\}(?=\s*\n\s*(?:function|const)\s+(?:App|renderWebchat)\b)/m;
54
- return content.replace(webchatAppRegex, "");
55
- }
56
- function replaceWebchatProviderWithTrigger(content) {
57
- const hasCoverComponents = /COVER_COMPONENTS/.test(content);
58
- const coverRegistryLine = hasCoverComponents ? " coverRegistry: COVER_COMPONENTS,\n" : "";
59
- const webchatTriggerBlock = `<WebchatTrigger
60
- appId={webchatConfig.appId}
61
- position='bottom-right'
62
- onReady={handleReady}
63
- webchatConfig={{
64
- avatarConfig,
65
- customMessages,
66
- ${coverRegistryLine} title: options.title || 'Demo Bot',
67
- placeholder: options.placeholder || 'Message...',
68
- }}
69
- />`;
70
- const providerRegex = /<WebchatProvider\s[^>]*>[\s\S]*?<\/WebchatProvider>/g;
71
- let result = content;
72
- const match = result.match(providerRegex);
73
- if (match) {
74
- for (const m of match) {
75
- result = result.replace(m, webchatTriggerBlock);
76
- }
77
- }
78
- return result;
79
- }
80
- function addHandleReady(content) {
81
- if (content.includes("handleReady")) {
82
- return content;
83
- }
84
- const handleReadySnippet = ` // Handle webchat ready \u2013 full control over when/how to open
85
- const handleReady = React.useCallback<
86
- NonNullable<WebchatTriggerProps['onReady']>
87
- >(controller => {
88
- controller.open()
89
- }, [])
90
-
91
- `;
92
- const returnWithProvider = content.match(
93
- /(\s+)(return\s*\(\s*\n\s*)<WebchatProvider/
94
- );
95
- if (returnWithProvider) {
96
- return content.replace(
97
- returnWithProvider[0],
98
- returnWithProvider[1] + handleReadySnippet + returnWithProvider[2] + "<WebchatProvider"
99
- );
100
- }
101
- const appReturnRegex = /(function App\s*\([\s\S]*?\)\s*\{[\s\S]*?)(return \()/m;
102
- return content.replace(appReturnRegex, `$1${handleReadySnippet}$2`);
103
- }
104
- function updateWindowBotonicType(content) {
105
- if (content.includes("ready: Promise<void>")) {
106
- return content;
107
- }
108
- const readySnippet = `
109
- // Ready state
110
- ready: Promise<void>
111
- isReady: () => boolean`;
112
- return content.replace(
113
- /(render:\s*\([\s\S]*?\)\s*=>\s*void)(\s*\n)/,
114
- `$1${readySnippet}$2`
115
- );
116
- }
117
- function processWebchatFile(content) {
118
- if (!content.includes("WebchatTrigger") || content.includes("from '@botonic/webchat-react/trigger'")) {
119
- return { transformed: false, newContent: content };
120
- }
121
- if (!content.includes("WebchatProvider")) {
122
- return { transformed: false, newContent: content };
123
- }
124
- let result = content;
125
- result = rewriteImports(result);
126
- result = removeWebchatAppComponent(result);
127
- result = addHandleReady(result);
128
- result = replaceWebchatProviderWithTrigger(result);
129
- result = updateWindowBotonicType(result);
130
- if (result === content) {
131
- return { transformed: false, newContent: content };
132
- }
133
- return {
134
- transformed: true,
135
- newContent: result,
136
- logMessage: `${WEBCHAT_FILE} migrated to lazy-loading WebchatTrigger`
137
- };
138
- }
139
- async function migrateWebchatTriggerGenerator(tree, options) {
140
- const projectPath = options.project.startsWith("apps/") ? options.project : `apps/${options.project}`;
141
- const targetVersion = (0, import_migration_utils.getPluginVersion)(MODULE_DIR);
142
- import_devkit.logger.info(
143
- `\u{1F504} Migrating ${options.project} to lazy-loading WebchatTrigger...`
144
- );
145
- const fileProcessor = (0, import_migration_utils.createFileProcessor)([
146
- {
147
- filePath: (p) => `${p}/${WEBCHAT_FILE}`,
148
- shouldProcess: (t, filePath) => {
149
- if (!t.exists(filePath)) return false;
150
- const content = t.read(filePath, "utf-8");
151
- return !!content && content.includes("WebchatTrigger") && !content.includes("from '@botonic/webchat-react/trigger'") && content.includes("WebchatProvider");
152
- },
153
- processFile: (_t, _filePath, content) => processWebchatFile(content)
154
- }
155
- ]);
156
- const result = await fileProcessor(tree, projectPath, targetVersion);
157
- if (result.transformed) {
158
- (0, import_migration_utils.updateBotonicDependencies)(tree, targetVersion, projectPath);
159
- import_devkit.logger.info(`\u2705 ${options.project} migrated to lazy-loading WebchatTrigger`);
160
- import_devkit.logger.info(` See migrate-webchat-trigger.md for verification steps`);
161
- } else {
162
- import_devkit.logger.info(`\u2139\uFE0F ${options.project} already up to date \u2013 skipping`);
163
- }
164
- await (0, import_devkit.formatFiles)(tree);
165
- }
@@ -1,15 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/schema",
3
- "$id": "MigrateWebchatTrigger",
4
- "title": "Migrate WebchatTrigger to lazy-loading entry point",
5
- "description": "Migrates a bot app to use @botonic/webchat-react/trigger lazy-loading entry point",
6
- "type": "object",
7
- "properties": {
8
- "project": {
9
- "type": "string",
10
- "description": "The bot project to migrate",
11
- "$default": { "$source": "argv", "index": 0 }
12
- }
13
- },
14
- "required": ["project"]
15
- }
@@ -1,67 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Discovers botonic bot apps and their current versions.
3
- # Uses nx show projects with tag:botonic:bot-app filter.
4
- # Run from workspace root. Output: JSON array of { name, path, version }.
5
- # Usage: bash .cursor/scripts/update-bot/discover-bots.sh
6
-
7
- set -euo pipefail
8
-
9
- # Ensure we're in workspace root (contains apps/ or nx.json)
10
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
- GIT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || true)"
12
- REL_ROOT="$(cd "$SCRIPT_DIR/../../../" && pwd)"
13
- if [[ -n "$GIT_ROOT" ]] && [[ -f "$GIT_ROOT/nx.json" ]]; then
14
- ROOT="$GIT_ROOT"
15
- elif [[ -d "$REL_ROOT/apps" ]] || [[ -f "$REL_ROOT/nx.json" ]]; then
16
- ROOT="$REL_ROOT"
17
- else
18
- ROOT="${GIT_ROOT:-.}"
19
- fi
20
- cd "$ROOT"
21
-
22
- # List bot apps via nx (tag:botonic:bot-app)
23
- # Nx may print plugin messages to stdout; use tail -1 to get JSON only
24
- names=$(npx nx show projects --projects "tag:botonic:bot-app" --json 2>/dev/null | tail -1 || echo "[]")
25
- if [[ "$names" == "[]" ]] || [[ -z "$names" ]]; then
26
- echo "[]"
27
- exit 0
28
- fi
29
-
30
- bots='[]'
31
- for name in $(echo "$names" | node -e "
32
- try {
33
- const arr = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8'));
34
- (Array.isArray(arr) ? arr : []).forEach(n => console.log(n));
35
- } catch {}
36
- "); do
37
- [[ -z "$name" ]] && continue
38
-
39
- path="$name"
40
- if root=$(npx nx show project "$name" --json 2>/dev/null | tail -1 | node -e "try { const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')); process.stdout.write(d.root||''); } catch {}"); then
41
- [[ -n "$root" ]] && path="$root"
42
- else
43
- path="apps/$name"
44
- fi
45
-
46
- version="unknown"
47
- pkg="$ROOT/$path/package.json"
48
- if [[ -f "$pkg" ]]; then
49
- version=$(node -e "
50
- try {
51
- const p = require('$pkg');
52
- const v = p.dependencies?.['@botonic/core']
53
- || p.dependencies?.['@botonic/webchat-react']
54
- || 'unknown';
55
- console.log(String(v).replace(/^[\^~]/, ''));
56
- } catch { console.log('unknown'); }
57
- " 2>/dev/null || echo "unknown")
58
- fi
59
-
60
- bots=$(echo "$bots" | node -e "
61
- const b = JSON.parse(require('fs').readFileSync('/dev/stdin', 'utf8'));
62
- b.push({ name: process.argv[1], path: process.argv[2], version: process.argv[3] });
63
- console.log(JSON.stringify(b, null, 2));
64
- " "$name" "$path" "$version")
65
- done
66
-
67
- echo "$bots"
@@ -1,2 +0,0 @@
1
- import type { Tree } from '@nx/devkit';
2
- export default function addBotonicUpdateBotsSkillMigration(tree: Tree): Promise<void>;
@@ -1,52 +0,0 @@
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 add_botonic_update_bots_skill_migration_exports = {};
30
- __export(add_botonic_update_bots_skill_migration_exports, {
31
- default: () => addBotonicUpdateBotsSkillMigration
32
- });
33
- module.exports = __toCommonJS(add_botonic_update_bots_skill_migration_exports);
34
- var import_devkit = require("@nx/devkit");
35
- var path = __toESM(require("path"));
36
- const MODULE_DIR = __dirname;
37
- const UPDATE_BOTONIC_MD = ".cursor/commands/update-botonic.md";
38
- const UPDATE_BOT_MD = ".cursor/commands/update-bot.md";
39
- async function addBotonicUpdateBotsSkillMigration(tree) {
40
- const botUpdateExists = tree.exists(UPDATE_BOT_MD);
41
- const botonicUpdateExists = tree.exists(UPDATE_BOTONIC_MD);
42
- if (botUpdateExists && botonicUpdateExists) {
43
- import_devkit.logger.info(
44
- "update-botonic and update-bot commands already present \u2013 skipping"
45
- );
46
- return;
47
- }
48
- (0, import_devkit.generateFiles)(tree, path.join(MODULE_DIR, "files"), ".", {});
49
- if (!botonicUpdateExists) import_devkit.logger.info("Added /update-botonic Cursor command");
50
- if (!botUpdateExists) import_devkit.logger.info("Added /update-bot Cursor command");
51
- await (0, import_devkit.formatFiles)(tree);
52
- }
@@ -1,23 +0,0 @@
1
- # Add /update-bot Cursor Command Migration
2
-
3
- ## Summary
4
-
5
- This migration adds the `/update-bot` Cursor command to your workspace. The command helps you update Botonic bot apps to newer versions using Nx migrations, one bot at a time, with git branch management.
6
-
7
- ## What the automated migration does
8
-
9
- - Creates `.cursor/commands/update-bot.md` — workflow and examples
10
- - Creates `.cursor/scripts/update-bot/discover-bots.sh` — finds bot apps via `nx show projects --projects "tag:botonic:bot-app"`
11
- - Creates `.cursor/scripts/update-bot/find-migration-guides.sh` — finds `<name>.migration.md` files between versions
12
-
13
- ## How to use the command
14
-
15
- 1. In Cursor, type `/update-bot` in the chat input and run it
16
- 2. The command discovers your bots, lets you pick one, and runs `nx migrate` one version at a time
17
- 3. For each version step, it reads any migration guide (`<name>.migration.md`) and guides you through verification
18
-
19
- ## Verification checklist
20
-
21
- - [ ] `.cursor/commands/update-bot.md` exists
22
- - [ ] Run `bash .cursor/scripts/update-bot/discover-bots.sh` from workspace root — returns JSON list of bots (or `[]` if none)
23
- - [ ] Run `bash .cursor/scripts/update-bot/find-migration-guides.sh 0.0.0 999.0.0` — returns JSON array (may be empty)
@@ -1,5 +0,0 @@
1
- # Update Botonic Bot
2
-
3
- Applies pending bot-app migrations from `.botonic/pending-bot-migrations.json` to a single bot.
4
-
5
- Follow the full workflow in: `node_modules/@botonic/nx-plugin/src/cursor-commands/update-bot.md`
@@ -1,5 +0,0 @@
1
- # Update Botonic Workspace
2
-
3
- Updates the Botonic plugin to the latest version and queues pending bot-app migrations.
4
-
5
- Follow the full workflow in: `node_modules/@botonic/nx-plugin/src/cursor-commands/update-botonic.md`
@@ -1,70 +0,0 @@
1
- #!/usr/bin/env bash
2
- # Finds <name>.migration.md files for migrations between two versions.
3
- # Reads node_modules/@botonic/nx-plugin/migrations.json (published, real semver).
4
- # Usage: find-migration-guides.sh <from-version> <to-version>
5
- # Output: JSON array of { version, migrations: [{ name, migrationGuide }] } grouped by unique version
6
-
7
- set -euo pipefail
8
-
9
- FROM_VERSION="${1:?Usage: find-migration-guides.sh <from> <to>}"
10
- TO_VERSION="${2:?Usage: find-migration-guides.sh <from> <to>}"
11
-
12
- # Run from workspace root
13
- SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
14
- GIT_ROOT="$(git rev-parse --show-toplevel 2>/dev/null || true)"
15
- REL_ROOT="$(cd "$SCRIPT_DIR/../../../" && pwd)"
16
- if [[ -n "$GIT_ROOT" ]] && [[ -f "$GIT_ROOT/nx.json" ]]; then
17
- ROOT="$GIT_ROOT"
18
- elif [[ -f "$REL_ROOT/nx.json" ]] || [[ -f "$REL_ROOT/node_modules/@botonic/nx-plugin/migrations.json" ]]; then
19
- ROOT="$REL_ROOT"
20
- else
21
- ROOT="${GIT_ROOT:-$REL_ROOT}"
22
- fi
23
- cd "$ROOT"
24
-
25
- MIGRATIONS_JSON="node_modules/@botonic/nx-plugin/migrations.json"
26
- MIGRATIONS_DIR="node_modules/@botonic/nx-plugin/src/migrations"
27
-
28
- if [ ! -f "$MIGRATIONS_JSON" ]; then
29
- echo '{"error": "migrations.json not found. Run pnpm install first."}' >&2
30
- exit 1
31
- fi
32
-
33
- node -e "
34
- const fs = require('fs');
35
- const path = require('path');
36
- let semver;
37
- try { semver = require('semver'); } catch { semver = null; }
38
-
39
- const mj = JSON.parse(fs.readFileSync('$MIGRATIONS_JSON', 'utf8'));
40
- const generators = mj.generators || {};
41
- const from = '$FROM_VERSION';
42
- const to = '$TO_VERSION';
43
- const migrationsDir = path.resolve('$MIGRATIONS_DIR');
44
-
45
- const valid = (v) => semver ? semver.valid(v) : /^\\d+\\.\\d+\\.\\d+$/.test(v);
46
- const gt = (a, b) => semver ? semver.gt(a, b) : a !== b;
47
- const lte = (a, b) => semver ? semver.lte(a, b) : true;
48
- const compare = (a, b) => semver ? semver.compare(a, b) : 0;
49
-
50
- const entries = Object.entries(generators)
51
- .filter(([, cfg]) => valid(cfg.version) && gt(cfg.version, from) && lte(cfg.version, to))
52
- .sort(([, a], [, b]) => compare(a.version, b.version));
53
-
54
- const byVersion = new Map();
55
- for (const [name, cfg] of entries) {
56
- const guideFile = path.join(migrationsDir, name, \`\${name}.migration.md\`);
57
- const migrationGuide = fs.existsSync(guideFile) ? guideFile : null;
58
- if (!byVersion.has(cfg.version)) {
59
- byVersion.set(cfg.version, []);
60
- }
61
- byVersion.get(cfg.version).push({ name, migrationGuide });
62
- }
63
-
64
- const results = Array.from(byVersion.entries()).map(([version, migrations]) => ({
65
- version,
66
- migrations
67
- }));
68
-
69
- console.log(JSON.stringify(results, null, 2));
70
- "
@@ -1,5 +0,0 @@
1
- {
2
- "$schema": "http://json-schema.org/schema",
3
- "type": "object",
4
- "properties": {}
5
- }
@@ -1,2 +0,0 @@
1
- import type { Tree } from '@nx/devkit';
2
- export default function addLilaraRegistry(tree: Tree): Promise<void>;