@ikas/component-cli 2.1.0 → 2.2.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/config.d.ts.map +1 -1
- package/dist/commands/config.js +160 -119
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +230 -24
- package/dist/commands/dev.js.map +1 -1
- package/dist/utils/component-helpers.d.ts +13 -0
- package/dist/utils/component-helpers.d.ts.map +1 -1
- package/dist/utils/component-helpers.js +12 -0
- package/dist/utils/component-helpers.js.map +1 -1
- package/dist/utils/websocket-server.d.ts +19 -0
- package/dist/utils/websocket-server.d.ts.map +1 -1
- package/dist/utils/websocket-server.js.map +1 -1
- package/package.json +1 -1
|
@@ -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;AA49CpC,wBAAgB,mBAAmB,IAAI,OAAO,CAuM7C"}
|
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, } from "../utils/component-helpers.js";
|
|
4
|
+
import { PROP_TYPES, toPascalCase, generateTypesFile, generateGlobalTypesFile, collectUsedEnumIds, generateComponentFile, generateStylesFile, generateProjectId, 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)) {
|
|
@@ -17,13 +17,79 @@ function loadConfig() {
|
|
|
17
17
|
function saveConfig(configPath, config) {
|
|
18
18
|
fs.writeFileSync(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
19
19
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
/**
|
|
21
|
+
* Resolve a component by canonical id (preferred) or exact PascalCase name.
|
|
22
|
+
* No silent normalization: pass --id from `config list-components`, or pass --name
|
|
23
|
+
* exactly as stored in ikas.config.json. Exits with a structured JSON error
|
|
24
|
+
* (listing valid {id, name} pairs) if zero/both/missing.
|
|
25
|
+
*/
|
|
26
|
+
function resolveComponent(config, ref) {
|
|
27
|
+
const id = ref.id?.trim() || undefined;
|
|
28
|
+
const name = ref.name?.trim() || undefined;
|
|
29
|
+
if (!id && !name) {
|
|
30
|
+
console.log(JSON.stringify({
|
|
31
|
+
success: false,
|
|
32
|
+
error: "Component reference required: pass --id (preferred) or --name (exact PascalCase). " +
|
|
33
|
+
"Run `ikas-component config list-components` to see canonical ids.",
|
|
34
|
+
validComponents: config.components.map((c) => ({ id: c.id, name: c.name })),
|
|
35
|
+
}));
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
if (id && name) {
|
|
39
|
+
console.log(JSON.stringify({
|
|
40
|
+
success: false,
|
|
41
|
+
error: "Specify only one of --id or --name, not both.",
|
|
42
|
+
}));
|
|
43
|
+
process.exit(1);
|
|
44
|
+
}
|
|
45
|
+
const found = id
|
|
46
|
+
? config.components.find((c) => c.id === id)
|
|
47
|
+
: config.components.find((c) => c.name === name);
|
|
48
|
+
if (!found) {
|
|
49
|
+
console.log(JSON.stringify({
|
|
50
|
+
success: false,
|
|
51
|
+
error: id
|
|
52
|
+
? `Component not found: id="${id}".`
|
|
53
|
+
: `Component not found: name="${name}". Names are matched exactly (PascalCase, no normalization).`,
|
|
54
|
+
lookup: id ? { id } : { name },
|
|
55
|
+
validComponents: config.components.map((c) => ({ id: c.id, name: c.name })),
|
|
56
|
+
hint: "Use --id (preferred) or exact PascalCase --name. " +
|
|
57
|
+
"Run `ikas-component config list-components` to see canonical ids.",
|
|
58
|
+
}));
|
|
59
|
+
process.exit(1);
|
|
60
|
+
}
|
|
61
|
+
return found;
|
|
23
62
|
}
|
|
24
63
|
function getComponentNames(config) {
|
|
25
64
|
return config.components.map((c) => c.name);
|
|
26
65
|
}
|
|
66
|
+
/**
|
|
67
|
+
* Emit a structured JSON error for unknown filteredComponentIds entries and exit non-zero.
|
|
68
|
+
* Lists valid `{ id, name }` pairs so the LLM/caller can recover.
|
|
69
|
+
*/
|
|
70
|
+
function emitFilteredComponentIdsError(unknown, components) {
|
|
71
|
+
console.log(JSON.stringify({
|
|
72
|
+
success: false,
|
|
73
|
+
error: `Unknown filteredComponentIds: ${unknown.join(", ")}. ` +
|
|
74
|
+
`Component ids are opaque and cannot be derived from names — they must come from the ` +
|
|
75
|
+
`componentId returned by 'config add-component' or from 'config list'.`,
|
|
76
|
+
validComponents: components.map((c) => ({ id: c.id, name: c.name })),
|
|
77
|
+
}));
|
|
78
|
+
process.exit(1);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Validate `input` ids against `config.components` and return the same array on success.
|
|
82
|
+
* Exits with a JSON error if any id is unknown. Use at every write site that accepts
|
|
83
|
+
* filteredComponentIds from user/LLM input.
|
|
84
|
+
*/
|
|
85
|
+
function assertKnownComponentIds(input, config) {
|
|
86
|
+
const components = config?.components ?? [];
|
|
87
|
+
const { unknown } = validateFilteredComponentIds(input, components);
|
|
88
|
+
if (unknown.length > 0) {
|
|
89
|
+
emitFilteredComponentIdsError(unknown, components);
|
|
90
|
+
}
|
|
91
|
+
return input;
|
|
92
|
+
}
|
|
27
93
|
function regenerateTypes(component, componentType, config) {
|
|
28
94
|
const componentDir = path.resolve(process.cwd(), path.dirname(component.entry));
|
|
29
95
|
const typesPath = path.join(componentDir, "types.ts");
|
|
@@ -201,7 +267,7 @@ async function parsePropsFlag(propsJson, config, configPath) {
|
|
|
201
267
|
? { enumTypeId: r.enumTypeId }
|
|
202
268
|
: {}),
|
|
203
269
|
...((propType === "COMPONENT" || propType === "COMPONENT_LIST") && r.filteredComponentIds && Array.isArray(r.filteredComponentIds)
|
|
204
|
-
? { filteredComponentIds: r.filteredComponentIds }
|
|
270
|
+
? { filteredComponentIds: assertKnownComponentIds(r.filteredComponentIds, config) }
|
|
205
271
|
: {}),
|
|
206
272
|
...((propType === "COMPONENT" || propType === "COMPONENT_LIST") && r.privateVarMap && typeof r.privateVarMap === "object"
|
|
207
273
|
? { privateVarMap: r.privateVarMap }
|
|
@@ -236,14 +302,15 @@ async function addComponent(name, options) {
|
|
|
236
302
|
if (!config.projectId) {
|
|
237
303
|
config.projectId = generateProjectId();
|
|
238
304
|
}
|
|
305
|
+
// Parse --props (and validate filteredComponentIds) BEFORE any filesystem side-effects
|
|
306
|
+
// so a bad payload doesn't leave an empty component directory behind.
|
|
307
|
+
const props = options.props
|
|
308
|
+
? await parsePropsFlag(options.props, config, configPath)
|
|
309
|
+
: [];
|
|
239
310
|
const componentId = generateComponentId(config.projectId);
|
|
240
311
|
const componentDir = path.resolve(process.cwd(), `src/components/${pascalName}`);
|
|
241
312
|
// Create directory
|
|
242
313
|
fs.mkdirSync(componentDir, { recursive: true });
|
|
243
|
-
// Parse --props if provided, otherwise empty
|
|
244
|
-
const props = options.props
|
|
245
|
-
? await parsePropsFlag(options.props, config, configPath)
|
|
246
|
-
: [];
|
|
247
314
|
// Auto-create prop groups from groupId references in props
|
|
248
315
|
const referencedGroupIds = new Set();
|
|
249
316
|
for (const prop of props) {
|
|
@@ -294,16 +361,9 @@ async function addComponent(name, options) {
|
|
|
294
361
|
],
|
|
295
362
|
}));
|
|
296
363
|
}
|
|
297
|
-
async function addProp(
|
|
364
|
+
async function addProp(ref, options) {
|
|
298
365
|
const { config, configPath } = loadConfig();
|
|
299
|
-
const component =
|
|
300
|
-
if (!component) {
|
|
301
|
-
console.log(JSON.stringify({
|
|
302
|
-
success: false,
|
|
303
|
-
error: `Component "${componentName}" not found. Available: ${getComponentNames(config).join(", ")}`,
|
|
304
|
-
}));
|
|
305
|
-
process.exit(1);
|
|
306
|
-
}
|
|
366
|
+
const component = resolveComponent(config, ref);
|
|
307
367
|
// Validate prop type
|
|
308
368
|
const propType = options.type.toUpperCase();
|
|
309
369
|
if (!PROP_TYPES.includes(propType)) {
|
|
@@ -389,6 +449,7 @@ async function addProp(componentName, options) {
|
|
|
389
449
|
console.log(JSON.stringify({ success: false, error: `Invalid --filteredComponentIds JSON: ${options.filteredComponentIds}` }));
|
|
390
450
|
process.exit(1);
|
|
391
451
|
}
|
|
452
|
+
assertKnownComponentIds(parsedFilteredIds, config);
|
|
392
453
|
}
|
|
393
454
|
// Parse privateVarMap JSON for COMPONENT/COMPONENT_LIST
|
|
394
455
|
let parsedPrivateVarMap;
|
|
@@ -450,16 +511,9 @@ function parseDefaultValue(value, propType) {
|
|
|
450
511
|
return value;
|
|
451
512
|
}
|
|
452
513
|
}
|
|
453
|
-
function updateProp(
|
|
514
|
+
function updateProp(ref, options) {
|
|
454
515
|
const { config, configPath } = loadConfig();
|
|
455
|
-
const component =
|
|
456
|
-
if (!component) {
|
|
457
|
-
console.log(JSON.stringify({
|
|
458
|
-
success: false,
|
|
459
|
-
error: `Component "${componentName}" not found. Available: ${getComponentNames(config).join(", ")}`,
|
|
460
|
-
}));
|
|
461
|
-
process.exit(1);
|
|
462
|
-
}
|
|
516
|
+
const component = resolveComponent(config, ref);
|
|
463
517
|
const propIndex = component.props.findIndex((p) => p.name === options.prop);
|
|
464
518
|
if (propIndex === -1) {
|
|
465
519
|
console.log(JSON.stringify({
|
|
@@ -542,11 +596,15 @@ function updateProp(componentName, options) {
|
|
|
542
596
|
console.log(JSON.stringify({ success: false, error: "--filteredComponentIds must be a JSON array of strings." }));
|
|
543
597
|
process.exit(1);
|
|
544
598
|
}
|
|
599
|
+
assertKnownComponentIds(parsed, config);
|
|
545
600
|
prop.filteredComponentIds = parsed;
|
|
546
601
|
}
|
|
547
|
-
catch {
|
|
548
|
-
|
|
549
|
-
|
|
602
|
+
catch (err) {
|
|
603
|
+
if (err instanceof SyntaxError) {
|
|
604
|
+
console.log(JSON.stringify({ success: false, error: `Invalid --filteredComponentIds JSON: ${options.filteredComponentIds}` }));
|
|
605
|
+
process.exit(1);
|
|
606
|
+
}
|
|
607
|
+
throw err;
|
|
550
608
|
}
|
|
551
609
|
}
|
|
552
610
|
}
|
|
@@ -589,16 +647,9 @@ function updateProp(componentName, options) {
|
|
|
589
647
|
},
|
|
590
648
|
}));
|
|
591
649
|
}
|
|
592
|
-
function removeProp(
|
|
650
|
+
function removeProp(ref, options) {
|
|
593
651
|
const { config, configPath } = loadConfig();
|
|
594
|
-
const component =
|
|
595
|
-
if (!component) {
|
|
596
|
-
console.log(JSON.stringify({
|
|
597
|
-
success: false,
|
|
598
|
-
error: `Component "${componentName}" not found. Available: ${getComponentNames(config).join(", ")}`,
|
|
599
|
-
}));
|
|
600
|
-
process.exit(1);
|
|
601
|
-
}
|
|
652
|
+
const component = resolveComponent(config, ref);
|
|
602
653
|
const propIndex = component.props.findIndex((p) => p.name === options.prop);
|
|
603
654
|
if (propIndex === -1) {
|
|
604
655
|
console.log(JSON.stringify({
|
|
@@ -619,21 +670,30 @@ function removeProp(componentName, options) {
|
|
|
619
670
|
remainingProps: component.props.map((p) => p.name),
|
|
620
671
|
}));
|
|
621
672
|
}
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
673
|
+
/**
|
|
674
|
+
* Strip a deleted component's ID from every other component's COMPONENT/COMPONENT_LIST
|
|
675
|
+
* `filteredComponentIds` allowlist. Empty arrays are deleted to keep the field optional
|
|
676
|
+
* (mirrors the editor-side convention).
|
|
677
|
+
*/
|
|
678
|
+
function pruneFilteredComponentIdRefs(config, removedId) {
|
|
679
|
+
for (const component of config.components) {
|
|
680
|
+
for (const prop of component.props || []) {
|
|
681
|
+
if (!prop.filteredComponentIds)
|
|
682
|
+
continue;
|
|
683
|
+
prop.filteredComponentIds = prop.filteredComponentIds.filter((id) => id !== removedId);
|
|
684
|
+
if (prop.filteredComponentIds.length === 0)
|
|
685
|
+
delete prop.filteredComponentIds;
|
|
686
|
+
}
|
|
632
687
|
}
|
|
633
|
-
|
|
688
|
+
}
|
|
689
|
+
function removeComponent(ref) {
|
|
690
|
+
const { config, configPath } = loadConfig();
|
|
691
|
+
const component = resolveComponent(config, ref);
|
|
692
|
+
const componentIndex = config.components.indexOf(component);
|
|
634
693
|
const componentDir = path.resolve(process.cwd(), path.dirname(component.entry));
|
|
635
|
-
// Remove component from config
|
|
694
|
+
// Remove component from config and strip orphaned references from remaining components
|
|
636
695
|
config.components.splice(componentIndex, 1);
|
|
696
|
+
pruneFilteredComponentIdRefs(config, component.id);
|
|
637
697
|
saveConfig(configPath, config);
|
|
638
698
|
// Remove component directory
|
|
639
699
|
if (fs.existsSync(componentDir)) {
|
|
@@ -643,21 +703,15 @@ function removeComponent(options) {
|
|
|
643
703
|
updateBarrelExport(process.cwd(), getComponentNames(config));
|
|
644
704
|
console.log(JSON.stringify({
|
|
645
705
|
success: true,
|
|
646
|
-
|
|
706
|
+
removedComponentId: component.id,
|
|
707
|
+
removedComponentName: component.name,
|
|
647
708
|
removedDirectory: path.relative(process.cwd(), componentDir),
|
|
648
|
-
remainingComponents:
|
|
709
|
+
remainingComponents: config.components.map((c) => ({ id: c.id, name: c.name })),
|
|
649
710
|
}));
|
|
650
711
|
}
|
|
651
|
-
function addPropGroup(
|
|
712
|
+
function addPropGroup(ref, options) {
|
|
652
713
|
const { config, configPath } = loadConfig();
|
|
653
|
-
const component =
|
|
654
|
-
if (!component) {
|
|
655
|
-
console.log(JSON.stringify({
|
|
656
|
-
success: false,
|
|
657
|
-
error: `Component "${componentName}" not found. Available: ${getComponentNames(config).join(", ")}`,
|
|
658
|
-
}));
|
|
659
|
-
process.exit(1);
|
|
660
|
-
}
|
|
714
|
+
const component = resolveComponent(config, ref);
|
|
661
715
|
if (!component.propGroups)
|
|
662
716
|
component.propGroups = [];
|
|
663
717
|
// Check uniqueness
|
|
@@ -708,16 +762,9 @@ function addPropGroup(componentName, options) {
|
|
|
708
762
|
},
|
|
709
763
|
}));
|
|
710
764
|
}
|
|
711
|
-
function updatePropGroup(
|
|
765
|
+
function updatePropGroup(ref, options) {
|
|
712
766
|
const { config, configPath } = loadConfig();
|
|
713
|
-
const component =
|
|
714
|
-
if (!component) {
|
|
715
|
-
console.log(JSON.stringify({
|
|
716
|
-
success: false,
|
|
717
|
-
error: `Component "${componentName}" not found. Available: ${getComponentNames(config).join(", ")}`,
|
|
718
|
-
}));
|
|
719
|
-
process.exit(1);
|
|
720
|
-
}
|
|
767
|
+
const component = resolveComponent(config, ref);
|
|
721
768
|
if (!component.propGroups || component.propGroups.length === 0) {
|
|
722
769
|
console.log(JSON.stringify({
|
|
723
770
|
success: false,
|
|
@@ -747,16 +794,9 @@ function updatePropGroup(componentName, options) {
|
|
|
747
794
|
},
|
|
748
795
|
}));
|
|
749
796
|
}
|
|
750
|
-
function removePropGroup(
|
|
797
|
+
function removePropGroup(ref, options) {
|
|
751
798
|
const { config, configPath } = loadConfig();
|
|
752
|
-
const component =
|
|
753
|
-
if (!component) {
|
|
754
|
-
console.log(JSON.stringify({
|
|
755
|
-
success: false,
|
|
756
|
-
error: `Component "${componentName}" not found. Available: ${getComponentNames(config).join(", ")}`,
|
|
757
|
-
}));
|
|
758
|
-
process.exit(1);
|
|
759
|
-
}
|
|
799
|
+
const component = resolveComponent(config, ref);
|
|
760
800
|
if (!component.propGroups || component.propGroups.length === 0) {
|
|
761
801
|
console.log(JSON.stringify({
|
|
762
802
|
success: false,
|
|
@@ -792,16 +832,9 @@ function removePropGroup(componentName, options) {
|
|
|
792
832
|
remainingPropGroups: component.propGroups.map(g => g.id),
|
|
793
833
|
}));
|
|
794
834
|
}
|
|
795
|
-
function movePropGroup(
|
|
835
|
+
function movePropGroup(ref, options) {
|
|
796
836
|
const { config, configPath } = loadConfig();
|
|
797
|
-
const component =
|
|
798
|
-
if (!component) {
|
|
799
|
-
console.log(JSON.stringify({
|
|
800
|
-
success: false,
|
|
801
|
-
error: `Component "${componentName}" not found. Available: ${getComponentNames(config).join(", ")}`,
|
|
802
|
-
}));
|
|
803
|
-
process.exit(1);
|
|
804
|
-
}
|
|
837
|
+
const component = resolveComponent(config, ref);
|
|
805
838
|
if (!component.propGroups || component.propGroups.length === 0) {
|
|
806
839
|
console.log(JSON.stringify({
|
|
807
840
|
success: false,
|
|
@@ -824,16 +857,9 @@ function movePropGroup(componentName, options) {
|
|
|
824
857
|
parentGroupId: options.parent || null,
|
|
825
858
|
}));
|
|
826
859
|
}
|
|
827
|
-
function updateComponent(options) {
|
|
860
|
+
function updateComponent(ref, options) {
|
|
828
861
|
const { config, configPath } = loadConfig();
|
|
829
|
-
const component =
|
|
830
|
-
if (!component) {
|
|
831
|
-
console.log(JSON.stringify({
|
|
832
|
-
success: false,
|
|
833
|
-
error: `Component "${options.name}" not found. Available: ${getComponentNames(config).join(", ")}`,
|
|
834
|
-
}));
|
|
835
|
-
process.exit(1);
|
|
836
|
-
}
|
|
862
|
+
const component = resolveComponent(config, ref);
|
|
837
863
|
if (options.isHeader !== undefined) {
|
|
838
864
|
if (options.isHeader) {
|
|
839
865
|
component.isHeader = true;
|
|
@@ -1093,7 +1119,8 @@ export function createConfigCommand() {
|
|
|
1093
1119
|
config
|
|
1094
1120
|
.command("add-prop")
|
|
1095
1121
|
.description("Add a prop to a component")
|
|
1096
|
-
.
|
|
1122
|
+
.option("--component-id <id>", "Component id (preferred; from `config list-components`)")
|
|
1123
|
+
.option("--component <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1097
1124
|
.requiredOption("--name <name>", "Prop name (camelCase)")
|
|
1098
1125
|
.requiredOption("--displayName <displayName>", "Display name in editor")
|
|
1099
1126
|
.requiredOption("--type <type>", `Prop type: ${PROP_TYPES.join(", ")}`)
|
|
@@ -1106,12 +1133,13 @@ export function createConfigCommand() {
|
|
|
1106
1133
|
.option("--filteredComponentIds <json>", "JSON array of component IDs to restrict selection (for COMPONENT/COMPONENT_LIST)")
|
|
1107
1134
|
.option("--privateVarMap <json>", 'JSON object mapping variable keys to {id, typeId} (for COMPONENT/COMPONENT_LIST)')
|
|
1108
1135
|
.action((options) => {
|
|
1109
|
-
addProp(options.component, options);
|
|
1136
|
+
addProp({ id: options.componentId, name: options.component }, options);
|
|
1110
1137
|
});
|
|
1111
1138
|
config
|
|
1112
1139
|
.command("update-prop")
|
|
1113
1140
|
.description("Update a prop on a component")
|
|
1114
|
-
.
|
|
1141
|
+
.option("--component-id <id>", "Component id (preferred; from `config list-components`)")
|
|
1142
|
+
.option("--component <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1115
1143
|
.requiredOption("--prop <propName>", "Prop name to update")
|
|
1116
1144
|
.option("--displayName <displayName>", "New display name")
|
|
1117
1145
|
.option("--type <type>", "New prop type")
|
|
@@ -1124,76 +1152,89 @@ export function createConfigCommand() {
|
|
|
1124
1152
|
.option("--filteredComponentIds <json>", "JSON array of component IDs (use 'none' to clear)")
|
|
1125
1153
|
.option("--privateVarMap <json>", "JSON object mapping variable keys to {id, typeId} (use 'none' to clear)")
|
|
1126
1154
|
.action((options) => {
|
|
1127
|
-
updateProp(options.component, options);
|
|
1155
|
+
updateProp({ id: options.componentId, name: options.component }, options);
|
|
1128
1156
|
});
|
|
1129
1157
|
config
|
|
1130
1158
|
.command("remove-prop")
|
|
1131
1159
|
.description("Remove a prop from a component")
|
|
1132
|
-
.
|
|
1160
|
+
.option("--component-id <id>", "Component id (preferred; from `config list-components`)")
|
|
1161
|
+
.option("--component <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1133
1162
|
.requiredOption("--prop <propName>", "Prop name to remove")
|
|
1134
1163
|
.action((options) => {
|
|
1135
|
-
removeProp(options.component, options);
|
|
1164
|
+
removeProp({ id: options.componentId, name: options.component }, options);
|
|
1136
1165
|
});
|
|
1137
1166
|
config
|
|
1138
1167
|
.command("update-component")
|
|
1139
|
-
.description("Update a component's metadata (isHeader, isFooter)")
|
|
1140
|
-
.
|
|
1168
|
+
.description("Update a component's metadata (isHeader, isFooter). Identify by --id (preferred) or exact --name.")
|
|
1169
|
+
.option("--id <id>", "Component id (preferred; from `config list-components`)")
|
|
1170
|
+
.option("--name <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1141
1171
|
.option("--isHeader", "Mark as store header")
|
|
1142
1172
|
.option("--no-isHeader", "Unmark as store header")
|
|
1143
1173
|
.option("--isFooter", "Mark as store footer")
|
|
1144
1174
|
.option("--no-isFooter", "Unmark as store footer")
|
|
1145
1175
|
.action((options) => {
|
|
1146
|
-
updateComponent(options);
|
|
1176
|
+
updateComponent({ id: options.id, name: options.name }, options);
|
|
1147
1177
|
});
|
|
1148
1178
|
config
|
|
1149
1179
|
.command("remove-component")
|
|
1150
|
-
.description("Remove a component from the project (deletes files)")
|
|
1151
|
-
.
|
|
1180
|
+
.description("Remove a component from the project (deletes files). Identify by --id (preferred) or exact --name.")
|
|
1181
|
+
.option("--id <id>", "Component id (preferred; from `config list-components`)")
|
|
1182
|
+
.option("--name <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1152
1183
|
.action((options) => {
|
|
1153
|
-
removeComponent(options);
|
|
1184
|
+
removeComponent({ id: options.id, name: options.name });
|
|
1154
1185
|
});
|
|
1155
1186
|
config
|
|
1156
1187
|
.command("add-prop-group")
|
|
1157
1188
|
.description("Add a prop group to a component")
|
|
1158
|
-
.
|
|
1189
|
+
.option("--component-id <componentId>", "Component id (preferred; from `config list-components`)")
|
|
1190
|
+
.option("--component <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1159
1191
|
.requiredOption("--id <id>", "Group ID (unique within component, kebab-case)")
|
|
1160
1192
|
.requiredOption("--name <name>", "Display name in editor")
|
|
1161
1193
|
.option("--description <description>", "Group description")
|
|
1162
1194
|
.option("--parent <parentId>", "Parent group ID (for nesting, max 1 level)")
|
|
1163
1195
|
.action((options) => {
|
|
1164
|
-
addPropGroup(options.component, options);
|
|
1196
|
+
addPropGroup({ id: options.componentId, name: options.component }, options);
|
|
1165
1197
|
});
|
|
1166
1198
|
config
|
|
1167
1199
|
.command("update-prop-group")
|
|
1168
1200
|
.description("Update a prop group on a component")
|
|
1169
|
-
.
|
|
1201
|
+
.option("--component-id <componentId>", "Component id (preferred; from `config list-components`)")
|
|
1202
|
+
.option("--component <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1170
1203
|
.requiredOption("--id <id>", "Group ID to update")
|
|
1171
1204
|
.option("--name <name>", "New display name")
|
|
1172
1205
|
.option("--description <description>", "New description")
|
|
1173
1206
|
.action((options) => {
|
|
1174
|
-
updatePropGroup(options.component, options);
|
|
1207
|
+
updatePropGroup({ id: options.componentId, name: options.component }, options);
|
|
1175
1208
|
});
|
|
1176
1209
|
config
|
|
1177
1210
|
.command("remove-prop-group")
|
|
1178
1211
|
.description("Remove a prop group from a component (props become ungrouped)")
|
|
1179
|
-
.
|
|
1212
|
+
.option("--component-id <componentId>", "Component id (preferred; from `config list-components`)")
|
|
1213
|
+
.option("--component <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1180
1214
|
.requiredOption("--id <id>", "Group ID to remove")
|
|
1181
1215
|
.action((options) => {
|
|
1182
|
-
removePropGroup(options.component, options);
|
|
1216
|
+
removePropGroup({ id: options.componentId, name: options.component }, options);
|
|
1183
1217
|
});
|
|
1184
1218
|
config
|
|
1185
1219
|
.command("move-prop-group")
|
|
1186
1220
|
.description("Move a prop group to a different parent or position (for drag-and-drop reordering)")
|
|
1187
|
-
.
|
|
1221
|
+
.option("--component-id <componentId>", "Component id (preferred; from `config list-components`)")
|
|
1222
|
+
.option("--component <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1188
1223
|
.requiredOption("--id <id>", "Group ID to move")
|
|
1189
1224
|
.option("--parent <parentId>", "Target parent group ID (omit to move to root)")
|
|
1190
1225
|
.option("--index <index>", "Zero-based insertion index within the target parent (appends when omitted)", v => parseInt(v, 10))
|
|
1191
1226
|
.action((options) => {
|
|
1192
|
-
movePropGroup(options.component, options);
|
|
1227
|
+
movePropGroup({ id: options.componentId, name: options.component }, options);
|
|
1228
|
+
});
|
|
1229
|
+
config
|
|
1230
|
+
.command("list-components")
|
|
1231
|
+
.description("List all components and their props (with canonical ids for use with --id flags)")
|
|
1232
|
+
.action(() => {
|
|
1233
|
+
listComponents();
|
|
1193
1234
|
});
|
|
1194
1235
|
config
|
|
1195
1236
|
.command("list")
|
|
1196
|
-
.description("
|
|
1237
|
+
.description("Alias for `list-components` (kept for backwards compatibility)")
|
|
1197
1238
|
.action(() => {
|
|
1198
1239
|
listComponents();
|
|
1199
1240
|
});
|