@ikas/component-cli 1.4.0-beta.7 → 1.4.0-beta.71
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 +212 -113
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/create-design-tokens.d.ts +11 -0
- package/dist/commands/create-design-tokens.d.ts.map +1 -0
- package/dist/commands/create-design-tokens.js +205 -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 +217 -31
- 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 +51 -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 +21 -3
- package/dist/utils/component-helpers.d.ts.map +1 -1
- package/dist/utils/component-helpers.js +111 -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/config.js
CHANGED
|
@@ -17,9 +17,48 @@ 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);
|
|
@@ -105,6 +144,19 @@ function camelCaseToDisplayName(name) {
|
|
|
105
144
|
.replace(/([a-z])([A-Z])/g, "$1 $2")
|
|
106
145
|
.replace(/^./, (c) => c.toUpperCase());
|
|
107
146
|
}
|
|
147
|
+
const ALLOWED_PROP_FIELDS = new Set([
|
|
148
|
+
"name",
|
|
149
|
+
"displayName",
|
|
150
|
+
"type",
|
|
151
|
+
"required",
|
|
152
|
+
"description",
|
|
153
|
+
"defaultValue",
|
|
154
|
+
"groupId",
|
|
155
|
+
"typeId",
|
|
156
|
+
"enumTypeId",
|
|
157
|
+
"filteredComponentIds",
|
|
158
|
+
"privateVarMap",
|
|
159
|
+
]);
|
|
108
160
|
/**
|
|
109
161
|
* Parse and validate the --props JSON flag for add-component.
|
|
110
162
|
* Returns validated ComponentProp[] or exits with error.
|
|
@@ -132,6 +184,16 @@ async function parsePropsFlag(propsJson, config, configPath) {
|
|
|
132
184
|
const props = [];
|
|
133
185
|
for (const raw of rawProps) {
|
|
134
186
|
const r = raw;
|
|
187
|
+
const unknownFields = Object.keys(r).filter((k) => !ALLOWED_PROP_FIELDS.has(k));
|
|
188
|
+
if (unknownFields.length > 0) {
|
|
189
|
+
console.log(JSON.stringify({
|
|
190
|
+
success: false,
|
|
191
|
+
error: `Unknown field(s) in --props entry: ${unknownFields.join(", ")}. ` +
|
|
192
|
+
`Allowed: ${[...ALLOWED_PROP_FIELDS].join(", ")}. ` +
|
|
193
|
+
`Note: use "groupId" (not "group") and "defaultValue" (not "default") in --props JSON.`,
|
|
194
|
+
}));
|
|
195
|
+
process.exit(1);
|
|
196
|
+
}
|
|
135
197
|
if (!r.name || typeof r.name !== "string") {
|
|
136
198
|
console.log(JSON.stringify({
|
|
137
199
|
success: false,
|
|
@@ -172,6 +234,14 @@ async function parsePropsFlag(propsJson, config, configPath) {
|
|
|
172
234
|
}));
|
|
173
235
|
process.exit(1);
|
|
174
236
|
}
|
|
237
|
+
// Validate LINK / LIST_OF_LINK defaultValue shape (reject JSON strings and legacy { href })
|
|
238
|
+
if ((propType === "LINK" || propType === "LIST_OF_LINK") && r.defaultValue !== undefined) {
|
|
239
|
+
const linkError = validateLinkDefaultValue(propType, r.defaultValue, r.name);
|
|
240
|
+
if (linkError) {
|
|
241
|
+
console.log(JSON.stringify({ success: false, error: linkError }));
|
|
242
|
+
process.exit(1);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
175
245
|
// Auto-generate displayName if omitted
|
|
176
246
|
const displayName = typeof r.displayName === "string" && r.displayName
|
|
177
247
|
? r.displayName
|
|
@@ -322,16 +392,9 @@ async function addComponent(name, options) {
|
|
|
322
392
|
],
|
|
323
393
|
}));
|
|
324
394
|
}
|
|
325
|
-
async function addProp(
|
|
395
|
+
async function addProp(ref, options) {
|
|
326
396
|
const { config, configPath } = loadConfig();
|
|
327
|
-
const component =
|
|
328
|
-
if (!component) {
|
|
329
|
-
console.log(JSON.stringify({
|
|
330
|
-
success: false,
|
|
331
|
-
error: `Component "${componentName}" not found. Available: ${getComponentNames(config).join(", ")}`,
|
|
332
|
-
}));
|
|
333
|
-
process.exit(1);
|
|
334
|
-
}
|
|
397
|
+
const component = resolveComponent(config, ref);
|
|
335
398
|
// Validate prop type
|
|
336
399
|
const propType = options.type.toUpperCase();
|
|
337
400
|
if (!PROP_TYPES.includes(propType)) {
|
|
@@ -434,14 +497,22 @@ async function addProp(componentName, options) {
|
|
|
434
497
|
process.exit(1);
|
|
435
498
|
}
|
|
436
499
|
}
|
|
500
|
+
const parsedDefaultValue = options.defaultValue !== undefined ? parseDefaultValue(options.defaultValue, propType) : undefined;
|
|
501
|
+
if ((propType === "LINK" || propType === "LIST_OF_LINK") && parsedDefaultValue !== undefined) {
|
|
502
|
+
const linkError = validateLinkDefaultValue(propType, parsedDefaultValue, options.name);
|
|
503
|
+
if (linkError) {
|
|
504
|
+
console.log(JSON.stringify({ success: false, error: linkError }));
|
|
505
|
+
process.exit(1);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
437
508
|
const newProp = {
|
|
438
509
|
name: options.name,
|
|
439
510
|
displayName: options.displayName,
|
|
440
511
|
type: propType,
|
|
441
512
|
required: options.required ?? false,
|
|
442
513
|
...(options.description ? { description: options.description } : {}),
|
|
443
|
-
...(
|
|
444
|
-
? { defaultValue:
|
|
514
|
+
...(parsedDefaultValue !== undefined
|
|
515
|
+
? { defaultValue: parsedDefaultValue }
|
|
445
516
|
: {}),
|
|
446
517
|
...(options.group ? { groupId: options.group } : {}),
|
|
447
518
|
...(options.typeId ? { typeId: options.typeId } : {}),
|
|
@@ -475,20 +546,73 @@ function parseDefaultValue(value, propType) {
|
|
|
475
546
|
return Number(value);
|
|
476
547
|
case "BOOLEAN":
|
|
477
548
|
return value === "true";
|
|
549
|
+
case "LINK":
|
|
550
|
+
case "LIST_OF_LINK":
|
|
551
|
+
// The --default-value flag arrives as a string; LINK values must be stored as a
|
|
552
|
+
// typed object. Parse it here; if it is not valid JSON, return the raw string so
|
|
553
|
+
// validateLinkDefaultValue can report a precise error.
|
|
554
|
+
try {
|
|
555
|
+
return JSON.parse(value);
|
|
556
|
+
}
|
|
557
|
+
catch {
|
|
558
|
+
return value;
|
|
559
|
+
}
|
|
478
560
|
default:
|
|
479
561
|
return value;
|
|
480
562
|
}
|
|
481
563
|
}
|
|
482
|
-
|
|
564
|
+
const VALID_LINK_TYPES = ["PAGE", "EXTERNAL", "FILE"];
|
|
565
|
+
const LINK_SHAPE_HELP = 'A link must be an object: { "linkType": "EXTERNAL", "label": "Text", "externalLink": "https://...", "subLinks": [] } ' +
|
|
566
|
+
'for external links, or { "linkType": "PAGE", "label": "Text", "pageType": "INDEX", "subLinks": [] } for store pages. ' +
|
|
567
|
+
"Do NOT pass a JSON string or a { label, href } shape.";
|
|
568
|
+
// Returns the index of the first array element that fails `fn`, as an error string, or null.
|
|
569
|
+
const firstError = (arr, fn) => arr.reduce((acc, item, index) => acc ?? fn(item, index), null);
|
|
570
|
+
const validateSingleLink = (link, propName, path) => {
|
|
571
|
+
const where = `defaultValue for prop "${propName}"${path}`;
|
|
572
|
+
if (typeof link === "string") {
|
|
573
|
+
return `${where} is a JSON string but must be an object. ${LINK_SHAPE_HELP}`;
|
|
574
|
+
}
|
|
575
|
+
if (!link || typeof link !== "object" || Array.isArray(link)) {
|
|
576
|
+
return `${where} must be a link object. ${LINK_SHAPE_HELP}`;
|
|
577
|
+
}
|
|
578
|
+
const l = link;
|
|
579
|
+
if ("href" in l && !("linkType" in l)) {
|
|
580
|
+
return `${where} uses a legacy { href } shape without "linkType". Use "linkType" + "externalLink"/"pageType" instead. ${LINK_SHAPE_HELP}`;
|
|
581
|
+
}
|
|
582
|
+
if (typeof l.linkType !== "string" || !VALID_LINK_TYPES.includes(l.linkType)) {
|
|
583
|
+
return `${where} must have a valid "linkType" (one of ${VALID_LINK_TYPES.join(", ")}). ${LINK_SHAPE_HELP}`;
|
|
584
|
+
}
|
|
585
|
+
if (l.subLinks !== undefined && !Array.isArray(l.subLinks)) {
|
|
586
|
+
return `${where}: "subLinks" must be an array (use [] when there are none).`;
|
|
587
|
+
}
|
|
588
|
+
if (Array.isArray(l.subLinks)) {
|
|
589
|
+
return firstError(l.subLinks, (sl, i) => validateSingleLink(sl, propName, `${path}.subLinks[${i}]`));
|
|
590
|
+
}
|
|
591
|
+
return null;
|
|
592
|
+
};
|
|
593
|
+
// Validates a LINK / LIST_OF_LINK defaultValue. Returns an error message, or null if valid.
|
|
594
|
+
// These defaults are a frequent source of bad data: agents tend to pass a JSON string or a
|
|
595
|
+
// legacy { label, href } shape. Rejecting them at authoring time keeps malformed link values
|
|
596
|
+
// out of published themes.
|
|
597
|
+
function validateLinkDefaultValue(propType, value, propName) {
|
|
598
|
+
if (value === undefined || value === null)
|
|
599
|
+
return null;
|
|
600
|
+
if (propType === "LINK") {
|
|
601
|
+
return validateSingleLink(value, propName, "");
|
|
602
|
+
}
|
|
603
|
+
// LIST_OF_LINK
|
|
604
|
+
if (typeof value === "string") {
|
|
605
|
+
return `defaultValue for prop "${propName}" is a JSON string but must be an object { "links": [...] }. ${LINK_SHAPE_HELP}`;
|
|
606
|
+
}
|
|
607
|
+
if (!value || typeof value !== "object" || Array.isArray(value) || !Array.isArray(value.links)) {
|
|
608
|
+
return `defaultValue for prop "${propName}" must be an object with a "links" array: { "links": [ <link>, ... ] }. ${LINK_SHAPE_HELP}`;
|
|
609
|
+
}
|
|
610
|
+
const links = value.links;
|
|
611
|
+
return firstError(links, (link, i) => validateSingleLink(link, propName, `.links[${i}]`));
|
|
612
|
+
}
|
|
613
|
+
function updateProp(ref, options) {
|
|
483
614
|
const { config, configPath } = loadConfig();
|
|
484
|
-
const component =
|
|
485
|
-
if (!component) {
|
|
486
|
-
console.log(JSON.stringify({
|
|
487
|
-
success: false,
|
|
488
|
-
error: `Component "${componentName}" not found. Available: ${getComponentNames(config).join(", ")}`,
|
|
489
|
-
}));
|
|
490
|
-
process.exit(1);
|
|
491
|
-
}
|
|
615
|
+
const component = resolveComponent(config, ref);
|
|
492
616
|
const propIndex = component.props.findIndex((p) => p.name === options.prop);
|
|
493
617
|
if (propIndex === -1) {
|
|
494
618
|
console.log(JSON.stringify({
|
|
@@ -519,7 +643,15 @@ function updateProp(componentName, options) {
|
|
|
519
643
|
prop.description = options.description || undefined;
|
|
520
644
|
}
|
|
521
645
|
if (options.defaultValue !== undefined) {
|
|
522
|
-
|
|
646
|
+
const parsed = parseDefaultValue(options.defaultValue, prop.type);
|
|
647
|
+
if (prop.type === "LINK" || prop.type === "LIST_OF_LINK") {
|
|
648
|
+
const linkError = validateLinkDefaultValue(prop.type, parsed, prop.name);
|
|
649
|
+
if (linkError) {
|
|
650
|
+
console.log(JSON.stringify({ success: false, error: linkError }));
|
|
651
|
+
process.exit(1);
|
|
652
|
+
}
|
|
653
|
+
}
|
|
654
|
+
prop.defaultValue = parsed;
|
|
523
655
|
}
|
|
524
656
|
if (options.group !== undefined) {
|
|
525
657
|
if (options.group === "" || options.group === "none") {
|
|
@@ -622,16 +754,9 @@ function updateProp(componentName, options) {
|
|
|
622
754
|
},
|
|
623
755
|
}));
|
|
624
756
|
}
|
|
625
|
-
function removeProp(
|
|
757
|
+
function removeProp(ref, options) {
|
|
626
758
|
const { config, configPath } = loadConfig();
|
|
627
|
-
const component =
|
|
628
|
-
if (!component) {
|
|
629
|
-
console.log(JSON.stringify({
|
|
630
|
-
success: false,
|
|
631
|
-
error: `Component "${componentName}" not found. Available: ${getComponentNames(config).join(", ")}`,
|
|
632
|
-
}));
|
|
633
|
-
process.exit(1);
|
|
634
|
-
}
|
|
759
|
+
const component = resolveComponent(config, ref);
|
|
635
760
|
const propIndex = component.props.findIndex((p) => p.name === options.prop);
|
|
636
761
|
if (propIndex === -1) {
|
|
637
762
|
console.log(JSON.stringify({
|
|
@@ -668,18 +793,10 @@ function pruneFilteredComponentIdRefs(config, removedId) {
|
|
|
668
793
|
}
|
|
669
794
|
}
|
|
670
795
|
}
|
|
671
|
-
function removeComponent(
|
|
796
|
+
function removeComponent(ref) {
|
|
672
797
|
const { config, configPath } = loadConfig();
|
|
673
|
-
const
|
|
674
|
-
const componentIndex = config.components.
|
|
675
|
-
if (componentIndex === -1) {
|
|
676
|
-
console.log(JSON.stringify({
|
|
677
|
-
success: false,
|
|
678
|
-
error: `Component "${options.name}" not found. Available: ${getComponentNames(config).join(", ")}`,
|
|
679
|
-
}));
|
|
680
|
-
process.exit(1);
|
|
681
|
-
}
|
|
682
|
-
const component = config.components[componentIndex];
|
|
798
|
+
const component = resolveComponent(config, ref);
|
|
799
|
+
const componentIndex = config.components.indexOf(component);
|
|
683
800
|
const componentDir = path.resolve(process.cwd(), path.dirname(component.entry));
|
|
684
801
|
// Remove component from config and strip orphaned references from remaining components
|
|
685
802
|
config.components.splice(componentIndex, 1);
|
|
@@ -693,21 +810,15 @@ function removeComponent(options) {
|
|
|
693
810
|
updateBarrelExport(process.cwd(), getComponentNames(config));
|
|
694
811
|
console.log(JSON.stringify({
|
|
695
812
|
success: true,
|
|
696
|
-
|
|
813
|
+
removedComponentId: component.id,
|
|
814
|
+
removedComponentName: component.name,
|
|
697
815
|
removedDirectory: path.relative(process.cwd(), componentDir),
|
|
698
|
-
remainingComponents:
|
|
816
|
+
remainingComponents: config.components.map((c) => ({ id: c.id, name: c.name })),
|
|
699
817
|
}));
|
|
700
818
|
}
|
|
701
|
-
function addPropGroup(
|
|
819
|
+
function addPropGroup(ref, options) {
|
|
702
820
|
const { config, configPath } = loadConfig();
|
|
703
|
-
const component =
|
|
704
|
-
if (!component) {
|
|
705
|
-
console.log(JSON.stringify({
|
|
706
|
-
success: false,
|
|
707
|
-
error: `Component "${componentName}" not found. Available: ${getComponentNames(config).join(", ")}`,
|
|
708
|
-
}));
|
|
709
|
-
process.exit(1);
|
|
710
|
-
}
|
|
821
|
+
const component = resolveComponent(config, ref);
|
|
711
822
|
if (!component.propGroups)
|
|
712
823
|
component.propGroups = [];
|
|
713
824
|
// Check uniqueness
|
|
@@ -758,16 +869,9 @@ function addPropGroup(componentName, options) {
|
|
|
758
869
|
},
|
|
759
870
|
}));
|
|
760
871
|
}
|
|
761
|
-
function updatePropGroup(
|
|
872
|
+
function updatePropGroup(ref, options) {
|
|
762
873
|
const { config, configPath } = loadConfig();
|
|
763
|
-
const component =
|
|
764
|
-
if (!component) {
|
|
765
|
-
console.log(JSON.stringify({
|
|
766
|
-
success: false,
|
|
767
|
-
error: `Component "${componentName}" not found. Available: ${getComponentNames(config).join(", ")}`,
|
|
768
|
-
}));
|
|
769
|
-
process.exit(1);
|
|
770
|
-
}
|
|
874
|
+
const component = resolveComponent(config, ref);
|
|
771
875
|
if (!component.propGroups || component.propGroups.length === 0) {
|
|
772
876
|
console.log(JSON.stringify({
|
|
773
877
|
success: false,
|
|
@@ -797,16 +901,9 @@ function updatePropGroup(componentName, options) {
|
|
|
797
901
|
},
|
|
798
902
|
}));
|
|
799
903
|
}
|
|
800
|
-
function removePropGroup(
|
|
904
|
+
function removePropGroup(ref, options) {
|
|
801
905
|
const { config, configPath } = loadConfig();
|
|
802
|
-
const component =
|
|
803
|
-
if (!component) {
|
|
804
|
-
console.log(JSON.stringify({
|
|
805
|
-
success: false,
|
|
806
|
-
error: `Component "${componentName}" not found. Available: ${getComponentNames(config).join(", ")}`,
|
|
807
|
-
}));
|
|
808
|
-
process.exit(1);
|
|
809
|
-
}
|
|
906
|
+
const component = resolveComponent(config, ref);
|
|
810
907
|
if (!component.propGroups || component.propGroups.length === 0) {
|
|
811
908
|
console.log(JSON.stringify({
|
|
812
909
|
success: false,
|
|
@@ -842,16 +939,9 @@ function removePropGroup(componentName, options) {
|
|
|
842
939
|
remainingPropGroups: component.propGroups.map(g => g.id),
|
|
843
940
|
}));
|
|
844
941
|
}
|
|
845
|
-
function movePropGroup(
|
|
942
|
+
function movePropGroup(ref, options) {
|
|
846
943
|
const { config, configPath } = loadConfig();
|
|
847
|
-
const component =
|
|
848
|
-
if (!component) {
|
|
849
|
-
console.log(JSON.stringify({
|
|
850
|
-
success: false,
|
|
851
|
-
error: `Component "${componentName}" not found. Available: ${getComponentNames(config).join(", ")}`,
|
|
852
|
-
}));
|
|
853
|
-
process.exit(1);
|
|
854
|
-
}
|
|
944
|
+
const component = resolveComponent(config, ref);
|
|
855
945
|
if (!component.propGroups || component.propGroups.length === 0) {
|
|
856
946
|
console.log(JSON.stringify({
|
|
857
947
|
success: false,
|
|
@@ -874,16 +964,9 @@ function movePropGroup(componentName, options) {
|
|
|
874
964
|
parentGroupId: options.parent || null,
|
|
875
965
|
}));
|
|
876
966
|
}
|
|
877
|
-
function updateComponent(options) {
|
|
967
|
+
function updateComponent(ref, options) {
|
|
878
968
|
const { config, configPath } = loadConfig();
|
|
879
|
-
const component =
|
|
880
|
-
if (!component) {
|
|
881
|
-
console.log(JSON.stringify({
|
|
882
|
-
success: false,
|
|
883
|
-
error: `Component "${options.name}" not found. Available: ${getComponentNames(config).join(", ")}`,
|
|
884
|
-
}));
|
|
885
|
-
process.exit(1);
|
|
886
|
-
}
|
|
969
|
+
const component = resolveComponent(config, ref);
|
|
887
970
|
if (options.isHeader !== undefined) {
|
|
888
971
|
if (options.isHeader) {
|
|
889
972
|
component.isHeader = true;
|
|
@@ -1136,14 +1219,16 @@ export function createConfigCommand() {
|
|
|
1136
1219
|
.option("--type <type>", "Component type: section or component", "component")
|
|
1137
1220
|
.option("--isHeader", "Mark this section as the store header (only for type: section)")
|
|
1138
1221
|
.option("--isFooter", "Mark this section as the store footer (only for type: section)")
|
|
1139
|
-
.option("--props <json>", "JSON array of props
|
|
1222
|
+
.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
|
+
"Example: '[{\"name\":\"title\",\"type\":\"TEXT\",\"required\":true,\"defaultValue\":\"Hello\",\"groupId\":\"basic\"}]'")
|
|
1140
1224
|
.action((options) => {
|
|
1141
1225
|
addComponent(options.name, options);
|
|
1142
1226
|
});
|
|
1143
1227
|
config
|
|
1144
1228
|
.command("add-prop")
|
|
1145
1229
|
.description("Add a prop to a component")
|
|
1146
|
-
.
|
|
1230
|
+
.option("--component-id <id>", "Component id (preferred; from `config list-components`)")
|
|
1231
|
+
.option("--component <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1147
1232
|
.requiredOption("--name <name>", "Prop name (camelCase)")
|
|
1148
1233
|
.requiredOption("--displayName <displayName>", "Display name in editor")
|
|
1149
1234
|
.requiredOption("--type <type>", `Prop type: ${PROP_TYPES.join(", ")}`)
|
|
@@ -1156,12 +1241,13 @@ export function createConfigCommand() {
|
|
|
1156
1241
|
.option("--filteredComponentIds <json>", "JSON array of component IDs to restrict selection (for COMPONENT/COMPONENT_LIST)")
|
|
1157
1242
|
.option("--privateVarMap <json>", 'JSON object mapping variable keys to {id, typeId} (for COMPONENT/COMPONENT_LIST)')
|
|
1158
1243
|
.action((options) => {
|
|
1159
|
-
addProp(options.component, options);
|
|
1244
|
+
addProp({ id: options.componentId, name: options.component }, options);
|
|
1160
1245
|
});
|
|
1161
1246
|
config
|
|
1162
1247
|
.command("update-prop")
|
|
1163
1248
|
.description("Update a prop on a component")
|
|
1164
|
-
.
|
|
1249
|
+
.option("--component-id <id>", "Component id (preferred; from `config list-components`)")
|
|
1250
|
+
.option("--component <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1165
1251
|
.requiredOption("--prop <propName>", "Prop name to update")
|
|
1166
1252
|
.option("--displayName <displayName>", "New display name")
|
|
1167
1253
|
.option("--type <type>", "New prop type")
|
|
@@ -1174,76 +1260,89 @@ export function createConfigCommand() {
|
|
|
1174
1260
|
.option("--filteredComponentIds <json>", "JSON array of component IDs (use 'none' to clear)")
|
|
1175
1261
|
.option("--privateVarMap <json>", "JSON object mapping variable keys to {id, typeId} (use 'none' to clear)")
|
|
1176
1262
|
.action((options) => {
|
|
1177
|
-
updateProp(options.component, options);
|
|
1263
|
+
updateProp({ id: options.componentId, name: options.component }, options);
|
|
1178
1264
|
});
|
|
1179
1265
|
config
|
|
1180
1266
|
.command("remove-prop")
|
|
1181
1267
|
.description("Remove a prop from a component")
|
|
1182
|
-
.
|
|
1268
|
+
.option("--component-id <id>", "Component id (preferred; from `config list-components`)")
|
|
1269
|
+
.option("--component <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1183
1270
|
.requiredOption("--prop <propName>", "Prop name to remove")
|
|
1184
1271
|
.action((options) => {
|
|
1185
|
-
removeProp(options.component, options);
|
|
1272
|
+
removeProp({ id: options.componentId, name: options.component }, options);
|
|
1186
1273
|
});
|
|
1187
1274
|
config
|
|
1188
1275
|
.command("update-component")
|
|
1189
|
-
.description("Update a component's metadata (isHeader, isFooter)")
|
|
1190
|
-
.
|
|
1276
|
+
.description("Update a component's metadata (isHeader, isFooter). Identify by --id (preferred) or exact --name.")
|
|
1277
|
+
.option("--id <id>", "Component id (preferred; from `config list-components`)")
|
|
1278
|
+
.option("--name <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1191
1279
|
.option("--isHeader", "Mark as store header")
|
|
1192
1280
|
.option("--no-isHeader", "Unmark as store header")
|
|
1193
1281
|
.option("--isFooter", "Mark as store footer")
|
|
1194
1282
|
.option("--no-isFooter", "Unmark as store footer")
|
|
1195
1283
|
.action((options) => {
|
|
1196
|
-
updateComponent(options);
|
|
1284
|
+
updateComponent({ id: options.id, name: options.name }, options);
|
|
1197
1285
|
});
|
|
1198
1286
|
config
|
|
1199
1287
|
.command("remove-component")
|
|
1200
|
-
.description("Remove a component from the project (deletes files)")
|
|
1201
|
-
.
|
|
1288
|
+
.description("Remove a component from the project (deletes files). Identify by --id (preferred) or exact --name.")
|
|
1289
|
+
.option("--id <id>", "Component id (preferred; from `config list-components`)")
|
|
1290
|
+
.option("--name <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1202
1291
|
.action((options) => {
|
|
1203
|
-
removeComponent(options);
|
|
1292
|
+
removeComponent({ id: options.id, name: options.name });
|
|
1204
1293
|
});
|
|
1205
1294
|
config
|
|
1206
1295
|
.command("add-prop-group")
|
|
1207
1296
|
.description("Add a prop group to a component")
|
|
1208
|
-
.
|
|
1297
|
+
.option("--component-id <componentId>", "Component id (preferred; from `config list-components`)")
|
|
1298
|
+
.option("--component <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1209
1299
|
.requiredOption("--id <id>", "Group ID (unique within component, kebab-case)")
|
|
1210
1300
|
.requiredOption("--name <name>", "Display name in editor")
|
|
1211
1301
|
.option("--description <description>", "Group description")
|
|
1212
1302
|
.option("--parent <parentId>", "Parent group ID (for nesting, max 1 level)")
|
|
1213
1303
|
.action((options) => {
|
|
1214
|
-
addPropGroup(options.component, options);
|
|
1304
|
+
addPropGroup({ id: options.componentId, name: options.component }, options);
|
|
1215
1305
|
});
|
|
1216
1306
|
config
|
|
1217
1307
|
.command("update-prop-group")
|
|
1218
1308
|
.description("Update a prop group on a component")
|
|
1219
|
-
.
|
|
1309
|
+
.option("--component-id <componentId>", "Component id (preferred; from `config list-components`)")
|
|
1310
|
+
.option("--component <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1220
1311
|
.requiredOption("--id <id>", "Group ID to update")
|
|
1221
1312
|
.option("--name <name>", "New display name")
|
|
1222
1313
|
.option("--description <description>", "New description")
|
|
1223
1314
|
.action((options) => {
|
|
1224
|
-
updatePropGroup(options.component, options);
|
|
1315
|
+
updatePropGroup({ id: options.componentId, name: options.component }, options);
|
|
1225
1316
|
});
|
|
1226
1317
|
config
|
|
1227
1318
|
.command("remove-prop-group")
|
|
1228
1319
|
.description("Remove a prop group from a component (props become ungrouped)")
|
|
1229
|
-
.
|
|
1320
|
+
.option("--component-id <componentId>", "Component id (preferred; from `config list-components`)")
|
|
1321
|
+
.option("--component <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1230
1322
|
.requiredOption("--id <id>", "Group ID to remove")
|
|
1231
1323
|
.action((options) => {
|
|
1232
|
-
removePropGroup(options.component, options);
|
|
1324
|
+
removePropGroup({ id: options.componentId, name: options.component }, options);
|
|
1233
1325
|
});
|
|
1234
1326
|
config
|
|
1235
1327
|
.command("move-prop-group")
|
|
1236
1328
|
.description("Move a prop group to a different parent or position (for drag-and-drop reordering)")
|
|
1237
|
-
.
|
|
1329
|
+
.option("--component-id <componentId>", "Component id (preferred; from `config list-components`)")
|
|
1330
|
+
.option("--component <name>", "Component name — exact match (PascalCase, as stored in ikas.config.json)")
|
|
1238
1331
|
.requiredOption("--id <id>", "Group ID to move")
|
|
1239
1332
|
.option("--parent <parentId>", "Target parent group ID (omit to move to root)")
|
|
1240
1333
|
.option("--index <index>", "Zero-based insertion index within the target parent (appends when omitted)", v => parseInt(v, 10))
|
|
1241
1334
|
.action((options) => {
|
|
1242
|
-
movePropGroup(options.component, options);
|
|
1335
|
+
movePropGroup({ id: options.componentId, name: options.component }, options);
|
|
1336
|
+
});
|
|
1337
|
+
config
|
|
1338
|
+
.command("list-components")
|
|
1339
|
+
.description("List all components and their props (with canonical ids for use with --id flags)")
|
|
1340
|
+
.action(() => {
|
|
1341
|
+
listComponents();
|
|
1243
1342
|
});
|
|
1244
1343
|
config
|
|
1245
1344
|
.command("list")
|
|
1246
|
-
.description("
|
|
1345
|
+
.description("Alias for `list-components` (kept for backwards compatibility)")
|
|
1247
1346
|
.action(() => {
|
|
1248
1347
|
listComponents();
|
|
1249
1348
|
});
|