@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.
- package/CHANGELOG.md +29 -0
- package/README.md +4 -4
- package/generators.json +0 -26
- package/migrations.json +1 -38
- package/package.json +1 -1
- package/src/executors/e2e-webchat/botonic-package-publish.spec.ts +3 -3
- package/src/executors/serve-bot/executor.js +98 -16
- package/src/executors/serve-bot/schema.json +10 -0
- package/src/generators/action/files/__name__.spec.ts.template +4 -4
- package/src/generators/action/files/__name__.ts.template +5 -5
- package/src/generators/action/generator.js +1 -1
- package/src/generators/bot-app/files/.eslintrc.json.template +30 -1
- package/src/generators/bot-app/files/src/client/webchat/index.tsx.template +1 -6
- package/src/generators/bot-app/files/src/server/bot/actions/not-found.ts.template +7 -6
- package/src/generators/bot-app/files/src/server/bot/actions/welcome.ts.template +7 -6
- package/src/generators/bot-app/files/src/server/bot/index.ts.template +9 -11
- package/src/generators/bot-app/files/src/server/bot/plugins/ai-agents/index.ts.template +4 -4
- package/src/generators/bot-app/files/src/server/bot/plugins/flow-builder/index.ts.template +5 -5
- package/src/generators/bot-app/files/src/server/bot/routes.ts.template +5 -5
- package/src/generators/bot-app/files/src/server/bot/tracking.ts.template +4 -4
- package/src/generators/bot-app/files/src/server/lambda/handler.js.template +1 -6
- package/src/generators/bot-app/files/vite/plugins/dev-log-viewer-html.plugin.ts.template +65 -0
- package/src/generators/bot-app/files/vite/webchat.config.ts.template +14 -1
- package/src/generators/bot-app/generator.js +6 -2
- package/src/generators/bot-app/lilara-version.json +1 -1
- package/src/generators/bot-app/schema.d.ts +1 -0
- package/src/generators/bot-app/schema.json +4 -0
- package/src/generators/custom-message/files/__name__-output.ts.template +12 -10
- package/src/generators/custom-message/generator.js +1 -1
- package/src/{cursor-commands → generators/preset/files/.claude/commands}/update-bot.md +7 -7
- package/src/{cursor-commands → generators/preset/files/.claude/commands}/update-botonic.md +5 -3
- package/src/{migrations/add-botonic-update-bots-skill/files/.cursor → generators/preset/files/.claude}/scripts/update-bot/discover-bots.sh +1 -1
- package/src/generators/preset/files/{.cursor → .claude}/skills/botonic-action/SKILL.md +21 -21
- package/src/generators/preset/files/{.cursor → .claude}/skills/botonic-custom-message/SKILL.md +11 -12
- package/src/generators/preset/files/{.cursor → .claude}/skills/botonic-webview/SKILL.md +8 -8
- package/src/generators/preset/files/.cursor/commands/update-bot.md +1 -3
- package/src/generators/preset/files/.cursor/commands/update-botonic.md +1 -3
- package/src/lib/util/executor-helpers.d.ts +0 -1
- package/src/lib/util/executor-helpers.js +1 -8
- package/src/generators/bot-app-migrations/migrate-fix-css-code-split/generator.d.ts +0 -5
- package/src/generators/bot-app-migrations/migrate-fix-css-code-split/generator.js +0 -92
- package/src/generators/bot-app-migrations/migrate-fix-css-code-split/schema.json +0 -15
- package/src/generators/bot-app-migrations/migrate-pnpm-compat/generator.d.ts +0 -5
- package/src/generators/bot-app-migrations/migrate-pnpm-compat/generator.js +0 -97
- package/src/generators/bot-app-migrations/migrate-pnpm-compat/schema.json +0 -15
- package/src/generators/bot-app-migrations/migrate-webchat-trigger/generator.d.ts +0 -5
- package/src/generators/bot-app-migrations/migrate-webchat-trigger/generator.js +0 -165
- package/src/generators/bot-app-migrations/migrate-webchat-trigger/schema.json +0 -15
- package/src/generators/preset/files/.cursor/scripts/update-bot/discover-bots.sh +0 -67
- package/src/migrations/add-botonic-update-bots-skill/add-botonic-update-bots-skill.migration.d.ts +0 -2
- package/src/migrations/add-botonic-update-bots-skill/add-botonic-update-bots-skill.migration.js +0 -52
- package/src/migrations/add-botonic-update-bots-skill/add-botonic-update-bots-skill.migration.md +0 -23
- package/src/migrations/add-botonic-update-bots-skill/files/.cursor/commands/update-bot.md +0 -5
- package/src/migrations/add-botonic-update-bots-skill/files/.cursor/commands/update-botonic.md +0 -5
- package/src/migrations/add-botonic-update-bots-skill/files/.cursor/scripts/update-bot/find-migration-guides.sh +0 -70
- package/src/migrations/add-botonic-update-bots-skill/schema.json +0 -5
- package/src/migrations/add-lilara-registry/add-lilara-registry.migration.d.ts +0 -2
- package/src/migrations/add-lilara-registry/add-lilara-registry.migration.js +0 -49
- package/src/migrations/add-lilara-registry/schema.json +0 -5
- package/src/migrations/fix-css-code-split/fix-css-code-split.migration.md +0 -45
- package/src/migrations/remove-codeartifact-registry/remove-codeartifact-registry.migration.d.ts +0 -2
- package/src/migrations/remove-codeartifact-registry/remove-codeartifact-registry.migration.js +0 -59
- package/src/migrations/remove-codeartifact-registry/schema.json +0 -5
- package/src/migrations/sync-pending-bot-migrations/schema.json +0 -5
- package/src/migrations/sync-pending-bot-migrations/sync-pending-bot-migrations.migration.d.ts +0 -2
- package/src/migrations/sync-pending-bot-migrations/sync-pending-bot-migrations.migration.js +0 -137
- package/src/migrations/sync-pending-bot-migrations/sync-pending-bot-migrations.migration.md +0 -19
- package/src/migrations/update-cursor-commands-to-stubs/schema.json +0 -5
- package/src/migrations/update-cursor-commands-to-stubs/update-cursor-commands-to-stubs.migration.d.ts +0 -2
- package/src/migrations/update-cursor-commands-to-stubs/update-cursor-commands-to-stubs.migration.js +0 -61
- package/src/migrations/update-pnpm-workspace-scripts/schema.json +0 -4
- package/src/migrations/update-pnpm-workspace-scripts/update-pnpm-workspace-scripts.migration.d.ts +0 -2
- package/src/migrations/update-pnpm-workspace-scripts/update-pnpm-workspace-scripts.migration.js +0 -47
- /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,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,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"
|
package/src/migrations/add-botonic-update-bots-skill/add-botonic-update-bots-skill.migration.js
DELETED
|
@@ -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
|
-
}
|
package/src/migrations/add-botonic-update-bots-skill/add-botonic-update-bots-skill.migration.md
DELETED
|
@@ -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,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
|
-
"
|