@ikas/component-cli 2.5.1 → 2.6.1
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.d.ts.map +1 -1
- package/dist/commands/add.js +10 -1
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +224 -46
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/create-design-tokens.d.ts +17 -0
- package/dist/commands/create-design-tokens.d.ts.map +1 -1
- package/dist/commands/create-design-tokens.js +194 -24
- package/dist/commands/create-design-tokens.js.map +1 -1
- package/dist/commands/delete-theme-globals.d.ts.map +1 -1
- package/dist/commands/delete-theme-globals.js +3 -3
- package/dist/commands/delete-theme-globals.js.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +70 -9
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/publish.d.ts.map +1 -1
- package/dist/commands/publish.js +23 -2
- package/dist/commands/publish.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +27 -6
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +10 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/compile.d.ts.map +1 -1
- package/dist/utils/compile.js +21 -4
- package/dist/utils/compile.js.map +1 -1
- package/dist/utils/component-helpers.d.ts +56 -2
- package/dist/utils/component-helpers.d.ts.map +1 -1
- package/dist/utils/component-helpers.js +141 -4
- package/dist/utils/component-helpers.js.map +1 -1
- package/dist/utils/editor-action-client.d.ts +1 -1
- package/dist/utils/editor-action-client.d.ts.map +1 -1
- package/dist/utils/editor-action-client.js.map +1 -1
- package/dist/utils/forbid-external-packages.d.ts +16 -0
- package/dist/utils/forbid-external-packages.d.ts.map +1 -0
- package/dist/utils/forbid-external-packages.js +89 -0
- package/dist/utils/forbid-external-packages.js.map +1 -0
- package/dist/utils/websocket-server.d.ts +4 -2
- package/dist/utils/websocket-server.d.ts.map +1 -1
- package/dist/utils/websocket-server.js +1 -1
- package/dist/utils/websocket-server.js.map +1 -1
- package/package.json +1 -1
- package/templates/add/section.css +11 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuNpC,wBAAgB,gBAAgB,IAAI,OAAO,CAI1C"}
|
package/dist/commands/add.js
CHANGED
|
@@ -4,7 +4,7 @@ import ora from "ora";
|
|
|
4
4
|
import inquirer from "inquirer";
|
|
5
5
|
import * as fs from "fs";
|
|
6
6
|
import * as path from "path";
|
|
7
|
-
import { PROP_TYPES, toPascalCase, generateTypesFile, generateGlobalTypesFile, collectUsedEnumIds, generateComponentFile, generateStylesFile, generateProjectId, generateComponentId, } from "../utils/component-helpers.js";
|
|
7
|
+
import { PROP_TYPES, toPascalCase, generateTypesFile, generateGlobalTypesFile, collectUsedEnumIds, generateComponentFile, generateStylesFile, generateProjectId, isValidProjectId, generateComponentId, } from "../utils/component-helpers.js";
|
|
8
8
|
async function addComponent() {
|
|
9
9
|
const configPath = path.resolve(process.cwd(), "ikas.config.json");
|
|
10
10
|
// Check if we're in an ikas component project
|
|
@@ -100,6 +100,15 @@ async function addComponent() {
|
|
|
100
100
|
});
|
|
101
101
|
console.log(chalk.green(` Added prop "${propName}" (${propDetails.type})\n`));
|
|
102
102
|
}
|
|
103
|
+
// A malformed projectId (hand-edited config) breaks the editor's republish
|
|
104
|
+
// stability: published/local id prefixes stop matching and every publish
|
|
105
|
+
// INSERTs duplicate design elements. Fail fast, before any filesystem writes.
|
|
106
|
+
if (config.projectId && !isValidProjectId(config.projectId)) {
|
|
107
|
+
console.error(chalk.red(`Error: invalid projectId "${config.projectId}" in ikas.config.json`));
|
|
108
|
+
console.error(chalk.gray("projectId must be at least 6 alphanumeric characters (no '-' or '_'). " +
|
|
109
|
+
"Restore the original generated value — do not hand-edit it."));
|
|
110
|
+
process.exit(1);
|
|
111
|
+
}
|
|
103
112
|
// Create component
|
|
104
113
|
const spinner = ora("Creating component...").start();
|
|
105
114
|
try {
|
package/dist/commands/add.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"add.js","sourceRoot":"","sources":["../../src/commands/add.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/commands/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAu5DpC,wBAAgB,mBAAmB,IAAI,OAAO,CAuU7C"}
|
package/dist/commands/config.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Command } from "commander";
|
|
2
2
|
import * as fs from "fs";
|
|
3
3
|
import * as path from "path";
|
|
4
|
-
import { PROP_TYPES, toPascalCase, generateTypesFile, generateGlobalTypesFile, collectUsedEnumIds, generateComponentFile, generateStylesFile, generateProjectId, generateComponentId, generateUniqueId, updateBarrelExport, findPropGroup, collectPropGroupIds, movePropGroupInTree, validateFilteredComponentIds, } from "../utils/component-helpers.js";
|
|
4
|
+
import { PROP_TYPES, toPascalCase, generateTypesFile, generateGlobalTypesFile, collectUsedEnumIds, generateComponentFile, generateStylesFile, generateProjectId, isValidProjectId, generateComponentId, generateUniqueId, updateBarrelExport, findPropGroup, collectPropGroupIds, movePropGroupInTree, validateFilteredComponentIds, } from "../utils/component-helpers.js";
|
|
5
5
|
function loadConfig() {
|
|
6
6
|
const configPath = path.resolve(process.cwd(), "ikas.config.json");
|
|
7
7
|
if (!fs.existsSync(configPath)) {
|
|
@@ -31,7 +31,10 @@ function resolveComponent(config, ref) {
|
|
|
31
31
|
success: false,
|
|
32
32
|
error: "Component reference required: pass --id (preferred) or --name (exact PascalCase). " +
|
|
33
33
|
"Run `ikas-component config list-components` to see canonical ids.",
|
|
34
|
-
validComponents: config.components.map((c) => ({
|
|
34
|
+
validComponents: config.components.map((c) => ({
|
|
35
|
+
id: c.id,
|
|
36
|
+
name: c.name,
|
|
37
|
+
})),
|
|
35
38
|
}));
|
|
36
39
|
process.exit(1);
|
|
37
40
|
}
|
|
@@ -52,7 +55,10 @@ function resolveComponent(config, ref) {
|
|
|
52
55
|
? `Component not found: id="${id}".`
|
|
53
56
|
: `Component not found: name="${name}". Names are matched exactly (PascalCase, no normalization).`,
|
|
54
57
|
lookup: id ? { id } : { name },
|
|
55
|
-
validComponents: config.components.map((c) => ({
|
|
58
|
+
validComponents: config.components.map((c) => ({
|
|
59
|
+
id: c.id,
|
|
60
|
+
name: c.name,
|
|
61
|
+
})),
|
|
56
62
|
hint: "Use --id (preferred) or exact PascalCase --name. " +
|
|
57
63
|
"Run `ikas-component config list-components` to see canonical ids.",
|
|
58
64
|
}));
|
|
@@ -235,13 +241,23 @@ async function parsePropsFlag(propsJson, config, configPath) {
|
|
|
235
241
|
process.exit(1);
|
|
236
242
|
}
|
|
237
243
|
// Validate LINK / LIST_OF_LINK defaultValue shape (reject JSON strings and legacy { href })
|
|
238
|
-
if ((propType === "LINK" || propType === "LIST_OF_LINK") &&
|
|
244
|
+
if ((propType === "LINK" || propType === "LIST_OF_LINK") &&
|
|
245
|
+
r.defaultValue !== undefined) {
|
|
239
246
|
const linkError = validateLinkDefaultValue(propType, r.defaultValue, r.name);
|
|
240
247
|
if (linkError) {
|
|
241
248
|
console.log(JSON.stringify({ success: false, error: linkError }));
|
|
242
249
|
process.exit(1);
|
|
243
250
|
}
|
|
244
251
|
}
|
|
252
|
+
// Validate SVG / SVG_LIST defaultValue (reject malformed/oversized/unsafe SVG)
|
|
253
|
+
if ((propType === "SVG" || propType === "SVG_LIST") &&
|
|
254
|
+
r.defaultValue !== undefined) {
|
|
255
|
+
const svgError = validateSvgDefaultValue(propType, r.defaultValue, r.name);
|
|
256
|
+
if (svgError) {
|
|
257
|
+
console.log(JSON.stringify({ success: false, error: svgError }));
|
|
258
|
+
process.exit(1);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
245
261
|
// Auto-generate displayName if omitted
|
|
246
262
|
const displayName = typeof r.displayName === "string" && r.displayName
|
|
247
263
|
? r.displayName
|
|
@@ -266,7 +282,10 @@ async function parsePropsFlag(propsJson, config, configPath) {
|
|
|
266
282
|
process.exit(1);
|
|
267
283
|
}
|
|
268
284
|
// Validate enum type exists (checks config then live dev server)
|
|
269
|
-
if (config &&
|
|
285
|
+
if (config &&
|
|
286
|
+
configPath &&
|
|
287
|
+
typeof r.enumTypeId === "string" &&
|
|
288
|
+
!r.enumTypeId.startsWith("@ikas/")) {
|
|
270
289
|
const resolved = await resolveEnumType(r.enumTypeId, config, configPath);
|
|
271
290
|
if (!resolved) {
|
|
272
291
|
console.log(JSON.stringify({
|
|
@@ -285,9 +304,7 @@ async function parsePropsFlag(propsJson, config, configPath) {
|
|
|
285
304
|
...(typeof r.description === "string" && r.description
|
|
286
305
|
? { description: r.description }
|
|
287
306
|
: {}),
|
|
288
|
-
...(r.defaultValue !== undefined
|
|
289
|
-
? { defaultValue: r.defaultValue }
|
|
290
|
-
: {}),
|
|
307
|
+
...(r.defaultValue !== undefined ? { defaultValue: r.defaultValue } : {}),
|
|
291
308
|
...(typeof r.groupId === "string" && r.groupId
|
|
292
309
|
? { groupId: r.groupId }
|
|
293
310
|
: {}),
|
|
@@ -297,11 +314,19 @@ async function parsePropsFlag(propsJson, config, configPath) {
|
|
|
297
314
|
...(propType === "ENUM" && typeof r.enumTypeId === "string"
|
|
298
315
|
? { enumTypeId: r.enumTypeId }
|
|
299
316
|
: {}),
|
|
300
|
-
...((propType === "COMPONENT" || propType === "COMPONENT_LIST") &&
|
|
301
|
-
|
|
317
|
+
...((propType === "COMPONENT" || propType === "COMPONENT_LIST") &&
|
|
318
|
+
r.filteredComponentIds &&
|
|
319
|
+
Array.isArray(r.filteredComponentIds)
|
|
320
|
+
? {
|
|
321
|
+
filteredComponentIds: assertKnownComponentIds(r.filteredComponentIds, config),
|
|
322
|
+
}
|
|
302
323
|
: {}),
|
|
303
|
-
...((propType === "COMPONENT" || propType === "COMPONENT_LIST") &&
|
|
304
|
-
|
|
324
|
+
...((propType === "COMPONENT" || propType === "COMPONENT_LIST") &&
|
|
325
|
+
r.privateVarMap &&
|
|
326
|
+
typeof r.privateVarMap === "object"
|
|
327
|
+
? {
|
|
328
|
+
privateVarMap: r.privateVarMap,
|
|
329
|
+
}
|
|
305
330
|
: {}),
|
|
306
331
|
};
|
|
307
332
|
props.push(prop);
|
|
@@ -333,6 +358,18 @@ async function addComponent(name, options) {
|
|
|
333
358
|
if (!config.projectId) {
|
|
334
359
|
config.projectId = generateProjectId();
|
|
335
360
|
}
|
|
361
|
+
else if (!isValidProjectId(config.projectId)) {
|
|
362
|
+
// A malformed projectId (hand-edited config) breaks the editor's republish
|
|
363
|
+
// stability: published/local id prefixes stop matching and every publish
|
|
364
|
+
// INSERTs duplicate design elements. Fail fast instead of corrupting data.
|
|
365
|
+
console.log(JSON.stringify({
|
|
366
|
+
success: false,
|
|
367
|
+
error: `Invalid projectId "${config.projectId}" in ikas.config.json. ` +
|
|
368
|
+
"projectId must be at least 6 alphanumeric characters (no '-' or '_'). " +
|
|
369
|
+
"Restore the original generated value — do not hand-edit it.",
|
|
370
|
+
}));
|
|
371
|
+
process.exit(1);
|
|
372
|
+
}
|
|
336
373
|
// Parse --props (and validate filteredComponentIds) BEFORE any filesystem side-effects
|
|
337
374
|
// so a bad payload doesn't leave an empty component directory behind.
|
|
338
375
|
const props = options.props
|
|
@@ -438,7 +475,9 @@ async function addProp(ref, options) {
|
|
|
438
475
|
}
|
|
439
476
|
// Validate that enumTypeId references an existing enum type
|
|
440
477
|
// (checks config.customTypes first, then falls back to the live dev server)
|
|
441
|
-
if (propType === "ENUM" &&
|
|
478
|
+
if (propType === "ENUM" &&
|
|
479
|
+
options.enumTypeId &&
|
|
480
|
+
!options.enumTypeId.startsWith("@ikas/")) {
|
|
442
481
|
const resolved = await resolveEnumType(options.enumTypeId, config, configPath);
|
|
443
482
|
if (!resolved) {
|
|
444
483
|
console.log(JSON.stringify({
|
|
@@ -468,43 +507,69 @@ async function addProp(ref, options) {
|
|
|
468
507
|
}
|
|
469
508
|
// Parse filteredComponentIds JSON for COMPONENT/COMPONENT_LIST
|
|
470
509
|
let parsedFilteredIds;
|
|
471
|
-
if (options.filteredComponentIds &&
|
|
510
|
+
if (options.filteredComponentIds &&
|
|
511
|
+
(propType === "COMPONENT" || propType === "COMPONENT_LIST")) {
|
|
472
512
|
try {
|
|
473
513
|
parsedFilteredIds = JSON.parse(options.filteredComponentIds);
|
|
474
514
|
if (!Array.isArray(parsedFilteredIds)) {
|
|
475
|
-
console.log(JSON.stringify({
|
|
515
|
+
console.log(JSON.stringify({
|
|
516
|
+
success: false,
|
|
517
|
+
error: "--filteredComponentIds must be a JSON array of strings.",
|
|
518
|
+
}));
|
|
476
519
|
process.exit(1);
|
|
477
520
|
}
|
|
478
521
|
}
|
|
479
522
|
catch {
|
|
480
|
-
console.log(JSON.stringify({
|
|
523
|
+
console.log(JSON.stringify({
|
|
524
|
+
success: false,
|
|
525
|
+
error: `Invalid --filteredComponentIds JSON: ${options.filteredComponentIds}`,
|
|
526
|
+
}));
|
|
481
527
|
process.exit(1);
|
|
482
528
|
}
|
|
483
529
|
assertKnownComponentIds(parsedFilteredIds, config);
|
|
484
530
|
}
|
|
485
531
|
// Parse privateVarMap JSON for COMPONENT/COMPONENT_LIST
|
|
486
532
|
let parsedPrivateVarMap;
|
|
487
|
-
if (options.privateVarMap &&
|
|
533
|
+
if (options.privateVarMap &&
|
|
534
|
+
(propType === "COMPONENT" || propType === "COMPONENT_LIST")) {
|
|
488
535
|
try {
|
|
489
536
|
parsedPrivateVarMap = JSON.parse(options.privateVarMap);
|
|
490
|
-
if (typeof parsedPrivateVarMap !== "object" ||
|
|
491
|
-
|
|
537
|
+
if (typeof parsedPrivateVarMap !== "object" ||
|
|
538
|
+
Array.isArray(parsedPrivateVarMap)) {
|
|
539
|
+
console.log(JSON.stringify({
|
|
540
|
+
success: false,
|
|
541
|
+
error: "--privateVarMap must be a JSON object mapping keys to {id, typeId}.",
|
|
542
|
+
}));
|
|
492
543
|
process.exit(1);
|
|
493
544
|
}
|
|
494
545
|
}
|
|
495
546
|
catch {
|
|
496
|
-
console.log(JSON.stringify({
|
|
547
|
+
console.log(JSON.stringify({
|
|
548
|
+
success: false,
|
|
549
|
+
error: `Invalid --privateVarMap JSON: ${options.privateVarMap}`,
|
|
550
|
+
}));
|
|
497
551
|
process.exit(1);
|
|
498
552
|
}
|
|
499
553
|
}
|
|
500
|
-
const parsedDefaultValue = options.defaultValue !== undefined
|
|
501
|
-
|
|
554
|
+
const parsedDefaultValue = options.defaultValue !== undefined
|
|
555
|
+
? parseDefaultValue(options.defaultValue, propType)
|
|
556
|
+
: undefined;
|
|
557
|
+
if ((propType === "LINK" || propType === "LIST_OF_LINK") &&
|
|
558
|
+
parsedDefaultValue !== undefined) {
|
|
502
559
|
const linkError = validateLinkDefaultValue(propType, parsedDefaultValue, options.name);
|
|
503
560
|
if (linkError) {
|
|
504
561
|
console.log(JSON.stringify({ success: false, error: linkError }));
|
|
505
562
|
process.exit(1);
|
|
506
563
|
}
|
|
507
564
|
}
|
|
565
|
+
if ((propType === "SVG" || propType === "SVG_LIST") &&
|
|
566
|
+
parsedDefaultValue !== undefined) {
|
|
567
|
+
const svgError = validateSvgDefaultValue(propType, parsedDefaultValue, options.name);
|
|
568
|
+
if (svgError) {
|
|
569
|
+
console.log(JSON.stringify({ success: false, error: svgError }));
|
|
570
|
+
process.exit(1);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
508
573
|
const newProp = {
|
|
509
574
|
name: options.name,
|
|
510
575
|
displayName: options.displayName,
|
|
@@ -535,8 +600,12 @@ async function addProp(ref, options) {
|
|
|
535
600
|
required: newProp.required,
|
|
536
601
|
...(newProp.groupId ? { groupId: newProp.groupId } : {}),
|
|
537
602
|
...(newProp.enumTypeId ? { enumTypeId: newProp.enumTypeId } : {}),
|
|
538
|
-
...(newProp.filteredComponentIds
|
|
539
|
-
|
|
603
|
+
...(newProp.filteredComponentIds
|
|
604
|
+
? { filteredComponentIds: newProp.filteredComponentIds }
|
|
605
|
+
: {}),
|
|
606
|
+
...(newProp.privateVarMap
|
|
607
|
+
? { privateVarMap: newProp.privateVarMap }
|
|
608
|
+
: {}),
|
|
540
609
|
},
|
|
541
610
|
}));
|
|
542
611
|
}
|
|
@@ -557,6 +626,16 @@ function parseDefaultValue(value, propType) {
|
|
|
557
626
|
catch {
|
|
558
627
|
return value;
|
|
559
628
|
}
|
|
629
|
+
case "SVG_LIST":
|
|
630
|
+
// Same reasoning as LINK_LIST: SVG_LIST must be stored as an array of SVG strings.
|
|
631
|
+
// Parse it here; if it is not valid JSON, return the raw string so
|
|
632
|
+
// validateSvgDefaultValue can report a precise "must be an array" error.
|
|
633
|
+
try {
|
|
634
|
+
return JSON.parse(value);
|
|
635
|
+
}
|
|
636
|
+
catch {
|
|
637
|
+
return value;
|
|
638
|
+
}
|
|
560
639
|
default:
|
|
561
640
|
return value;
|
|
562
641
|
}
|
|
@@ -579,7 +658,8 @@ const validateSingleLink = (link, propName, path) => {
|
|
|
579
658
|
if ("href" in l && !("linkType" in l)) {
|
|
580
659
|
return `${where} uses a legacy { href } shape without "linkType". Use "linkType" + "externalLink"/"pageType" instead. ${LINK_SHAPE_HELP}`;
|
|
581
660
|
}
|
|
582
|
-
if (typeof l.linkType !== "string" ||
|
|
661
|
+
if (typeof l.linkType !== "string" ||
|
|
662
|
+
!VALID_LINK_TYPES.includes(l.linkType)) {
|
|
583
663
|
return `${where} must have a valid "linkType" (one of ${VALID_LINK_TYPES.join(", ")}). ${LINK_SHAPE_HELP}`;
|
|
584
664
|
}
|
|
585
665
|
if (l.subLinks !== undefined && !Array.isArray(l.subLinks)) {
|
|
@@ -604,12 +684,78 @@ function validateLinkDefaultValue(propType, value, propName) {
|
|
|
604
684
|
if (typeof value === "string") {
|
|
605
685
|
return `defaultValue for prop "${propName}" is a JSON string but must be an object { "links": [...] }. ${LINK_SHAPE_HELP}`;
|
|
606
686
|
}
|
|
607
|
-
if (!value ||
|
|
687
|
+
if (!value ||
|
|
688
|
+
typeof value !== "object" ||
|
|
689
|
+
Array.isArray(value) ||
|
|
690
|
+
!Array.isArray(value.links)) {
|
|
608
691
|
return `defaultValue for prop "${propName}" must be an object with a "links" array: { "links": [ <link>, ... ] }. ${LINK_SHAPE_HELP}`;
|
|
609
692
|
}
|
|
610
693
|
const links = value.links;
|
|
611
694
|
return firstError(links, (link, i) => validateSingleLink(link, propName, `.links[${i}]`));
|
|
612
695
|
}
|
|
696
|
+
const SVG_DEFAULT_HELP = "An SVG default must be a single well-formed <svg>…</svg> string ≤ 64 KB with no embedded base64 raster images. " +
|
|
697
|
+
"Tip: the editor uses each svg's `class` attribute as its display name — set class=\"my-icon\" to name it; " +
|
|
698
|
+
"SVG_LIST items with no class show as svg-1, svg-2, ….";
|
|
699
|
+
// Keep the cap and base64 pattern in sync with @ikas/editor-models validate-svg.ts (the
|
|
700
|
+
// authoritative validator). Duplicated here on purpose — see validateSvgShape below.
|
|
701
|
+
const SVG_MAX_SIZE_KB = 64;
|
|
702
|
+
const SVG_BASE64_RASTER_RE = /data:image\/[a-z0-9.+-]+;base64/i;
|
|
703
|
+
const SVG_SHAPE_RE = /^\s*(?:<\?xml[^>]*\?>\s*)?(?:<!DOCTYPE[^>]*>\s*)?<svg[\s>][\s\S]*<\/svg>\s*$/i;
|
|
704
|
+
// Count TOP-LEVEL <svg> roots without a DOM: scan svg open/close tags in order and track
|
|
705
|
+
// nesting depth. A root is any <svg> opened at depth 0. This matches the editor's DOM-based
|
|
706
|
+
// single-root check — it rejects siblings (`<svg/><svg/>`) while allowing a nested <svg>.
|
|
707
|
+
// Self-closing <svg .../> counts as a root but opens no nesting level.
|
|
708
|
+
function svgRootCount(input) {
|
|
709
|
+
const tags = input.match(/<svg\b[^>]*>|<\/svg\s*>/gi) || [];
|
|
710
|
+
return tags.reduce((acc, tag) => {
|
|
711
|
+
if (tag.startsWith("</"))
|
|
712
|
+
return { depth: Math.max(0, acc.depth - 1), roots: acc.roots };
|
|
713
|
+
const roots = acc.depth === 0 ? acc.roots + 1 : acc.roots;
|
|
714
|
+
const depth = /\/>\s*$/.test(tag) ? acc.depth : acc.depth + 1;
|
|
715
|
+
return { depth, roots };
|
|
716
|
+
}, { depth: 0, roots: 0 }).roots;
|
|
717
|
+
}
|
|
718
|
+
// Lightweight, dependency-free SVG structure check. This standalone CLI is publishable and
|
|
719
|
+
// must not depend on the private @ikas/editor-models package (nor pull a DOM/DOMPurify into a
|
|
720
|
+
// CLI), so it mirrors the RULES of the editor's validateSvg (size, base64, single <svg> root)
|
|
721
|
+
// for fast authoring feedback. The authoritative sanitize runs in the editor/upload path.
|
|
722
|
+
// Returns a rejection reason, or null if the shape is acceptable.
|
|
723
|
+
function validateSvgShape(input) {
|
|
724
|
+
if (typeof input !== "string" || input.trim() === "")
|
|
725
|
+
return "empty or not a string";
|
|
726
|
+
if (Buffer.byteLength(input, "utf8") > SVG_MAX_SIZE_KB * 1024)
|
|
727
|
+
return `exceeds ${SVG_MAX_SIZE_KB} KB`;
|
|
728
|
+
if (SVG_BASE64_RASTER_RE.test(input))
|
|
729
|
+
return "embedded base64 raster image not allowed";
|
|
730
|
+
if (!SVG_SHAPE_RE.test(input))
|
|
731
|
+
return "not a single-root <svg> document";
|
|
732
|
+
if (svgRootCount(input) !== 1)
|
|
733
|
+
return "must be exactly one <svg> root";
|
|
734
|
+
return null;
|
|
735
|
+
}
|
|
736
|
+
// Validates an SVG / SVG_LIST defaultValue. Returns an error message, or null if valid.
|
|
737
|
+
// Authoring an SVG default is a common mistake source for agents; rejecting here (with an
|
|
738
|
+
// instructive message) keeps malformed/oversized SVGs out of published components.
|
|
739
|
+
function validateSvgDefaultValue(propType, value, propName) {
|
|
740
|
+
if (value === undefined || value === null)
|
|
741
|
+
return null;
|
|
742
|
+
if (propType === "SVG") {
|
|
743
|
+
const reason = validateSvgShape(value);
|
|
744
|
+
return reason
|
|
745
|
+
? `defaultValue for prop "${propName}" is not a valid SVG: ${reason}. ${SVG_DEFAULT_HELP}`
|
|
746
|
+
: null;
|
|
747
|
+
}
|
|
748
|
+
// SVG_LIST
|
|
749
|
+
if (!Array.isArray(value)) {
|
|
750
|
+
return `defaultValue for prop "${propName}" must be an array of SVG strings: [ "<svg>…</svg>", ... ]. ${SVG_DEFAULT_HELP}`;
|
|
751
|
+
}
|
|
752
|
+
return firstError(value, (svg, i) => {
|
|
753
|
+
const reason = validateSvgShape(svg);
|
|
754
|
+
return reason
|
|
755
|
+
? `defaultValue[${i}] for prop "${propName}" is not a valid SVG: ${reason}. ${SVG_DEFAULT_HELP}`
|
|
756
|
+
: null;
|
|
757
|
+
});
|
|
758
|
+
}
|
|
613
759
|
function updateProp(ref, options) {
|
|
614
760
|
const { config, configPath } = loadConfig();
|
|
615
761
|
const component = resolveComponent(config, ref);
|
|
@@ -693,14 +839,18 @@ function updateProp(ref, options) {
|
|
|
693
839
|
}
|
|
694
840
|
}
|
|
695
841
|
if (options.filteredComponentIds !== undefined) {
|
|
696
|
-
if (options.filteredComponentIds === "" ||
|
|
842
|
+
if (options.filteredComponentIds === "" ||
|
|
843
|
+
options.filteredComponentIds === "none") {
|
|
697
844
|
delete prop.filteredComponentIds;
|
|
698
845
|
}
|
|
699
846
|
else {
|
|
700
847
|
try {
|
|
701
848
|
const parsed = JSON.parse(options.filteredComponentIds);
|
|
702
849
|
if (!Array.isArray(parsed)) {
|
|
703
|
-
console.log(JSON.stringify({
|
|
850
|
+
console.log(JSON.stringify({
|
|
851
|
+
success: false,
|
|
852
|
+
error: "--filteredComponentIds must be a JSON array of strings.",
|
|
853
|
+
}));
|
|
704
854
|
process.exit(1);
|
|
705
855
|
}
|
|
706
856
|
assertKnownComponentIds(parsed, config);
|
|
@@ -708,7 +858,10 @@ function updateProp(ref, options) {
|
|
|
708
858
|
}
|
|
709
859
|
catch (err) {
|
|
710
860
|
if (err instanceof SyntaxError) {
|
|
711
|
-
console.log(JSON.stringify({
|
|
861
|
+
console.log(JSON.stringify({
|
|
862
|
+
success: false,
|
|
863
|
+
error: `Invalid --filteredComponentIds JSON: ${options.filteredComponentIds}`,
|
|
864
|
+
}));
|
|
712
865
|
process.exit(1);
|
|
713
866
|
}
|
|
714
867
|
throw err;
|
|
@@ -723,13 +876,19 @@ function updateProp(ref, options) {
|
|
|
723
876
|
try {
|
|
724
877
|
const parsed = JSON.parse(options.privateVarMap);
|
|
725
878
|
if (typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
726
|
-
console.log(JSON.stringify({
|
|
879
|
+
console.log(JSON.stringify({
|
|
880
|
+
success: false,
|
|
881
|
+
error: "--privateVarMap must be a JSON object mapping keys to {id, typeId}.",
|
|
882
|
+
}));
|
|
727
883
|
process.exit(1);
|
|
728
884
|
}
|
|
729
885
|
prop.privateVarMap = parsed;
|
|
730
886
|
}
|
|
731
887
|
catch {
|
|
732
|
-
console.log(JSON.stringify({
|
|
888
|
+
console.log(JSON.stringify({
|
|
889
|
+
success: false,
|
|
890
|
+
error: `Invalid --privateVarMap JSON: ${options.privateVarMap}`,
|
|
891
|
+
}));
|
|
733
892
|
process.exit(1);
|
|
734
893
|
}
|
|
735
894
|
}
|
|
@@ -749,7 +908,9 @@ function updateProp(ref, options) {
|
|
|
749
908
|
...(prop.groupId ? { groupId: prop.groupId } : {}),
|
|
750
909
|
...(prop.typeId ? { typeId: prop.typeId } : {}),
|
|
751
910
|
...(prop.enumTypeId ? { enumTypeId: prop.enumTypeId } : {}),
|
|
752
|
-
...(prop.filteredComponentIds
|
|
911
|
+
...(prop.filteredComponentIds
|
|
912
|
+
? { filteredComponentIds: prop.filteredComponentIds }
|
|
913
|
+
: {}),
|
|
753
914
|
...(prop.privateVarMap ? { privateVarMap: prop.privateVarMap } : {}),
|
|
754
915
|
},
|
|
755
916
|
}));
|
|
@@ -813,7 +974,10 @@ function removeComponent(ref) {
|
|
|
813
974
|
removedComponentId: component.id,
|
|
814
975
|
removedComponentName: component.name,
|
|
815
976
|
removedDirectory: path.relative(process.cwd(), componentDir),
|
|
816
|
-
remainingComponents: config.components.map((c) => ({
|
|
977
|
+
remainingComponents: config.components.map((c) => ({
|
|
978
|
+
id: c.id,
|
|
979
|
+
name: c.name,
|
|
980
|
+
})),
|
|
817
981
|
}));
|
|
818
982
|
}
|
|
819
983
|
function addPropGroup(ref, options) {
|
|
@@ -920,10 +1084,10 @@ function removePropGroup(ref, options) {
|
|
|
920
1084
|
process.exit(1);
|
|
921
1085
|
}
|
|
922
1086
|
if (found.parent) {
|
|
923
|
-
found.parent.children = found.parent.children.filter(c => c.id !== options.id);
|
|
1087
|
+
found.parent.children = found.parent.children.filter((c) => c.id !== options.id);
|
|
924
1088
|
}
|
|
925
1089
|
else {
|
|
926
|
-
component.propGroups = component.propGroups.filter(g => g.id !== options.id);
|
|
1090
|
+
component.propGroups = component.propGroups.filter((g) => g.id !== options.id);
|
|
927
1091
|
}
|
|
928
1092
|
// Clear groupId from props referencing the deleted group
|
|
929
1093
|
for (const prop of component.props) {
|
|
@@ -936,7 +1100,7 @@ function removePropGroup(ref, options) {
|
|
|
936
1100
|
success: true,
|
|
937
1101
|
componentName: component.name,
|
|
938
1102
|
removedPropGroup: options.id,
|
|
939
|
-
remainingPropGroups: component.propGroups.map(g => g.id),
|
|
1103
|
+
remainingPropGroups: component.propGroups.map((g) => g.id),
|
|
940
1104
|
}));
|
|
941
1105
|
}
|
|
942
1106
|
function movePropGroup(ref, options) {
|
|
@@ -953,7 +1117,10 @@ function movePropGroup(ref, options) {
|
|
|
953
1117
|
component.propGroups = movePropGroupInTree(component.propGroups, options.id, options.parent || null, options.index);
|
|
954
1118
|
}
|
|
955
1119
|
catch (e) {
|
|
956
|
-
console.log(JSON.stringify({
|
|
1120
|
+
console.log(JSON.stringify({
|
|
1121
|
+
success: false,
|
|
1122
|
+
error: e.message || "Failed to move prop group",
|
|
1123
|
+
}));
|
|
957
1124
|
process.exit(1);
|
|
958
1125
|
}
|
|
959
1126
|
saveConfig(configPath, config);
|
|
@@ -1009,7 +1176,9 @@ function listComponents() {
|
|
|
1009
1176
|
required: p.required,
|
|
1010
1177
|
...(p.groupId ? { groupId: p.groupId } : {}),
|
|
1011
1178
|
})),
|
|
1012
|
-
...(c.propGroups && c.propGroups.length > 0
|
|
1179
|
+
...(c.propGroups && c.propGroups.length > 0
|
|
1180
|
+
? { propGroups: c.propGroups }
|
|
1181
|
+
: {}),
|
|
1013
1182
|
}));
|
|
1014
1183
|
console.log(JSON.stringify({
|
|
1015
1184
|
success: true,
|
|
@@ -1023,7 +1192,9 @@ function listComponents() {
|
|
|
1023
1192
|
async function addEnum(options) {
|
|
1024
1193
|
const { config, configPath } = loadConfig();
|
|
1025
1194
|
// Validate name
|
|
1026
|
-
if (!options.name ||
|
|
1195
|
+
if (!options.name ||
|
|
1196
|
+
typeof options.name !== "string" ||
|
|
1197
|
+
!options.name.trim()) {
|
|
1027
1198
|
console.log(JSON.stringify({ success: false, error: "Enum name is required." }));
|
|
1028
1199
|
process.exit(1);
|
|
1029
1200
|
}
|
|
@@ -1137,7 +1308,7 @@ function updateEnum(options) {
|
|
|
1137
1308
|
Object.keys(enumOptions).length === 0) {
|
|
1138
1309
|
console.log(JSON.stringify({
|
|
1139
1310
|
success: false,
|
|
1140
|
-
error:
|
|
1311
|
+
error: "Options must be a non-empty JSON object.",
|
|
1141
1312
|
}));
|
|
1142
1313
|
process.exit(1);
|
|
1143
1314
|
}
|
|
@@ -1210,8 +1381,7 @@ function listEnums() {
|
|
|
1210
1381
|
}
|
|
1211
1382
|
// --- Command registration ---
|
|
1212
1383
|
export function createConfigCommand() {
|
|
1213
|
-
const config = new Command("config")
|
|
1214
|
-
.description("Non-interactive commands for managing ikas.config.json (designed for AI agents and scripting)");
|
|
1384
|
+
const config = new Command("config").description("Non-interactive commands for managing ikas.config.json (designed for AI agents and scripting)");
|
|
1215
1385
|
config
|
|
1216
1386
|
.command("add-component")
|
|
1217
1387
|
.description("Add a new component to the project")
|
|
@@ -1220,7 +1390,7 @@ export function createConfigCommand() {
|
|
|
1220
1390
|
.option("--isHeader", "Mark this section as the store header (only for type: section)")
|
|
1221
1391
|
.option("--isFooter", "Mark this section as the store footer (only for type: section)")
|
|
1222
1392
|
.option("--props <json>", "JSON array of props. Required per entry: name, type. Optional: displayName (auto from name), required, description, defaultValue, groupId, typeId (TYPE props), enumTypeId (ENUM props), filteredComponentIds, privateVarMap. " +
|
|
1223
|
-
|
|
1393
|
+
'Example: \'[{"name":"title","type":"TEXT","required":true,"defaultValue":"Hello","groupId":"basic"}]\'')
|
|
1224
1394
|
.action((options) => {
|
|
1225
1395
|
addComponent(options.name, options);
|
|
1226
1396
|
});
|
|
@@ -1239,7 +1409,7 @@ export function createConfigCommand() {
|
|
|
1239
1409
|
.option("--typeId <typeId>", "Type ID for TYPE props (required when type is TYPE)")
|
|
1240
1410
|
.option("--enumTypeId <enumTypeId>", "Enum type ID for ENUM props (required when type is ENUM)")
|
|
1241
1411
|
.option("--filteredComponentIds <json>", "JSON array of component IDs to restrict selection (for COMPONENT/COMPONENT_LIST)")
|
|
1242
|
-
.option("--privateVarMap <json>",
|
|
1412
|
+
.option("--privateVarMap <json>", "JSON object mapping variable keys to {id, typeId} (for COMPONENT/COMPONENT_LIST)")
|
|
1243
1413
|
.action((options) => {
|
|
1244
1414
|
addProp({ id: options.componentId, name: options.component }, options);
|
|
1245
1415
|
});
|
|
@@ -1330,7 +1500,7 @@ export function createConfigCommand() {
|
|
|
1330
1500
|
.option("--component <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1331
1501
|
.requiredOption("--id <id>", "Group ID to move")
|
|
1332
1502
|
.option("--parent <parentId>", "Target parent group ID (omit to move to root)")
|
|
1333
|
-
.option("--index <index>", "Zero-based insertion index within the target parent (appends when omitted)", v => parseInt(v, 10))
|
|
1503
|
+
.option("--index <index>", "Zero-based insertion index within the target parent (appends when omitted)", (v) => parseInt(v, 10))
|
|
1334
1504
|
.action((options) => {
|
|
1335
1505
|
movePropGroup({ id: options.componentId, name: options.component }, options);
|
|
1336
1506
|
});
|
|
@@ -1426,7 +1596,15 @@ async function fetchLiveEditorEnumById(enumId) {
|
|
|
1426
1596
|
clearTimeout(timeout);
|
|
1427
1597
|
const types = message.payload?.types || [];
|
|
1428
1598
|
const match = types.find((t) => t.category === "enum" && t.id === enumId);
|
|
1429
|
-
finish(match
|
|
1599
|
+
finish(match
|
|
1600
|
+
? {
|
|
1601
|
+
id: match.id,
|
|
1602
|
+
name: match.name,
|
|
1603
|
+
...(match.enumOptions
|
|
1604
|
+
? { enumOptions: match.enumOptions }
|
|
1605
|
+
: {}),
|
|
1606
|
+
}
|
|
1607
|
+
: null);
|
|
1430
1608
|
}
|
|
1431
1609
|
}
|
|
1432
1610
|
catch {
|