@ikas/component-cli 1.4.0-beta.186 → 1.4.0-beta.188
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 +196 -8
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/dev.d.ts.map +1 -1
- package/dist/commands/dev.js +138 -27
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/publish.d.ts.map +1 -1
- package/dist/commands/publish.js +11 -2
- package/dist/commands/publish.js.map +1 -1
- package/dist/types.d.ts +28 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/component-helpers.d.ts +82 -0
- package/dist/utils/component-helpers.d.ts.map +1 -1
- package/dist/utils/component-helpers.js +165 -2
- package/dist/utils/component-helpers.js.map +1 -1
- package/dist/utils/websocket-server.d.ts +35 -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;AAmXpC,eAAO,MAAM,qBAAqB,SAAU;IAC1C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;CACd,KAAG,OAA2D,CAAC;AAEhE;;;;GAIG;AACH,wBAAgB,sBAAsB,CACpC,GAAG,EAAE,OAAO,EACZ,QAAQ,EAAE,MAAM,GACf;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAqBlE;AAmyBD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CA0B1E;AAMD,eAAO,MAAM,kBAAkB,UAkB9B,CAAC;AAOF,eAAO,MAAM,oBAAoB,aACrB,MAAM,YACN,MAAM,gBACF,OAAO,KACpB,IAUF,CAAC;AAuEF,wBAAgB,wBAAwB,CACtC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAwBf;AAOD;;;;;GAKG;AACH,wBAAgB,6BAA6B,CAC3C,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,EAChB,oBAAoB,CAAC,EAAE,MAAM,EAAE,EAC/B,oBAAoB,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GACjC,MAAM,GAAG,IAAI,CAuDf;AAoDD,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAoBf;AAUD,wBAAgB,+BAA+B,CAC7C,KAAK,EAAE,OAAO,EACd,eAAe,EACX;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GAChE,SAAS,EACb,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAsCf;AASD,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,GACf,MAAM,GAAG,IAAI,CAgBf;AA+FD,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,OAAO,GACd,MAAM,GAAG,IAAI,CAwBf;AA4iCD,wBAAgB,mBAAmB,IAAI,OAAO,CA+X7C"}
|
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, isBuiltInEnumTypeId, generateGlobalTypesFile, collectUsedEnumIds, generateComponentFile, generateStylesFile, generateProjectId, isValidProjectId, generateComponentId, generateUniqueId, updateBarrelExport, findPropGroup, collectPropGroupIds, movePropGroupInTree, validateFilteredComponentIds, } from "../utils/component-helpers.js";
|
|
4
|
+
import { PROP_TYPES, toPascalCase, generateTypesFile, isBuiltInEnumTypeId, generateGlobalTypesFile, collectUsedEnumIds, generateComponentFile, generateStylesFile, generateProjectId, isValidProjectId, generateComponentId, generateUniqueId, updateBarrelExport, findPropGroup, collectPropGroupIds, movePropGroupInTree, validateFilteredComponentIds, visibilityGateError, pruneCustomTypesNoLongerUsed, usedCustomTypeIds, } 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)) {
|
|
@@ -168,6 +168,10 @@ const ALLOWED_PROP_FIELDS = new Set([
|
|
|
168
168
|
"filteredComponentIds",
|
|
169
169
|
"privateVarMap",
|
|
170
170
|
"numberRangeData",
|
|
171
|
+
"requiredProp",
|
|
172
|
+
"requiredPropValue",
|
|
173
|
+
"requiredEnumOptionId",
|
|
174
|
+
"requiredEnumOptionValue",
|
|
171
175
|
]);
|
|
172
176
|
// Emit the standard CLI error envelope and exit(1) when a validator returned a message; a no-op
|
|
173
177
|
// when the message is null. Collapses the repeated `if (err) { console.log(...); process.exit(1) }`
|
|
@@ -178,6 +182,24 @@ function failIf(error) {
|
|
|
178
182
|
process.exit(1);
|
|
179
183
|
}
|
|
180
184
|
}
|
|
185
|
+
/**
|
|
186
|
+
* A `--requiredPropValue` flag as a boolean. Commander hands every flag over as a string, and this is
|
|
187
|
+
* the one place that turns it back; anything other than true/false is refused rather than coerced,
|
|
188
|
+
* since "0" or "off" silently becoming `true` is exactly the kind of gate nobody would think to
|
|
189
|
+
* check.
|
|
190
|
+
*/
|
|
191
|
+
function parseRequiredPropValue(raw, where) {
|
|
192
|
+
if (raw === undefined)
|
|
193
|
+
return undefined;
|
|
194
|
+
if (typeof raw === "boolean")
|
|
195
|
+
return raw;
|
|
196
|
+
if (raw === "true")
|
|
197
|
+
return true;
|
|
198
|
+
if (raw === "false")
|
|
199
|
+
return false;
|
|
200
|
+
failIf(`--requiredPropValue for ${where} must be "true" or "false" (got "${raw}").`);
|
|
201
|
+
return undefined;
|
|
202
|
+
}
|
|
181
203
|
/**
|
|
182
204
|
* Validate/sanitize a numberRangeData object for a NUMBER_RANGE prop. Accepts an object
|
|
183
205
|
* or a JSON string. min/max/interval are truncated to integers; only a positive interval
|
|
@@ -434,9 +456,30 @@ async function parsePropsFlag(propsJson, config, configPath) {
|
|
|
434
456
|
...(propType === "NUMBER_RANGE"
|
|
435
457
|
? { numberRangeData: requireNumberRangeData(r.numberRangeData, r.name) }
|
|
436
458
|
: {}),
|
|
459
|
+
...(r.requiredProp !== undefined
|
|
460
|
+
? { requiredProp: r.requiredProp }
|
|
461
|
+
: {}),
|
|
462
|
+
...(r.requiredPropValue !== undefined
|
|
463
|
+
? { requiredPropValue: r.requiredPropValue }
|
|
464
|
+
: {}),
|
|
465
|
+
...(r.requiredEnumOptionId !== undefined
|
|
466
|
+
? { requiredEnumOptionId: r.requiredEnumOptionId }
|
|
467
|
+
: {}),
|
|
468
|
+
...(r.requiredEnumOptionValue !== undefined
|
|
469
|
+
? { requiredEnumOptionValue: r.requiredEnumOptionValue }
|
|
470
|
+
: {}),
|
|
437
471
|
};
|
|
438
472
|
props.push(prop);
|
|
439
473
|
}
|
|
474
|
+
// Gates are checked once the whole batch is parsed: a prop may name one declared after it, and
|
|
475
|
+
// cycle detection needs every prop in hand. The batch IS the component's prop list here — the
|
|
476
|
+
// component itself does not exist yet — so it stands in as one.
|
|
477
|
+
const batch = { name: "the new component", props };
|
|
478
|
+
for (const prop of props) {
|
|
479
|
+
failIf(visibilityGateError(batch, prop, `prop "${prop.name}"`, {
|
|
480
|
+
selfPropName: prop.name,
|
|
481
|
+
}));
|
|
482
|
+
}
|
|
440
483
|
return props;
|
|
441
484
|
}
|
|
442
485
|
// --- Subcommands ---
|
|
@@ -690,6 +733,7 @@ async function addProp(ref, options) {
|
|
|
690
733
|
const numError = validateNumberDefaultValue(options.defaultValue, options.name);
|
|
691
734
|
failIf(numError);
|
|
692
735
|
}
|
|
736
|
+
const parsedVisibilityValue = parseRequiredPropValue(options.requiredPropValue, `prop "${options.name}"`);
|
|
693
737
|
const parsedNumberRangeData = propType === "NUMBER_RANGE"
|
|
694
738
|
? requireNumberRangeData(options.numberRangeData, options.name)
|
|
695
739
|
: undefined;
|
|
@@ -714,7 +758,21 @@ async function addProp(ref, options) {
|
|
|
714
758
|
...(parsedNumberRangeData
|
|
715
759
|
? { numberRangeData: parsedNumberRangeData }
|
|
716
760
|
: {}),
|
|
761
|
+
...(options.requiredProp ? { requiredProp: options.requiredProp } : {}),
|
|
762
|
+
...(parsedVisibilityValue !== undefined
|
|
763
|
+
? { requiredPropValue: parsedVisibilityValue }
|
|
764
|
+
: {}),
|
|
765
|
+
...(options.requiredProp && options.requiredEnumOptionValue !== undefined
|
|
766
|
+
? {
|
|
767
|
+
// The editor has no separate option id; the value doubles as one.
|
|
768
|
+
requiredEnumOptionId: options.requiredEnumOptionValue,
|
|
769
|
+
requiredEnumOptionValue: options.requiredEnumOptionValue,
|
|
770
|
+
}
|
|
771
|
+
: {}),
|
|
717
772
|
};
|
|
773
|
+
failIf(visibilityGateError(component, newProp, `prop "${newProp.name}"`, {
|
|
774
|
+
selfPropName: newProp.name,
|
|
775
|
+
}));
|
|
718
776
|
component.props.push(newProp);
|
|
719
777
|
saveConfig(configPath, config);
|
|
720
778
|
// Regenerate types.ts and global types
|
|
@@ -727,7 +785,6 @@ async function addProp(ref, options) {
|
|
|
727
785
|
name: newProp.name,
|
|
728
786
|
displayName: newProp.displayName,
|
|
729
787
|
type: newProp.type,
|
|
730
|
-
required: newProp.required,
|
|
731
788
|
...(newProp.groupId ? { groupId: newProp.groupId } : {}),
|
|
732
789
|
...(newProp.enumTypeId ? { enumTypeId: newProp.enumTypeId } : {}),
|
|
733
790
|
...(newProp.filteredComponentIds
|
|
@@ -739,6 +796,14 @@ async function addProp(ref, options) {
|
|
|
739
796
|
...(newProp.numberRangeData
|
|
740
797
|
? { numberRangeData: newProp.numberRangeData }
|
|
741
798
|
: {}),
|
|
799
|
+
...(newProp.requiredProp
|
|
800
|
+
? {
|
|
801
|
+
requiredProp: newProp.requiredProp,
|
|
802
|
+
...(newProp.requiredEnumOptionValue !== undefined
|
|
803
|
+
? { requiredEnumOptionValue: newProp.requiredEnumOptionValue }
|
|
804
|
+
: { requiredPropValue: newProp.requiredPropValue ?? true }),
|
|
805
|
+
}
|
|
806
|
+
: {}),
|
|
742
807
|
},
|
|
743
808
|
}));
|
|
744
809
|
}
|
|
@@ -871,9 +936,9 @@ export function validateLinkDefaultValue(propType, value, propName) {
|
|
|
871
936
|
const links = value.links;
|
|
872
937
|
return firstError(links, (link, i) => validateSingleLink(link, propName, `.links[${i}]`));
|
|
873
938
|
}
|
|
874
|
-
const COMPONENT_SHAPE_HELP =
|
|
939
|
+
const COMPONENT_SHAPE_HELP = "A COMPONENT / COMPONENT_LIST default must be an object listing child code components: " +
|
|
875
940
|
'{ "components": [ { "codeComponentId": "<id>" } ] }. Only code components are allowed; each entry ' +
|
|
876
|
-
|
|
941
|
+
'needs a string "codeComponentId" (no componentId, no inline propValues).';
|
|
877
942
|
/**
|
|
878
943
|
* Validate a COMPONENT / COMPONENT_LIST defaultValue. Reference-only: each entry must name a code
|
|
879
944
|
* component via `codeComponentId`. Rejects non-CC (`componentId`) children, missing ids, more than
|
|
@@ -887,14 +952,19 @@ export function validateComponentDefaultValue(propType, value, propName, filtere
|
|
|
887
952
|
if (typeof value === "string") {
|
|
888
953
|
return `${where} is a JSON string but must be an object. ${COMPONENT_SHAPE_HELP}`;
|
|
889
954
|
}
|
|
890
|
-
if (!value ||
|
|
955
|
+
if (!value ||
|
|
956
|
+
typeof value !== "object" ||
|
|
957
|
+
Array.isArray(value) ||
|
|
958
|
+
!Array.isArray(value.components)) {
|
|
891
959
|
return `${where} must be an object with a "components" array. ${COMPONENT_SHAPE_HELP}`;
|
|
892
960
|
}
|
|
893
961
|
const components = value.components;
|
|
894
962
|
if (propType === "COMPONENT" && components.length > 1) {
|
|
895
963
|
return `${where}: a COMPONENT prop holds a single child — provide at most one entry (use COMPONENT_LIST for many).`;
|
|
896
964
|
}
|
|
897
|
-
const allow = filteredComponentIds && filteredComponentIds.length
|
|
965
|
+
const allow = filteredComponentIds && filteredComponentIds.length
|
|
966
|
+
? new Set(filteredComponentIds)
|
|
967
|
+
: null;
|
|
898
968
|
return firstError(components, (entry, i) => {
|
|
899
969
|
const at = `${where}.components[${i}]`;
|
|
900
970
|
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
@@ -904,7 +974,8 @@ export function validateComponentDefaultValue(propType, value, propName, filtere
|
|
|
904
974
|
if ("componentId" in e && !("codeComponentId" in e)) {
|
|
905
975
|
return `${at} references a non-code component (componentId). Only code components are allowed as defaults. ${COMPONENT_SHAPE_HELP}`;
|
|
906
976
|
}
|
|
907
|
-
if (typeof e.codeComponentId !== "string" ||
|
|
977
|
+
if (typeof e.codeComponentId !== "string" ||
|
|
978
|
+
e.codeComponentId.trim().length === 0) {
|
|
908
979
|
return `${at} must have a non-empty string "codeComponentId". ${COMPONENT_SHAPE_HELP}`;
|
|
909
980
|
}
|
|
910
981
|
if (allow && !allow.has(e.codeComponentId)) {
|
|
@@ -1165,6 +1236,7 @@ async function updateProp(ref, options) {
|
|
|
1165
1236
|
process.exit(1);
|
|
1166
1237
|
}
|
|
1167
1238
|
const prop = component.props[propIndex];
|
|
1239
|
+
const previouslyUsedTypeIds = usedCustomTypeIds(config);
|
|
1168
1240
|
if (options.displayName !== undefined) {
|
|
1169
1241
|
prop.displayName = options.displayName;
|
|
1170
1242
|
}
|
|
@@ -1338,6 +1410,35 @@ async function updateProp(ref, options) {
|
|
|
1338
1410
|
}
|
|
1339
1411
|
}
|
|
1340
1412
|
}
|
|
1413
|
+
if (options.requiredProp !== undefined) {
|
|
1414
|
+
if (options.requiredProp === "" || options.requiredProp === "none") {
|
|
1415
|
+
// Every field goes together — see `IProp.requiredPropId`.
|
|
1416
|
+
delete prop.requiredProp;
|
|
1417
|
+
delete prop.requiredPropValue;
|
|
1418
|
+
delete prop.requiredEnumOptionId;
|
|
1419
|
+
delete prop.requiredEnumOptionValue;
|
|
1420
|
+
}
|
|
1421
|
+
else {
|
|
1422
|
+
prop.requiredProp = options.requiredProp;
|
|
1423
|
+
}
|
|
1424
|
+
}
|
|
1425
|
+
if (options.requiredEnumOptionValue !== undefined && prop.requiredProp) {
|
|
1426
|
+
prop.requiredEnumOptionId = options.requiredEnumOptionValue;
|
|
1427
|
+
prop.requiredEnumOptionValue = options.requiredEnumOptionValue;
|
|
1428
|
+
delete prop.requiredPropValue;
|
|
1429
|
+
}
|
|
1430
|
+
if (options.requiredPropValue !== undefined && prop.requiredProp) {
|
|
1431
|
+
delete prop.requiredEnumOptionId;
|
|
1432
|
+
delete prop.requiredEnumOptionValue;
|
|
1433
|
+
prop.requiredPropValue = parseRequiredPropValue(options.requiredPropValue, `prop "${prop.name}"`);
|
|
1434
|
+
}
|
|
1435
|
+
// Re-checked on every update, not only when a visibility flag is passed: flipping `required`, or
|
|
1436
|
+
// renaming the prop this one hangs on, can invalidate a gate that was sound when it was written.
|
|
1437
|
+
failIf(visibilityGateError(component, prop, `prop "${prop.name}"`, {
|
|
1438
|
+
selfPropName: prop.name,
|
|
1439
|
+
}));
|
|
1440
|
+
// Re-typing or re-binding the prop may leave its old enum unreferenced.
|
|
1441
|
+
pruneCustomTypesNoLongerUsed(config, previouslyUsedTypeIds);
|
|
1341
1442
|
saveConfig(configPath, config);
|
|
1342
1443
|
// Regenerate types.ts and global types
|
|
1343
1444
|
regenerateTypes(component, undefined, config);
|
|
@@ -1349,7 +1450,6 @@ async function updateProp(ref, options) {
|
|
|
1349
1450
|
name: prop.name,
|
|
1350
1451
|
displayName: prop.displayName,
|
|
1351
1452
|
type: prop.type,
|
|
1352
|
-
required: prop.required,
|
|
1353
1453
|
...(prop.groupId ? { groupId: prop.groupId } : {}),
|
|
1354
1454
|
...(prop.typeId ? { typeId: prop.typeId } : {}),
|
|
1355
1455
|
...(prop.enumTypeId ? { enumTypeId: prop.enumTypeId } : {}),
|
|
@@ -1360,6 +1460,14 @@ async function updateProp(ref, options) {
|
|
|
1360
1460
|
...(prop.numberRangeData
|
|
1361
1461
|
? { numberRangeData: prop.numberRangeData }
|
|
1362
1462
|
: {}),
|
|
1463
|
+
...(prop.requiredProp
|
|
1464
|
+
? {
|
|
1465
|
+
requiredProp: prop.requiredProp,
|
|
1466
|
+
...(prop.requiredEnumOptionValue !== undefined
|
|
1467
|
+
? { requiredEnumOptionValue: prop.requiredEnumOptionValue }
|
|
1468
|
+
: { requiredPropValue: prop.requiredPropValue ?? true }),
|
|
1469
|
+
}
|
|
1470
|
+
: {}),
|
|
1363
1471
|
},
|
|
1364
1472
|
}));
|
|
1365
1473
|
}
|
|
@@ -1374,7 +1482,9 @@ function removeProp(ref, options) {
|
|
|
1374
1482
|
}));
|
|
1375
1483
|
process.exit(1);
|
|
1376
1484
|
}
|
|
1485
|
+
const previouslyUsedTypeIds = usedCustomTypeIds(config);
|
|
1377
1486
|
component.props.splice(propIndex, 1);
|
|
1487
|
+
pruneCustomTypesNoLongerUsed(config, previouslyUsedTypeIds);
|
|
1378
1488
|
saveConfig(configPath, config);
|
|
1379
1489
|
// Regenerate types.ts and global types
|
|
1380
1490
|
regenerateTypes(component, undefined, config);
|
|
@@ -1446,7 +1556,24 @@ function addPropGroup(ref, options) {
|
|
|
1446
1556
|
id: options.id,
|
|
1447
1557
|
name: options.name,
|
|
1448
1558
|
...(options.description ? { description: options.description } : {}),
|
|
1559
|
+
...(options.requiredProp ? { requiredProp: options.requiredProp } : {}),
|
|
1560
|
+
...(options.requiredProp && options.requiredEnumOptionValue !== undefined
|
|
1561
|
+
? {
|
|
1562
|
+
requiredEnumOptionId: options.requiredEnumOptionValue,
|
|
1563
|
+
requiredEnumOptionValue: options.requiredEnumOptionValue,
|
|
1564
|
+
}
|
|
1565
|
+
: {}),
|
|
1566
|
+
...(options.requiredProp &&
|
|
1567
|
+
options.requiredEnumOptionValue === undefined &&
|
|
1568
|
+
options.requiredPropValue !== undefined
|
|
1569
|
+
? {
|
|
1570
|
+
requiredPropValue: parseRequiredPropValue(options.requiredPropValue, `group "${options.id}"`),
|
|
1571
|
+
}
|
|
1572
|
+
: {}),
|
|
1449
1573
|
};
|
|
1574
|
+
failIf(visibilityGateError(component, newGroup, `group "${newGroup.id}"`, {
|
|
1575
|
+
group: newGroup,
|
|
1576
|
+
}));
|
|
1450
1577
|
if (options.parent) {
|
|
1451
1578
|
const found = findPropGroup(component.propGroups, options.parent);
|
|
1452
1579
|
if (!found) {
|
|
@@ -1478,6 +1605,14 @@ function addPropGroup(ref, options) {
|
|
|
1478
1605
|
id: newGroup.id,
|
|
1479
1606
|
name: newGroup.name,
|
|
1480
1607
|
...(options.parent ? { parentId: options.parent } : {}),
|
|
1608
|
+
...(newGroup.requiredProp
|
|
1609
|
+
? {
|
|
1610
|
+
requiredProp: newGroup.requiredProp,
|
|
1611
|
+
...(newGroup.requiredEnumOptionValue !== undefined
|
|
1612
|
+
? { requiredEnumOptionValue: newGroup.requiredEnumOptionValue }
|
|
1613
|
+
: { requiredPropValue: newGroup.requiredPropValue ?? true }),
|
|
1614
|
+
}
|
|
1615
|
+
: {}),
|
|
1481
1616
|
},
|
|
1482
1617
|
}));
|
|
1483
1618
|
}
|
|
@@ -1503,6 +1638,34 @@ function updatePropGroup(ref, options) {
|
|
|
1503
1638
|
found.group.name = options.name;
|
|
1504
1639
|
if (options.description !== undefined)
|
|
1505
1640
|
found.group.description = options.description || undefined;
|
|
1641
|
+
if (options.requiredProp !== undefined) {
|
|
1642
|
+
if (options.requiredProp === "" || options.requiredProp === "none") {
|
|
1643
|
+
// Every field goes together — see `IThemePropGroup.requiredPropId`.
|
|
1644
|
+
delete found.group.requiredProp;
|
|
1645
|
+
delete found.group.requiredPropValue;
|
|
1646
|
+
delete found.group.requiredEnumOptionId;
|
|
1647
|
+
delete found.group.requiredEnumOptionValue;
|
|
1648
|
+
}
|
|
1649
|
+
else {
|
|
1650
|
+
found.group.requiredProp = options.requiredProp;
|
|
1651
|
+
}
|
|
1652
|
+
}
|
|
1653
|
+
if (options.requiredEnumOptionValue !== undefined &&
|
|
1654
|
+
found.group.requiredProp) {
|
|
1655
|
+
found.group.requiredEnumOptionId = options.requiredEnumOptionValue;
|
|
1656
|
+
found.group.requiredEnumOptionValue = options.requiredEnumOptionValue;
|
|
1657
|
+
delete found.group.requiredPropValue;
|
|
1658
|
+
}
|
|
1659
|
+
if (options.requiredPropValue !== undefined && found.group.requiredProp) {
|
|
1660
|
+
delete found.group.requiredEnumOptionId;
|
|
1661
|
+
delete found.group.requiredEnumOptionValue;
|
|
1662
|
+
found.group.requiredPropValue = parseRequiredPropValue(options.requiredPropValue, `group "${found.group.id}"`);
|
|
1663
|
+
}
|
|
1664
|
+
// Re-checked on every update: moving a prop into this group can invalidate a gate that was sound
|
|
1665
|
+
// when it was written.
|
|
1666
|
+
failIf(visibilityGateError(component, found.group, `group "${found.group.id}"`, {
|
|
1667
|
+
group: found.group,
|
|
1668
|
+
}));
|
|
1506
1669
|
saveConfig(configPath, config);
|
|
1507
1670
|
console.log(JSON.stringify({
|
|
1508
1671
|
success: true,
|
|
@@ -1510,6 +1673,16 @@ function updatePropGroup(ref, options) {
|
|
|
1510
1673
|
updatedPropGroup: {
|
|
1511
1674
|
id: found.group.id,
|
|
1512
1675
|
name: found.group.name,
|
|
1676
|
+
...(found.group.requiredProp
|
|
1677
|
+
? {
|
|
1678
|
+
requiredProp: found.group.requiredProp,
|
|
1679
|
+
...(found.group.requiredEnumOptionValue !== undefined
|
|
1680
|
+
? {
|
|
1681
|
+
requiredEnumOptionValue: found.group.requiredEnumOptionValue,
|
|
1682
|
+
}
|
|
1683
|
+
: { requiredPropValue: found.group.requiredPropValue ?? true }),
|
|
1684
|
+
}
|
|
1685
|
+
: {}),
|
|
1513
1686
|
},
|
|
1514
1687
|
}));
|
|
1515
1688
|
}
|
|
@@ -1762,6 +1935,9 @@ function updateEnum(options) {
|
|
|
1762
1935
|
}
|
|
1763
1936
|
enumType.enumOptions = enumOptions;
|
|
1764
1937
|
}
|
|
1938
|
+
// Stamp so the editor accepts this as newer than its own copy (it otherwise
|
|
1939
|
+
// only adds unknown ids and would revert this edit on its next sync-types).
|
|
1940
|
+
enumType.updatedAt = Date.now();
|
|
1765
1941
|
saveConfig(configPath, config);
|
|
1766
1942
|
// Regenerate global types and all component types
|
|
1767
1943
|
regenerateGlobalTypes(config);
|
|
@@ -1859,6 +2035,9 @@ export function createConfigCommand() {
|
|
|
1859
2035
|
.option("--filteredComponentIds <json>", "JSON array of component IDs to restrict selection (for COMPONENT/COMPONENT_LIST)")
|
|
1860
2036
|
.option("--privateVarMap <json>", "JSON object mapping variable keys to {id, typeId} (for COMPONENT/COMPONENT_LIST)")
|
|
1861
2037
|
.option("--numberRangeData <json>", 'JSON slider config for NUMBER_RANGE props, e.g. \'{"min":0,"max":100,"interval":5,"unit":"px"}\'')
|
|
2038
|
+
.option("--requiredProp <propName>", 'Show this only while the named BOOLEAN or ENUM prop satisfies the condition ("Koşullu Prop")')
|
|
2039
|
+
.option("--requiredPropValue <boolean>", "For a BOOLEAN --requiredProp: which state shows it, true (default) or false")
|
|
2040
|
+
.option("--requiredEnumOptionValue <value>", "For an ENUM --requiredProp: the option value that shows it")
|
|
1862
2041
|
.action((options) => {
|
|
1863
2042
|
addProp({ id: options.componentId, name: options.component }, options);
|
|
1864
2043
|
});
|
|
@@ -1879,6 +2058,9 @@ export function createConfigCommand() {
|
|
|
1879
2058
|
.option("--filteredComponentIds <json>", "JSON array of component IDs (use 'none' to clear)")
|
|
1880
2059
|
.option("--privateVarMap <json>", "JSON object mapping variable keys to {id, typeId} (use 'none' to clear)")
|
|
1881
2060
|
.option("--numberRangeData <json>", "JSON slider config for NUMBER_RANGE props (use 'none' to clear)")
|
|
2061
|
+
.option("--requiredProp <propName>", "BOOLEAN or ENUM prop that gates this prop in the editor panel (use 'none' to clear)")
|
|
2062
|
+
.option("--requiredPropValue <boolean>", "For a BOOLEAN --requiredProp: which state shows it, true (default) or false")
|
|
2063
|
+
.option("--requiredEnumOptionValue <value>", "For an ENUM --requiredProp: the option value that shows it")
|
|
1882
2064
|
.action((options) => {
|
|
1883
2065
|
updateProp({ id: options.componentId, name: options.component }, options);
|
|
1884
2066
|
});
|
|
@@ -1920,6 +2102,9 @@ export function createConfigCommand() {
|
|
|
1920
2102
|
.requiredOption("--name <name>", "Display name in editor")
|
|
1921
2103
|
.option("--description <description>", "Group description")
|
|
1922
2104
|
.option("--parent <parentId>", "Parent group ID (for nesting, max 1 level)")
|
|
2105
|
+
.option("--requiredProp <propName>", 'Show this only while the named BOOLEAN or ENUM prop satisfies the condition ("Koşullu Prop")')
|
|
2106
|
+
.option("--requiredPropValue <boolean>", "For a BOOLEAN --requiredProp: which state shows it, true (default) or false")
|
|
2107
|
+
.option("--requiredEnumOptionValue <value>", "For an ENUM --requiredProp: the option value that shows it")
|
|
1923
2108
|
.action((options) => {
|
|
1924
2109
|
addPropGroup({ id: options.componentId, name: options.component }, options);
|
|
1925
2110
|
});
|
|
@@ -1931,6 +2116,9 @@ export function createConfigCommand() {
|
|
|
1931
2116
|
.requiredOption("--id <id>", "Group ID to update")
|
|
1932
2117
|
.option("--name <name>", "New display name")
|
|
1933
2118
|
.option("--description <description>", "New description")
|
|
2119
|
+
.option("--requiredProp <propName>", "BOOLEAN or ENUM prop that gates this group in the editor panel (use 'none' to clear)")
|
|
2120
|
+
.option("--requiredPropValue <boolean>", "For a BOOLEAN --requiredProp: which state shows it, true (default) or false")
|
|
2121
|
+
.option("--requiredEnumOptionValue <value>", "For an ENUM --requiredProp: the option value that shows it")
|
|
1934
2122
|
.action((options) => {
|
|
1935
2123
|
updatePropGroup({ id: options.componentId, name: options.component }, options);
|
|
1936
2124
|
});
|