@ikas/component-cli 1.4.0-beta.6 → 1.4.0-beta.60
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/dist/commands/add-sections-to-page.d.ts +3 -0
- package/dist/commands/add-sections-to-page.d.ts.map +1 -0
- package/dist/commands/add-sections-to-page.js +39 -0
- package/dist/commands/add-sections-to-page.js.map +1 -0
- package/dist/commands/add-to-page.d.ts +3 -0
- package/dist/commands/add-to-page.d.ts.map +1 -0
- package/dist/commands/add-to-page.js +41 -0
- package/dist/commands/add-to-page.js.map +1 -0
- package/dist/commands/build.d.ts.map +1 -1
- package/dist/commands/build.js +5 -165
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +230 -114
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/create-design-tokens.d.ts +7 -0
- package/dist/commands/create-design-tokens.d.ts.map +1 -0
- package/dist/commands/create-design-tokens.js +127 -0
- package/dist/commands/create-design-tokens.js.map +1 -0
- package/dist/commands/create-global-variable.d.ts +3 -0
- package/dist/commands/create-global-variable.d.ts.map +1 -0
- package/dist/commands/create-global-variable.js +53 -0
- package/dist/commands/create-global-variable.js.map +1 -0
- package/dist/commands/create-page.d.ts +3 -0
- package/dist/commands/create-page.d.ts.map +1 -0
- package/dist/commands/create-page.js +31 -0
- package/dist/commands/create-page.js.map +1 -0
- package/dist/commands/create.d.ts +3 -8
- package/dist/commands/create.d.ts.map +1 -1
- package/dist/commands/create.js +175 -8
- package/dist/commands/create.js.map +1 -1
- package/dist/commands/delete-theme-globals.d.ts +4 -0
- package/dist/commands/delete-theme-globals.d.ts.map +1 -0
- package/dist/commands/delete-theme-globals.js +48 -0
- package/dist/commands/delete-theme-globals.js.map +1 -0
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +220 -25
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/get-component-props.d.ts +3 -0
- package/dist/commands/get-component-props.d.ts.map +1 -0
- package/dist/commands/get-component-props.js +32 -0
- package/dist/commands/get-component-props.js.map +1 -0
- package/dist/commands/get-page-by-type.d.ts +3 -0
- package/dist/commands/get-page-by-type.d.ts.map +1 -0
- package/dist/commands/get-page-by-type.js +25 -0
- package/dist/commands/get-page-by-type.js.map +1 -0
- package/dist/commands/get-section-values.d.ts +3 -0
- package/dist/commands/get-section-values.d.ts.map +1 -0
- package/dist/commands/get-section-values.js +39 -0
- package/dist/commands/get-section-values.js.map +1 -0
- package/dist/commands/import.d.ts +3 -0
- package/dist/commands/import.d.ts.map +1 -0
- package/dist/commands/import.js +25 -0
- package/dist/commands/import.js.map +1 -0
- package/dist/commands/list-entities.d.ts +3 -0
- package/dist/commands/list-entities.d.ts.map +1 -0
- package/dist/commands/list-entities.js +32 -0
- package/dist/commands/list-entities.js.map +1 -0
- package/dist/commands/list-imported.d.ts +3 -0
- package/dist/commands/list-imported.d.ts.map +1 -0
- package/dist/commands/list-imported.js +25 -0
- package/dist/commands/list-imported.js.map +1 -0
- package/dist/commands/list-page-sections.d.ts +3 -0
- package/dist/commands/list-page-sections.d.ts.map +1 -0
- package/dist/commands/list-page-sections.js +25 -0
- package/dist/commands/list-page-sections.js.map +1 -0
- package/dist/commands/list-pages.d.ts +3 -0
- package/dist/commands/list-pages.d.ts.map +1 -0
- package/dist/commands/list-pages.js +21 -0
- package/dist/commands/list-pages.js.map +1 -0
- package/dist/commands/list-theme-globals.d.ts +3 -0
- package/dist/commands/list-theme-globals.d.ts.map +1 -0
- package/dist/commands/list-theme-globals.js +22 -0
- package/dist/commands/list-theme-globals.js.map +1 -0
- package/dist/commands/publish-theme.d.ts +3 -0
- package/dist/commands/publish-theme.d.ts.map +1 -0
- package/dist/commands/publish-theme.js +29 -0
- package/dist/commands/publish-theme.js.map +1 -0
- package/dist/commands/search-products.d.ts +3 -0
- package/dist/commands/search-products.d.ts.map +1 -0
- package/dist/commands/search-products.js +40 -0
- package/dist/commands/search-products.js.map +1 -0
- package/dist/commands/update-global-variable.d.ts +3 -0
- package/dist/commands/update-global-variable.d.ts.map +1 -0
- package/dist/commands/update-global-variable.js +47 -0
- package/dist/commands/update-global-variable.js.map +1 -0
- package/dist/commands/update-page-sections.d.ts +3 -0
- package/dist/commands/update-page-sections.d.ts.map +1 -0
- package/dist/commands/update-page-sections.js +39 -0
- package/dist/commands/update-page-sections.js.map +1 -0
- package/dist/commands/update-section-prop.d.ts +3 -0
- package/dist/commands/update-section-prop.d.ts.map +1 -0
- package/dist/commands/update-section-prop.js +59 -0
- package/dist/commands/update-section-prop.js.map +1 -0
- package/dist/commands/upload-image.d.ts +3 -0
- package/dist/commands/upload-image.d.ts.map +1 -0
- package/dist/commands/upload-image.js +38 -0
- package/dist/commands/upload-image.js.map +1 -0
- package/dist/commands/upload-images.d.ts +3 -0
- package/dist/commands/upload-images.d.ts.map +1 -0
- package/dist/commands/upload-images.js +48 -0
- package/dist/commands/upload-images.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +11 -1
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/compile.d.ts +4 -1
- package/dist/utils/compile.d.ts.map +1 -1
- package/dist/utils/compile.js +517 -48
- package/dist/utils/compile.js.map +1 -1
- package/dist/utils/component-helpers.d.ts +3 -3
- package/dist/utils/component-helpers.d.ts.map +1 -1
- package/dist/utils/component-helpers.js +75 -4
- package/dist/utils/component-helpers.js.map +1 -1
- package/dist/utils/editor-action-client.d.ts +28 -0
- package/dist/utils/editor-action-client.d.ts.map +1 -0
- package/dist/utils/editor-action-client.js +116 -0
- package/dist/utils/editor-action-client.js.map +1 -0
- package/dist/utils/load-image.d.ts +16 -0
- package/dist/utils/load-image.d.ts.map +1 -0
- package/dist/utils/load-image.js +50 -0
- package/dist/utils/load-image.js.map +1 -0
- package/dist/utils/websocket-server.d.ts +52 -2
- package/dist/utils/websocket-server.d.ts.map +1 -1
- package/dist/utils/websocket-server.js +59 -1
- package/dist/utils/websocket-server.js.map +1 -1
- package/package.json +1 -1
- package/dist/commands/proxy.d.ts +0 -39
- package/dist/commands/proxy.d.ts.map +0 -1
- package/dist/commands/proxy.js +0 -212
- package/dist/commands/proxy.js.map +0 -1
package/dist/commands/create.js
CHANGED
|
@@ -1,9 +1,176 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import inquirer from "inquirer";
|
|
5
|
+
import ora from "ora";
|
|
6
|
+
import * as path from "path";
|
|
7
|
+
import { generateComponentId, generateProjectId } from "../utils/component-helpers.js";
|
|
8
|
+
import { readTemplate } from "../utils/template.js";
|
|
9
|
+
const PROP_TYPES = [
|
|
10
|
+
"TEXT",
|
|
11
|
+
"NUMBER",
|
|
12
|
+
"BOOLEAN",
|
|
13
|
+
"IMAGE",
|
|
14
|
+
"LINK",
|
|
15
|
+
"LIST_OF_LINK",
|
|
16
|
+
"COLOR",
|
|
17
|
+
"PRODUCT",
|
|
18
|
+
"PRODUCT_LIST",
|
|
19
|
+
"CATEGORY",
|
|
20
|
+
"CATEGORY_LIST",
|
|
21
|
+
"BRAND",
|
|
22
|
+
"BRAND_LIST",
|
|
23
|
+
"BLOG",
|
|
24
|
+
"BLOG_LIST",
|
|
25
|
+
"BLOG_CATEGORY",
|
|
26
|
+
"BLOG_CATEGORY_LIST",
|
|
27
|
+
"TYPE",
|
|
28
|
+
"ENUM",
|
|
29
|
+
"COMPONENT",
|
|
30
|
+
"COMPONENT_LIST",
|
|
31
|
+
];
|
|
32
|
+
async function createProject(projectName) {
|
|
33
|
+
const spinner = ora("Creating project...").start();
|
|
34
|
+
try {
|
|
35
|
+
const projectPath = path.resolve(process.cwd(), projectName);
|
|
36
|
+
// Check if directory exists
|
|
37
|
+
if (fs.existsSync(projectPath)) {
|
|
38
|
+
spinner.fail(`Directory "${projectName}" already exists`);
|
|
39
|
+
process.exit(1);
|
|
40
|
+
}
|
|
41
|
+
// Create directory structure
|
|
42
|
+
fs.mkdirSync(projectPath, { recursive: true });
|
|
43
|
+
fs.mkdirSync(path.join(projectPath, "src/components/ExampleComponent"), { recursive: true });
|
|
44
|
+
fs.mkdirSync(path.join(projectPath, "src/components/ExampleSection"), { recursive: true });
|
|
45
|
+
// Generate IDs for the example config
|
|
46
|
+
const projectId = generateProjectId();
|
|
47
|
+
const exampleComponentId = generateComponentId(projectId, "example-component");
|
|
48
|
+
const exampleSectionId = generateComponentId(projectId, "example-section");
|
|
49
|
+
const vars = {
|
|
50
|
+
PROJECT_NAME: projectName,
|
|
51
|
+
PROJECT_ID: projectId,
|
|
52
|
+
EXAMPLE_COMPONENT_ID: exampleComponentId,
|
|
53
|
+
EXAMPLE_SECTION_ID: exampleSectionId,
|
|
54
|
+
};
|
|
55
|
+
// Write all template files
|
|
56
|
+
const files = [
|
|
57
|
+
{ template: "create/package.json", dest: "package.json", vars },
|
|
58
|
+
{ template: "create/tsconfig.json", dest: "tsconfig.json" },
|
|
59
|
+
{ template: "create/vite.config.ts", dest: "vite.config.ts" },
|
|
60
|
+
{ template: "create/ikas.config.json", dest: "ikas.config.json", vars },
|
|
61
|
+
{ template: "create/gitignore", dest: ".gitignore" },
|
|
62
|
+
{ template: "create/mcp.json", dest: ".mcp.json" },
|
|
63
|
+
{ template: "create/README.md", dest: "README.md", vars },
|
|
64
|
+
{ template: "create/claude-md", dest: "CLAUDE.md" },
|
|
65
|
+
{ template: "create/cursorrules", dest: ".cursorrules" },
|
|
66
|
+
{ template: "create/src/global.css", dest: "src/global.css" },
|
|
67
|
+
{ template: "create/src/global-types.ts", dest: "src/global-types.ts" },
|
|
68
|
+
{ template: "create/src/ikas-component-utils.d.ts", dest: "src/ikas-component-utils.d.ts" },
|
|
69
|
+
{ template: "create/src/components/index.ts", dest: "src/components/index.ts" },
|
|
70
|
+
{ template: "create/src/components/ExampleComponent/index.tsx", dest: "src/components/ExampleComponent/index.tsx" },
|
|
71
|
+
{ template: "create/src/components/ExampleComponent/types.ts", dest: "src/components/ExampleComponent/types.ts" },
|
|
72
|
+
{ template: "create/src/components/ExampleComponent/styles.css", dest: "src/components/ExampleComponent/styles.css" },
|
|
73
|
+
{ template: "create/src/components/ExampleSection/index.tsx", dest: "src/components/ExampleSection/index.tsx" },
|
|
74
|
+
{ template: "create/src/components/ExampleSection/types.ts", dest: "src/components/ExampleSection/types.ts" },
|
|
75
|
+
{ template: "create/src/components/ExampleSection/styles.css", dest: "src/components/ExampleSection/styles.css" },
|
|
76
|
+
];
|
|
77
|
+
for (const file of files) {
|
|
78
|
+
fs.writeFileSync(path.join(projectPath, file.dest), readTemplate(file.template, file.vars));
|
|
79
|
+
}
|
|
80
|
+
// Create or merge .cursor/mcp.json for Cursor editor
|
|
81
|
+
// Uses node + ${workspaceFolder} instead of npx because Cursor
|
|
82
|
+
// doesn't reliably inherit the shell PATH.
|
|
83
|
+
const cursorDir = path.join(projectPath, ".cursor");
|
|
84
|
+
const cursorMcpPath = path.join(cursorDir, "mcp.json");
|
|
85
|
+
fs.mkdirSync(cursorDir, { recursive: true });
|
|
86
|
+
let cursorMcpConfig = { mcpServers: {} };
|
|
87
|
+
if (fs.existsSync(cursorMcpPath)) {
|
|
88
|
+
try {
|
|
89
|
+
cursorMcpConfig = JSON.parse(fs.readFileSync(cursorMcpPath, "utf-8"));
|
|
90
|
+
if (!cursorMcpConfig.mcpServers) {
|
|
91
|
+
cursorMcpConfig.mcpServers = {};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
cursorMcpConfig = { mcpServers: {} };
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
cursorMcpConfig.mcpServers["ikas-code-components"] = {
|
|
99
|
+
command: "node",
|
|
100
|
+
args: ["${workspaceFolder}/node_modules/@ikas/code-components-mcp/dist/index.js"]
|
|
101
|
+
};
|
|
102
|
+
fs.writeFileSync(cursorMcpPath, JSON.stringify(cursorMcpConfig, null, 2));
|
|
103
|
+
spinner.succeed(chalk.green(`Project "${projectName}" created successfully!`));
|
|
104
|
+
console.log("\n" + chalk.cyan("Next steps:"));
|
|
105
|
+
console.log(chalk.white(` cd ${projectName}`));
|
|
106
|
+
console.log(chalk.white(" npm install"));
|
|
107
|
+
console.log(chalk.white(" npm run dev"));
|
|
108
|
+
console.log("\n" + chalk.gray("Happy coding! 🚀"));
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
spinner.fail("Failed to create project");
|
|
112
|
+
console.error(error);
|
|
113
|
+
process.exit(1);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
export function createCreateCommand() {
|
|
117
|
+
return new Command("create")
|
|
118
|
+
.description("Create a new ikas component project")
|
|
119
|
+
.argument("[name]", "Project name")
|
|
120
|
+
.action(async (name) => {
|
|
121
|
+
let projectName = name;
|
|
122
|
+
if (!projectName) {
|
|
123
|
+
const answers = await inquirer.prompt([
|
|
124
|
+
{
|
|
125
|
+
type: "input",
|
|
126
|
+
name: "projectName",
|
|
127
|
+
message: "What is your project name?",
|
|
128
|
+
default: "my-ikas-components",
|
|
129
|
+
validate: (input) => {
|
|
130
|
+
if (!input.trim())
|
|
131
|
+
return "Project name is required";
|
|
132
|
+
if (!/^[a-z0-9-_]+$/i.test(input)) {
|
|
133
|
+
return "Project name can only contain letters, numbers, hyphens, and underscores";
|
|
134
|
+
}
|
|
135
|
+
return true;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
]);
|
|
139
|
+
projectName = answers.projectName;
|
|
140
|
+
}
|
|
141
|
+
await createProject(projectName);
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
// Standalone runner for create-ikas-component command
|
|
145
|
+
export async function run() {
|
|
146
|
+
const program = new Command();
|
|
147
|
+
program
|
|
148
|
+
.name("create-ikas-component")
|
|
149
|
+
.description("Create a new ikas component project")
|
|
150
|
+
.argument("[name]", "Project name")
|
|
151
|
+
.action(async (name) => {
|
|
152
|
+
let projectName = name;
|
|
153
|
+
if (!projectName) {
|
|
154
|
+
const answers = await inquirer.prompt([
|
|
155
|
+
{
|
|
156
|
+
type: "input",
|
|
157
|
+
name: "projectName",
|
|
158
|
+
message: "What is your project name?",
|
|
159
|
+
default: "my-ikas-components",
|
|
160
|
+
validate: (input) => {
|
|
161
|
+
if (!input.trim())
|
|
162
|
+
return "Project name is required";
|
|
163
|
+
if (!/^[a-z0-9-_]+$/i.test(input)) {
|
|
164
|
+
return "Project name can only contain letters, numbers, hyphens, and underscores";
|
|
165
|
+
}
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
]);
|
|
170
|
+
projectName = answers.projectName;
|
|
171
|
+
}
|
|
172
|
+
await createProject(projectName);
|
|
173
|
+
});
|
|
174
|
+
program.parse(process.argv);
|
|
175
|
+
}
|
|
9
176
|
//# sourceMappingURL=create.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,IAAI,
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../src/commands/create.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete-theme-globals.d.ts","sourceRoot":"","sources":["../../src/commands/delete-theme-globals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAWpC,wBAAgB,iCAAiC,IAAI,OAAO,CAe3D;AAED,wBAAgB,8BAA8B,IAAI,OAAO,CAyBxD"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { printErrorAndExit, printResultAndExit, runEditorAction } from "../utils/editor-action-client.js";
|
|
3
|
+
const TOKEN_TYPES = ["color", "typography", "breakpoint", "keyframe", "colorScheme"];
|
|
4
|
+
function portOpts(port) {
|
|
5
|
+
const p = port ? parseInt(port, 10) : undefined;
|
|
6
|
+
return p ? { port: p } : {};
|
|
7
|
+
}
|
|
8
|
+
export function createDeleteGlobalVariableCommand() {
|
|
9
|
+
const cmd = new Command("delete-global-variable");
|
|
10
|
+
cmd
|
|
11
|
+
.description("Delete a global variable from the connected editor")
|
|
12
|
+
.requiredOption("--name <key>", "The variable's runtime key (from `list-theme-globals`)")
|
|
13
|
+
.option("--port <port>", "Dev server WebSocket port", "5201")
|
|
14
|
+
.action(async (options) => {
|
|
15
|
+
if (!options.name)
|
|
16
|
+
printErrorAndExit(new Error("--name is required"));
|
|
17
|
+
try {
|
|
18
|
+
printResultAndExit(await runEditorAction("delete-global-variable", { name: options.name }, portOpts(options.port)));
|
|
19
|
+
}
|
|
20
|
+
catch (e) {
|
|
21
|
+
printErrorAndExit(e);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
return cmd;
|
|
25
|
+
}
|
|
26
|
+
export function createDeleteDesignTokenCommand() {
|
|
27
|
+
const cmd = new Command("delete-design-token");
|
|
28
|
+
cmd
|
|
29
|
+
.description("Delete a design token (color, typography, breakpoint, keyframe, or color scheme) from the connected editor")
|
|
30
|
+
.requiredOption("--token-type <type>", TOKEN_TYPES.join(" | "))
|
|
31
|
+
.requiredOption("--id <id>", "The token id (from `list-theme-globals`)")
|
|
32
|
+
.option("--port <port>", "Dev server WebSocket port", "5201")
|
|
33
|
+
.action(async (options) => {
|
|
34
|
+
if (!options.tokenType || !TOKEN_TYPES.includes(options.tokenType)) {
|
|
35
|
+
printErrorAndExit(new Error(`--token-type must be one of: ${TOKEN_TYPES.join(", ")}`));
|
|
36
|
+
}
|
|
37
|
+
if (!options.id)
|
|
38
|
+
printErrorAndExit(new Error("--id is required"));
|
|
39
|
+
try {
|
|
40
|
+
printResultAndExit(await runEditorAction("delete-design-token", { tokenType: options.tokenType, id: options.id }, portOpts(options.port)));
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
printErrorAndExit(e);
|
|
44
|
+
}
|
|
45
|
+
});
|
|
46
|
+
return cmd;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=delete-theme-globals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete-theme-globals.js","sourceRoot":"","sources":["../../src/commands/delete-theme-globals.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,iBAAiB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAE1G,MAAM,WAAW,GAAG,CAAC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;AAErF,SAAS,QAAQ,CAAC,IAAa;IAC7B,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAChD,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAC9B,CAAC;AAED,MAAM,UAAU,iCAAiC;IAC/C,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,wBAAwB,CAAC,CAAC;IAClD,GAAG;SACA,WAAW,CAAC,oDAAoD,CAAC;SACjE,cAAc,CAAC,cAAc,EAAE,wDAAwD,CAAC;SACxF,MAAM,CAAC,eAAe,EAAE,2BAA2B,EAAE,MAAM,CAAC;SAC5D,MAAM,CAAC,KAAK,EAAE,OAAyC,EAAE,EAAE;QAC1D,IAAI,CAAC,OAAO,CAAC,IAAI;YAAE,iBAAiB,CAAC,IAAI,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC;QACtE,IAAI,CAAC;YACH,kBAAkB,CAAC,MAAM,eAAe,CAAC,wBAAwB,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACtH,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,iBAAiB,CAAC,CAAC,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;IACL,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,8BAA8B;IAC5C,MAAM,GAAG,GAAG,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC/C,GAAG;SACA,WAAW,CAAC,4GAA4G,CAAC;SACzH,cAAc,CAAC,qBAAqB,EAAE,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;SAC9D,cAAc,CAAC,WAAW,EAAE,0CAA0C,CAAC;SACvE,MAAM,CAAC,eAAe,EAAE,2BAA2B,EAAE,MAAM,CAAC;SAC5D,MAAM,CAAC,KAAK,EAAE,OAA2D,EAAE,EAAE;QAC5E,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC;YACnE,iBAAiB,CAAC,IAAI,KAAK,CAAC,gCAAgC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;QACzF,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,EAAE;YAAE,iBAAiB,CAAC,IAAI,KAAK,CAAC,kBAAkB,CAAC,CAAC,CAAC;QAClE,IAAI,CAAC;YACH,kBAAkB,CAChB,MAAM,eAAe,CACnB,qBAAqB,EACrB,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,EAChD,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CACvB,CACF,CAAC;QACJ,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,iBAAiB,CAAC,CAAC,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;IACL,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/commands/dev.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAwlDpC,wBAAgB,gBAAgB,IAAI,OAAO,CAI1C"}
|
package/dist/commands/dev.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import chokidar from "chokidar";
|
|
3
3
|
import { Command } from "commander";
|
|
4
|
+
import * as crypto from "crypto";
|
|
4
5
|
import * as fs from "fs";
|
|
5
6
|
import * as path from "path";
|
|
6
7
|
import { toPascalCase, generateTypesFile, generateGlobalTypesFile, collectUsedEnumIds, collectUsedCustomTypeIds, generateComponentFile, generateStylesFile, updateBarrelExport, generateProjectId, generateComponentId, generateUniqueId, buildPropGroupHierarchy, findPropGroup, collectPropGroupIds, movePropGroupInTree, validateFilteredComponentIds, } from "../utils/component-helpers.js";
|
|
@@ -12,10 +13,20 @@ const DEV_SERVER_PORT = 5201;
|
|
|
12
13
|
const compiledComponents = new Map();
|
|
13
14
|
const compiledSharedModules = new Map();
|
|
14
15
|
let compiledGlobalStyles;
|
|
16
|
+
// Hashes broadcast on the last cycle, used to compute deltas. Reset only on process
|
|
17
|
+
// startup. Editors compare these hashes (sent on the wire as `contentHash`) against their
|
|
18
|
+
// stored YJS value to decide whether to apply the update — so once we've seen a given hash
|
|
19
|
+
// here, we can safely skip broadcasting it again.
|
|
20
|
+
const lastBroadcastComponentHashes = new Map();
|
|
21
|
+
const lastBroadcastSharedHashes = new Map();
|
|
22
|
+
let lastBroadcastGlobalStyleHash;
|
|
15
23
|
// Cached types list received from the editor via sync-types
|
|
16
24
|
let cachedEditorTypes = null;
|
|
17
25
|
// Cached custom type definitions received from the editor via sync-types (full IType objects)
|
|
18
26
|
let cachedCustomTypes = null;
|
|
27
|
+
// Cached theme global variables received from the editor via sync-types.
|
|
28
|
+
// Drives the ThemeSettingName union in src/global-types.ts.
|
|
29
|
+
let cachedThemeSettings = null;
|
|
19
30
|
const LIBRARY_TYPE_PREFIX = "@ikas/";
|
|
20
31
|
/**
|
|
21
32
|
* Match custom types for a component's props from the cached custom types.
|
|
@@ -128,12 +139,23 @@ async function compileAllComponentsForDev(config) {
|
|
|
128
139
|
if (chunkIds.length > 0) {
|
|
129
140
|
console.log(chalk.cyan(` Extracted ${chunkIds.length} shared chunk(s)`));
|
|
130
141
|
}
|
|
131
|
-
// Store global CSS (unscoped)
|
|
142
|
+
// Store global CSS (unscoped). Preserve `updatedAt` across rebuilds when the compiled
|
|
143
|
+
// global CSS is byte-identical so the editor only sees a fresh timestamp when the
|
|
144
|
+
// designer actually changed `global.css` — the publish UI watches this timestamp to
|
|
145
|
+
// decide whether globals need (re)publishing independently of any code component.
|
|
132
146
|
if (result.globalCss && config.projectId) {
|
|
133
|
-
|
|
147
|
+
const previousHash = computeGlobalStyleHash(compiledGlobalStyles);
|
|
148
|
+
const previousUpdatedAt = compiledGlobalStyles?.updatedAt;
|
|
149
|
+
const next = {
|
|
134
150
|
projectId: config.projectId,
|
|
135
151
|
compiledCss: result.globalCss,
|
|
136
152
|
};
|
|
153
|
+
const nextHash = computeGlobalStyleHash(next);
|
|
154
|
+
next.updatedAt =
|
|
155
|
+
nextHash === previousHash && previousUpdatedAt !== undefined
|
|
156
|
+
? previousUpdatedAt
|
|
157
|
+
: Date.now();
|
|
158
|
+
compiledGlobalStyles = next;
|
|
137
159
|
console.log(chalk.cyan(` Compiled global styles`));
|
|
138
160
|
}
|
|
139
161
|
else {
|
|
@@ -208,6 +230,7 @@ async function compileAllComponentsForDev(config) {
|
|
|
208
230
|
compiledComponents.set(component.id, data);
|
|
209
231
|
console.log(chalk.green(` Compiled: ${component.name}`));
|
|
210
232
|
}
|
|
233
|
+
populateContentHashes();
|
|
211
234
|
return true;
|
|
212
235
|
}
|
|
213
236
|
/**
|
|
@@ -267,6 +290,7 @@ function rebuildCompiledComponentFromConfig(config, componentId) {
|
|
|
267
290
|
: undefined,
|
|
268
291
|
};
|
|
269
292
|
compiledComponents.set(componentId, updated);
|
|
293
|
+
populateContentHashes();
|
|
270
294
|
return updated;
|
|
271
295
|
}
|
|
272
296
|
/**
|
|
@@ -275,6 +299,152 @@ function rebuildCompiledComponentFromConfig(config, componentId) {
|
|
|
275
299
|
function getAllSharedModules() {
|
|
276
300
|
return Array.from(compiledSharedModules.values());
|
|
277
301
|
}
|
|
302
|
+
function sha256Hex(input) {
|
|
303
|
+
return crypto.createHash("sha256").update(input).digest("hex");
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Compute `contentHash` for every entry in `compiledSharedModules` and `compiledComponents`,
|
|
307
|
+
* mutating each entry in place. A component's hash incorporates the hashes of its referenced
|
|
308
|
+
* shared modules (sorted), so any shared-util change cascades into consumers without
|
|
309
|
+
* requiring a separate "shared module changed" message — the consumer's own hash already
|
|
310
|
+
* differs. Global styles are tracked separately via `updatedAt` on the global style payload;
|
|
311
|
+
* they intentionally do NOT roll into component hashes (designers publish globals as a
|
|
312
|
+
* standalone unit).
|
|
313
|
+
*/
|
|
314
|
+
function populateContentHashes() {
|
|
315
|
+
for (const mod of compiledSharedModules.values()) {
|
|
316
|
+
mod.contentHash = sha256Hex([mod.id, mod.compiledServerJs, mod.compiledClientJs, mod.canvasClientJs, mod.compiledCss].join("\0"));
|
|
317
|
+
}
|
|
318
|
+
for (const comp of compiledComponents.values()) {
|
|
319
|
+
const referencedHashes = (comp.usedSharedModuleIds || [])
|
|
320
|
+
.slice()
|
|
321
|
+
.sort()
|
|
322
|
+
.map((id) => `${id}:${compiledSharedModules.get(id)?.contentHash || ""}`)
|
|
323
|
+
.join("|");
|
|
324
|
+
comp.contentHash = sha256Hex([
|
|
325
|
+
comp.id,
|
|
326
|
+
comp.name,
|
|
327
|
+
comp.projectId || "",
|
|
328
|
+
comp.type || "component",
|
|
329
|
+
comp.isHeader ? "1" : "0",
|
|
330
|
+
comp.isFooter ? "1" : "0",
|
|
331
|
+
comp.compiledServerJs,
|
|
332
|
+
comp.compiledClientJs,
|
|
333
|
+
comp.compiledCss,
|
|
334
|
+
comp.canvasClientJs,
|
|
335
|
+
JSON.stringify(comp.props),
|
|
336
|
+
JSON.stringify(comp.propGroups || null),
|
|
337
|
+
JSON.stringify(comp.configPropGroups || null),
|
|
338
|
+
JSON.stringify(comp.customTypes || null),
|
|
339
|
+
(comp.usedSharedModuleIds || []).slice().sort().join(","),
|
|
340
|
+
referencedHashes,
|
|
341
|
+
].join("\0"));
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
function computeGlobalStyleHash(g) {
|
|
345
|
+
if (!g)
|
|
346
|
+
return undefined;
|
|
347
|
+
return sha256Hex([g.projectId, g.compiledCss].join("\0"));
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Build a `component-update` payload's `sharedModules` array for one component: the chunks
|
|
351
|
+
* the editor needs to resolve this component's imports. We always include the full
|
|
352
|
+
* transitive set (cheap) so the editor never sees a missing chunk during a partial update.
|
|
353
|
+
*/
|
|
354
|
+
function sharedModulesForComponent(comp) {
|
|
355
|
+
if (!comp.usedSharedModuleIds || comp.usedSharedModuleIds.length === 0)
|
|
356
|
+
return undefined;
|
|
357
|
+
const out = [];
|
|
358
|
+
for (const id of comp.usedSharedModuleIds) {
|
|
359
|
+
const mod = compiledSharedModules.get(id);
|
|
360
|
+
if (mod)
|
|
361
|
+
out.push(mod);
|
|
362
|
+
}
|
|
363
|
+
return out.length > 0 ? out : undefined;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Diff current compile state against `lastBroadcast*` maps and decide what to send:
|
|
367
|
+
*
|
|
368
|
+
* - Nothing changed → no broadcast at all (this is the whole point — quiet rebuilds).
|
|
369
|
+
* - Exactly one component changed, no deletes, no global change → single
|
|
370
|
+
* `component-update` (cheap, no full-state replay on the editor).
|
|
371
|
+
* - Anything more (multi-component, deletes, global style change) → one bundled
|
|
372
|
+
* `initial-state`. We deliberately collapse multi-component changes into ONE message so
|
|
373
|
+
* the editor doesn't tick through N sequential `markUpdating` / refresh cycles. The
|
|
374
|
+
* editor's `autoSyncToTheme` uses `contentHash` to skip YJS writes for components that
|
|
375
|
+
* didn't actually change, so the full-state payload only mutates what really moved.
|
|
376
|
+
*
|
|
377
|
+
* Newly-connecting editors always receive a full `initial-state` via `onRequestState` in
|
|
378
|
+
* websocket-server.ts and are independent of this path.
|
|
379
|
+
*/
|
|
380
|
+
function broadcastCompileDelta(wsServer) {
|
|
381
|
+
const currentGlobalHash = computeGlobalStyleHash(compiledGlobalStyles);
|
|
382
|
+
const globalStylesChanged = currentGlobalHash !== lastBroadcastGlobalStyleHash;
|
|
383
|
+
const changedComponentIds = [];
|
|
384
|
+
for (const [id, comp] of compiledComponents) {
|
|
385
|
+
const prev = lastBroadcastComponentHashes.get(id);
|
|
386
|
+
if (prev !== comp.contentHash)
|
|
387
|
+
changedComponentIds.push(id);
|
|
388
|
+
}
|
|
389
|
+
const deletedComponentIds = [];
|
|
390
|
+
for (const id of lastBroadcastComponentHashes.keys()) {
|
|
391
|
+
if (!compiledComponents.has(id))
|
|
392
|
+
deletedComponentIds.push(id);
|
|
393
|
+
}
|
|
394
|
+
let changedSharedCount = 0;
|
|
395
|
+
for (const [id, mod] of compiledSharedModules) {
|
|
396
|
+
if (lastBroadcastSharedHashes.get(id) !== mod.contentHash)
|
|
397
|
+
changedSharedCount++;
|
|
398
|
+
}
|
|
399
|
+
const result = {
|
|
400
|
+
changedComponents: changedComponentIds.length,
|
|
401
|
+
deletedComponents: deletedComponentIds.length,
|
|
402
|
+
changedSharedModules: changedSharedCount,
|
|
403
|
+
globalStylesChanged,
|
|
404
|
+
};
|
|
405
|
+
const nothingChanged = changedComponentIds.length === 0 &&
|
|
406
|
+
deletedComponentIds.length === 0 &&
|
|
407
|
+
!globalStylesChanged;
|
|
408
|
+
if (nothingChanged)
|
|
409
|
+
return result;
|
|
410
|
+
// Single-component edit fast path: avoid making the editor clear+refill its devComponents
|
|
411
|
+
// map and run autoSyncToTheme for every component. One targeted update is enough.
|
|
412
|
+
const canUseSingleUpdate = changedComponentIds.length === 1 &&
|
|
413
|
+
deletedComponentIds.length === 0 &&
|
|
414
|
+
!globalStylesChanged;
|
|
415
|
+
if (canUseSingleUpdate) {
|
|
416
|
+
const comp = compiledComponents.get(changedComponentIds[0]);
|
|
417
|
+
wsServer.broadcastComponentUpdate(comp, sharedModulesForComponent(comp));
|
|
418
|
+
lastBroadcastComponentHashes.set(comp.id, comp.contentHash);
|
|
419
|
+
}
|
|
420
|
+
else {
|
|
421
|
+
for (const id of deletedComponentIds) {
|
|
422
|
+
wsServer.broadcastComponentDeleted(id);
|
|
423
|
+
lastBroadcastComponentHashes.delete(id);
|
|
424
|
+
}
|
|
425
|
+
wsServer.broadcast({
|
|
426
|
+
type: "initial-state",
|
|
427
|
+
payload: {
|
|
428
|
+
components: getAllComponents(),
|
|
429
|
+
sharedModules: getAllSharedModules(),
|
|
430
|
+
globalStyles: compiledGlobalStyles,
|
|
431
|
+
timestamp: Date.now(),
|
|
432
|
+
},
|
|
433
|
+
});
|
|
434
|
+
lastBroadcastComponentHashes.clear();
|
|
435
|
+
for (const [id, comp] of compiledComponents) {
|
|
436
|
+
if (comp.contentHash)
|
|
437
|
+
lastBroadcastComponentHashes.set(id, comp.contentHash);
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
lastBroadcastSharedHashes.clear();
|
|
441
|
+
for (const [id, mod] of compiledSharedModules) {
|
|
442
|
+
if (mod.contentHash)
|
|
443
|
+
lastBroadcastSharedHashes.set(id, mod.contentHash);
|
|
444
|
+
}
|
|
445
|
+
lastBroadcastGlobalStyleHash = currentGlobalHash;
|
|
446
|
+
return result;
|
|
447
|
+
}
|
|
278
448
|
/**
|
|
279
449
|
* Read and return the current config from disk
|
|
280
450
|
*/
|
|
@@ -294,7 +464,7 @@ function writeConfig(configPath, config) {
|
|
|
294
464
|
function writeGlobalTypesFile(config) {
|
|
295
465
|
const globalTypesPath = path.resolve(process.cwd(), "src/global-types.ts");
|
|
296
466
|
const usedEnumIds = collectUsedEnumIds(config.components);
|
|
297
|
-
const content = generateGlobalTypesFile(cachedEditorTypes, cachedCustomTypes, usedEnumIds);
|
|
467
|
+
const content = generateGlobalTypesFile(cachedEditorTypes, cachedCustomTypes, usedEnumIds, cachedThemeSettings);
|
|
298
468
|
// Avoid unnecessary writes (prevents file watcher loops)
|
|
299
469
|
if (fs.existsSync(globalTypesPath)) {
|
|
300
470
|
const existing = fs.readFileSync(globalTypesPath, "utf-8");
|
|
@@ -323,7 +493,10 @@ function createEditorHandlers(configPath, getConfig, setConfig, wsServer) {
|
|
|
323
493
|
const broadcastConfigChange = (componentId) => {
|
|
324
494
|
const updated = rebuildCompiledComponentFromConfig(getConfig(), componentId);
|
|
325
495
|
if (updated) {
|
|
326
|
-
wsServer.broadcastComponentUpdate(updated);
|
|
496
|
+
wsServer.broadcastComponentUpdate(updated, sharedModulesForComponent(updated));
|
|
497
|
+
if (updated.contentHash) {
|
|
498
|
+
lastBroadcastComponentHashes.set(updated.id, updated.contentHash);
|
|
499
|
+
}
|
|
327
500
|
}
|
|
328
501
|
};
|
|
329
502
|
return {
|
|
@@ -701,8 +874,10 @@ function createEditorHandlers(configPath, getConfig, setConfig, wsServer) {
|
|
|
701
874
|
regenerateAllComponentTypes(config);
|
|
702
875
|
console.log(chalk.green(` Deleted enum: ${removed.name} (${enumId})`));
|
|
703
876
|
},
|
|
704
|
-
onSyncTypes: (types, customTypes) => {
|
|
877
|
+
onSyncTypes: (types, customTypes, themeSettings) => {
|
|
705
878
|
cachedEditorTypes = types;
|
|
879
|
+
if (themeSettings)
|
|
880
|
+
cachedThemeSettings = themeSettings;
|
|
706
881
|
// Merge incoming custom types with existing ones instead of replacing.
|
|
707
882
|
// Custom types belong to the code component project and should not be
|
|
708
883
|
// lost when a different editor project connects.
|
|
@@ -808,6 +983,18 @@ async function startDevServer(opts = {}) {
|
|
|
808
983
|
// Initial compilation of all components (multi-entry with code splitting)
|
|
809
984
|
console.log(chalk.cyan(" Compiling components..."));
|
|
810
985
|
await compileAllComponentsForDev(config);
|
|
986
|
+
// Seed the broadcast-hash maps so the first delta-broadcast after startup doesn't replay
|
|
987
|
+
// the initial state — newly-connecting editors get a full `initial-state` directly via
|
|
988
|
+
// `onRequestState`, independent of the delta path.
|
|
989
|
+
for (const [id, comp] of compiledComponents) {
|
|
990
|
+
if (comp.contentHash)
|
|
991
|
+
lastBroadcastComponentHashes.set(id, comp.contentHash);
|
|
992
|
+
}
|
|
993
|
+
for (const [id, mod] of compiledSharedModules) {
|
|
994
|
+
if (mod.contentHash)
|
|
995
|
+
lastBroadcastSharedHashes.set(id, mod.contentHash);
|
|
996
|
+
}
|
|
997
|
+
lastBroadcastGlobalStyleHash = computeGlobalStyleHash(compiledGlobalStyles);
|
|
811
998
|
console.log("");
|
|
812
999
|
// Start WebSocket server
|
|
813
1000
|
const wsServer = new DevServerWebSocket(DEV_SERVER_PORT);
|
|
@@ -848,16 +1035,15 @@ async function startDevServer(opts = {}) {
|
|
|
848
1035
|
console.log(chalk.yellow(` Recompiling all (triggered by: ${triggeredBy})...`));
|
|
849
1036
|
const success = await compileAllComponentsForDev(config);
|
|
850
1037
|
if (success) {
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
});
|
|
1038
|
+
const delta = broadcastCompileDelta(wsServer);
|
|
1039
|
+
if (delta.changedComponents === 0 &&
|
|
1040
|
+
delta.deletedComponents === 0 &&
|
|
1041
|
+
!delta.globalStylesChanged) {
|
|
1042
|
+
console.log(chalk.gray(" No editor-visible changes (skipped broadcast)"));
|
|
1043
|
+
}
|
|
1044
|
+
else {
|
|
1045
|
+
console.log(chalk.cyan(` Broadcast delta: ${delta.changedComponents} changed, ${delta.deletedComponents} deleted, ${delta.changedSharedModules} shared chunks changed${delta.globalStylesChanged ? ", globals updated" : ""}`));
|
|
1046
|
+
}
|
|
861
1047
|
}
|
|
862
1048
|
else {
|
|
863
1049
|
// Broadcast error for the triggering component if identifiable
|
|
@@ -878,16 +1064,8 @@ async function startDevServer(opts = {}) {
|
|
|
878
1064
|
cachedCustomTypes = config.customTypes || [];
|
|
879
1065
|
writeGlobalTypesFile(config);
|
|
880
1066
|
await compileAllComponentsForDev(config);
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
type: "initial-state",
|
|
884
|
-
payload: {
|
|
885
|
-
components: getAllComponents(),
|
|
886
|
-
sharedModules: getAllSharedModules(),
|
|
887
|
-
globalStyles: compiledGlobalStyles,
|
|
888
|
-
timestamp: Date.now(),
|
|
889
|
-
},
|
|
890
|
-
});
|
|
1067
|
+
const delta = broadcastCompileDelta(wsServer);
|
|
1068
|
+
console.log(chalk.cyan(` Config reload delta: ${delta.changedComponents} changed, ${delta.deletedComponents} deleted, ${delta.changedSharedModules} shared chunks changed${delta.globalStylesChanged ? ", globals updated" : ""}`));
|
|
891
1069
|
}
|
|
892
1070
|
catch (e) {
|
|
893
1071
|
console.error(chalk.red(" Failed to reload config"));
|
|
@@ -914,6 +1092,23 @@ async function startDevServer(opts = {}) {
|
|
|
914
1092
|
const entryPath = path.resolve(process.cwd(), component.entry);
|
|
915
1093
|
if (!fs.existsSync(entryPath)) {
|
|
916
1094
|
compiledComponents.delete(component.id);
|
|
1095
|
+
// Sync ikas.config.json: remove the component entry and strip any orphaned
|
|
1096
|
+
// filteredComponentIds references in remaining components' props. Write config
|
|
1097
|
+
// before broadcasting so an editor requesting state sees the post-delete view.
|
|
1098
|
+
const idx = config.components.findIndex((c) => c.id === component.id);
|
|
1099
|
+
if (idx !== -1) {
|
|
1100
|
+
config.components.splice(idx, 1);
|
|
1101
|
+
for (const remaining of config.components) {
|
|
1102
|
+
for (const prop of remaining.props || []) {
|
|
1103
|
+
if (!prop.filteredComponentIds)
|
|
1104
|
+
continue;
|
|
1105
|
+
prop.filteredComponentIds = prop.filteredComponentIds.filter((id) => id !== component.id);
|
|
1106
|
+
if (prop.filteredComponentIds.length === 0)
|
|
1107
|
+
delete prop.filteredComponentIds;
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
writeConfig(configPath, config);
|
|
1111
|
+
}
|
|
917
1112
|
wsServer.broadcastComponentDeleted(component.id);
|
|
918
1113
|
console.log(chalk.red(` Component removed: ${component.name}`));
|
|
919
1114
|
}
|