@uniformdev/transformer 1.0.0 → 1.1.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/cli/index.js +858 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +64 -1
- package/dist/index.js +472 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/cli/index.ts
|
|
4
|
-
import { Command as
|
|
4
|
+
import { Command as Command10 } from "commander";
|
|
5
5
|
|
|
6
6
|
// src/cli/commands/propagate-root-component-property.ts
|
|
7
7
|
import { Command } from "commander";
|
|
@@ -324,6 +324,34 @@ var ComponentService = class {
|
|
|
324
324
|
});
|
|
325
325
|
return component;
|
|
326
326
|
}
|
|
327
|
+
// Slot methods
|
|
328
|
+
findSlot(component, slotId, options = {}) {
|
|
329
|
+
const { strict = false } = options;
|
|
330
|
+
return component.slots?.find((s) => this.compareIds(s.id, slotId, strict));
|
|
331
|
+
}
|
|
332
|
+
addSlot(component, slot) {
|
|
333
|
+
if (!component.slots) {
|
|
334
|
+
component.slots = [];
|
|
335
|
+
}
|
|
336
|
+
component.slots.push({ ...slot });
|
|
337
|
+
return component;
|
|
338
|
+
}
|
|
339
|
+
updateSlotAllowedComponents(component, slotId, allowedComponents, options = {}) {
|
|
340
|
+
const { strict = false } = options;
|
|
341
|
+
const slot = component.slots?.find((s) => this.compareIds(s.id, slotId, strict));
|
|
342
|
+
if (slot) {
|
|
343
|
+
slot.allowedComponents = allowedComponents;
|
|
344
|
+
}
|
|
345
|
+
return component;
|
|
346
|
+
}
|
|
347
|
+
removeSlot(component, slotId, options = {}) {
|
|
348
|
+
const { strict = false } = options;
|
|
349
|
+
if (!component.slots) {
|
|
350
|
+
return component;
|
|
351
|
+
}
|
|
352
|
+
component.slots = component.slots.filter((s) => !this.compareIds(s.id, slotId, strict));
|
|
353
|
+
return component;
|
|
354
|
+
}
|
|
327
355
|
};
|
|
328
356
|
|
|
329
357
|
// src/core/services/composition.service.ts
|
|
@@ -1417,11 +1445,11 @@ var PatternAnalyzerService = class {
|
|
|
1417
1445
|
return str.length;
|
|
1418
1446
|
}
|
|
1419
1447
|
formatJsonOutput(result) {
|
|
1420
|
-
const cleanedPatterns = result.patterns.map(({ fingerprint, ...pattern }) => ({
|
|
1448
|
+
const cleanedPatterns = result.patterns.map(({ fingerprint: _fingerprint, ...pattern }) => ({
|
|
1421
1449
|
...pattern,
|
|
1422
|
-
compositions: pattern.compositions.map(({ filePath, ...comp }) => comp)
|
|
1450
|
+
compositions: pattern.compositions.map(({ filePath: _filePath, ...comp }) => comp)
|
|
1423
1451
|
}));
|
|
1424
|
-
const cleanedUniqueCompositions = result.uniqueCompositions.map(({ filePath, ...comp }) => comp);
|
|
1452
|
+
const cleanedUniqueCompositions = result.uniqueCompositions.map(({ filePath: _filePath, ...comp }) => comp);
|
|
1425
1453
|
return JSON.stringify(
|
|
1426
1454
|
{
|
|
1427
1455
|
summary: result.summary,
|
|
@@ -2377,8 +2405,830 @@ function createRenameComponentCommand() {
|
|
|
2377
2405
|
return command;
|
|
2378
2406
|
}
|
|
2379
2407
|
|
|
2408
|
+
// src/cli/commands/add-component.ts
|
|
2409
|
+
import { Command as Command7 } from "commander";
|
|
2410
|
+
|
|
2411
|
+
// src/core/services/component-adder.service.ts
|
|
2412
|
+
import { randomUUID } from "crypto";
|
|
2413
|
+
var ComponentAdderService = class {
|
|
2414
|
+
constructor(fileSystem, componentService, logger) {
|
|
2415
|
+
this.fileSystem = fileSystem;
|
|
2416
|
+
this.componentService = componentService;
|
|
2417
|
+
this.logger = logger;
|
|
2418
|
+
}
|
|
2419
|
+
compareIds(id1, id2, strict) {
|
|
2420
|
+
if (strict) {
|
|
2421
|
+
return id1 === id2;
|
|
2422
|
+
}
|
|
2423
|
+
return id1.toLowerCase() === id2.toLowerCase();
|
|
2424
|
+
}
|
|
2425
|
+
parseParameters(parameterString) {
|
|
2426
|
+
const result = {};
|
|
2427
|
+
if (!parameterString) return result;
|
|
2428
|
+
const pairs = parameterString.split("|");
|
|
2429
|
+
for (const pair of pairs) {
|
|
2430
|
+
const [key, ...valueParts] = pair.split(":");
|
|
2431
|
+
if (key && valueParts.length > 0) {
|
|
2432
|
+
result[key.trim()] = valueParts.join(":").trim();
|
|
2433
|
+
}
|
|
2434
|
+
}
|
|
2435
|
+
return result;
|
|
2436
|
+
}
|
|
2437
|
+
generateId(baseName) {
|
|
2438
|
+
return `${baseName}-${randomUUID().slice(0, 8)}`;
|
|
2439
|
+
}
|
|
2440
|
+
cloneComponentInstance(instance) {
|
|
2441
|
+
const clone = JSON.parse(JSON.stringify(instance));
|
|
2442
|
+
if (clone._id) {
|
|
2443
|
+
clone._id = this.generateId(clone.type);
|
|
2444
|
+
}
|
|
2445
|
+
if (clone.slots) {
|
|
2446
|
+
for (const slotInstances of Object.values(clone.slots)) {
|
|
2447
|
+
if (Array.isArray(slotInstances)) {
|
|
2448
|
+
for (const nestedInstance of slotInstances) {
|
|
2449
|
+
this.regenerateInstanceIds(nestedInstance);
|
|
2450
|
+
}
|
|
2451
|
+
}
|
|
2452
|
+
}
|
|
2453
|
+
}
|
|
2454
|
+
return clone;
|
|
2455
|
+
}
|
|
2456
|
+
regenerateInstanceIds(instance) {
|
|
2457
|
+
if (instance._id) {
|
|
2458
|
+
instance._id = this.generateId(instance.type);
|
|
2459
|
+
}
|
|
2460
|
+
if (instance.slots) {
|
|
2461
|
+
for (const slotInstances of Object.values(instance.slots)) {
|
|
2462
|
+
if (Array.isArray(slotInstances)) {
|
|
2463
|
+
for (const nestedInstance of slotInstances) {
|
|
2464
|
+
this.regenerateInstanceIds(nestedInstance);
|
|
2465
|
+
}
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2468
|
+
}
|
|
2469
|
+
}
|
|
2470
|
+
createComponentInstance(componentType, parameters) {
|
|
2471
|
+
const instance = {
|
|
2472
|
+
type: componentType,
|
|
2473
|
+
_id: this.generateId(componentType)
|
|
2474
|
+
};
|
|
2475
|
+
if (Object.keys(parameters).length > 0) {
|
|
2476
|
+
instance.parameters = {};
|
|
2477
|
+
for (const [key, value] of Object.entries(parameters)) {
|
|
2478
|
+
instance.parameters[key] = {
|
|
2479
|
+
type: "text",
|
|
2480
|
+
value
|
|
2481
|
+
};
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
return instance;
|
|
2485
|
+
}
|
|
2486
|
+
addComponentToSlot(slots, slotId, instance) {
|
|
2487
|
+
if (!slots[slotId]) {
|
|
2488
|
+
slots[slotId] = [];
|
|
2489
|
+
}
|
|
2490
|
+
slots[slotId].push(instance);
|
|
2491
|
+
}
|
|
2492
|
+
async addComponent(options) {
|
|
2493
|
+
const {
|
|
2494
|
+
rootDir,
|
|
2495
|
+
componentsDir,
|
|
2496
|
+
compositionsDir,
|
|
2497
|
+
compositionPatternsDir,
|
|
2498
|
+
componentPatternsDir,
|
|
2499
|
+
parentComponentType,
|
|
2500
|
+
slot,
|
|
2501
|
+
newComponentType,
|
|
2502
|
+
parameters: paramString,
|
|
2503
|
+
whatIf,
|
|
2504
|
+
strict
|
|
2505
|
+
} = options;
|
|
2506
|
+
if (!newComponentType) {
|
|
2507
|
+
throw new TransformError("newComponentType is required for add-component");
|
|
2508
|
+
}
|
|
2509
|
+
const fullComponentsDir = this.fileSystem.resolvePath(rootDir, componentsDir);
|
|
2510
|
+
const fullCompositionsDir = this.fileSystem.resolvePath(rootDir, compositionsDir);
|
|
2511
|
+
const fullCompositionPatternsDir = this.fileSystem.resolvePath(rootDir, compositionPatternsDir);
|
|
2512
|
+
const fullComponentPatternsDir = this.fileSystem.resolvePath(rootDir, componentPatternsDir);
|
|
2513
|
+
const findOptions = { strict };
|
|
2514
|
+
this.logger.info(`Loading parent component: ${parentComponentType}`);
|
|
2515
|
+
const { component: parentComponent, filePath: parentComponentFilePath } = await this.componentService.loadComponent(fullComponentsDir, parentComponentType, findOptions);
|
|
2516
|
+
if (!parentComponent.slots) {
|
|
2517
|
+
parentComponent.slots = [];
|
|
2518
|
+
}
|
|
2519
|
+
let slotDef = parentComponent.slots.find(
|
|
2520
|
+
(s) => this.compareIds(s.id, slot, strict)
|
|
2521
|
+
);
|
|
2522
|
+
if (!slotDef) {
|
|
2523
|
+
this.logger.info(`Slot "${slot}" not found on component "${parentComponentType}", creating it`);
|
|
2524
|
+
slotDef = { id: slot, name: slot, allowedComponents: [] };
|
|
2525
|
+
parentComponent.slots.push(slotDef);
|
|
2526
|
+
}
|
|
2527
|
+
this.logger.info(`Validating new component: ${newComponentType}`);
|
|
2528
|
+
try {
|
|
2529
|
+
await this.componentService.loadComponent(fullComponentsDir, newComponentType, findOptions);
|
|
2530
|
+
} catch (error) {
|
|
2531
|
+
if (error instanceof ComponentNotFoundError) {
|
|
2532
|
+
throw new TransformError(
|
|
2533
|
+
`Component type "${newComponentType}" not found in ${fullComponentsDir}`
|
|
2534
|
+
);
|
|
2535
|
+
}
|
|
2536
|
+
throw error;
|
|
2537
|
+
}
|
|
2538
|
+
let allowedComponentsUpdated = false;
|
|
2539
|
+
const slotIndex = parentComponent.slots?.findIndex(
|
|
2540
|
+
(s) => this.compareIds(s.id, slotDef.id, strict)
|
|
2541
|
+
);
|
|
2542
|
+
if (slotIndex !== void 0 && slotIndex >= 0) {
|
|
2543
|
+
const actualSlot = parentComponent.slots[slotIndex];
|
|
2544
|
+
if (!actualSlot.allowedComponents) {
|
|
2545
|
+
actualSlot.allowedComponents = [];
|
|
2546
|
+
}
|
|
2547
|
+
const isAlreadyAllowed = actualSlot.allowedComponents.some(
|
|
2548
|
+
(c) => this.compareIds(c, newComponentType, strict)
|
|
2549
|
+
);
|
|
2550
|
+
if (!isAlreadyAllowed) {
|
|
2551
|
+
this.logger.action(
|
|
2552
|
+
whatIf,
|
|
2553
|
+
"UPDATE",
|
|
2554
|
+
`Adding "${newComponentType}" to allowedComponents for slot "${slot}" on component "${parentComponentType}"`
|
|
2555
|
+
);
|
|
2556
|
+
actualSlot.allowedComponents.push(newComponentType);
|
|
2557
|
+
if (!whatIf) {
|
|
2558
|
+
await this.componentService.saveComponent(parentComponentFilePath, parentComponent);
|
|
2559
|
+
}
|
|
2560
|
+
allowedComponentsUpdated = true;
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
const parsedParams = this.parseParameters(paramString);
|
|
2564
|
+
const newInstance = this.createComponentInstance(newComponentType, parsedParams);
|
|
2565
|
+
const compositionsResult = await this.addComponentToDirectory(
|
|
2566
|
+
fullCompositionsDir,
|
|
2567
|
+
parentComponentType,
|
|
2568
|
+
slot,
|
|
2569
|
+
newInstance,
|
|
2570
|
+
whatIf,
|
|
2571
|
+
strict,
|
|
2572
|
+
"composition"
|
|
2573
|
+
);
|
|
2574
|
+
const compositionPatternsResult = await this.addComponentToDirectory(
|
|
2575
|
+
fullCompositionPatternsDir,
|
|
2576
|
+
parentComponentType,
|
|
2577
|
+
slot,
|
|
2578
|
+
newInstance,
|
|
2579
|
+
whatIf,
|
|
2580
|
+
strict,
|
|
2581
|
+
"compositionPattern"
|
|
2582
|
+
);
|
|
2583
|
+
const componentPatternsResult = await this.addComponentToDirectory(
|
|
2584
|
+
fullComponentPatternsDir,
|
|
2585
|
+
parentComponentType,
|
|
2586
|
+
slot,
|
|
2587
|
+
newInstance,
|
|
2588
|
+
whatIf,
|
|
2589
|
+
strict,
|
|
2590
|
+
"componentPattern"
|
|
2591
|
+
);
|
|
2592
|
+
this.logger.info("");
|
|
2593
|
+
this.logger.info(
|
|
2594
|
+
`Summary: ${allowedComponentsUpdated ? "1 component definition updated, " : ""}${compositionsResult} composition(s), ${compositionPatternsResult} composition pattern(s), ${componentPatternsResult} component pattern(s) updated. ${compositionsResult + compositionPatternsResult + componentPatternsResult} instance(s) added.`
|
|
2595
|
+
);
|
|
2596
|
+
return {
|
|
2597
|
+
allowedComponentsUpdated,
|
|
2598
|
+
compositionsModified: compositionsResult,
|
|
2599
|
+
compositionPatternsModified: compositionPatternsResult,
|
|
2600
|
+
componentPatternsModified: componentPatternsResult,
|
|
2601
|
+
instancesAdded: compositionsResult + compositionPatternsResult + componentPatternsResult
|
|
2602
|
+
};
|
|
2603
|
+
}
|
|
2604
|
+
async addComponentPattern(options) {
|
|
2605
|
+
const {
|
|
2606
|
+
rootDir,
|
|
2607
|
+
componentsDir,
|
|
2608
|
+
compositionsDir,
|
|
2609
|
+
compositionPatternsDir,
|
|
2610
|
+
componentPatternsDir,
|
|
2611
|
+
parentComponentType,
|
|
2612
|
+
slot,
|
|
2613
|
+
componentPatternId,
|
|
2614
|
+
whatIf,
|
|
2615
|
+
strict
|
|
2616
|
+
} = options;
|
|
2617
|
+
if (!componentPatternId) {
|
|
2618
|
+
throw new TransformError("componentPatternId is required for add-component-pattern");
|
|
2619
|
+
}
|
|
2620
|
+
const fullComponentsDir = this.fileSystem.resolvePath(rootDir, componentsDir);
|
|
2621
|
+
const fullCompositionsDir = this.fileSystem.resolvePath(rootDir, compositionsDir);
|
|
2622
|
+
const fullCompositionPatternsDir = this.fileSystem.resolvePath(rootDir, compositionPatternsDir);
|
|
2623
|
+
const fullComponentPatternsDir = this.fileSystem.resolvePath(rootDir, componentPatternsDir);
|
|
2624
|
+
const findOptions = { strict };
|
|
2625
|
+
this.logger.info(`Loading parent component: ${parentComponentType}`);
|
|
2626
|
+
const { component: parentComponent } = await this.componentService.loadComponent(fullComponentsDir, parentComponentType, findOptions);
|
|
2627
|
+
if (!parentComponent.slots) {
|
|
2628
|
+
parentComponent.slots = [];
|
|
2629
|
+
}
|
|
2630
|
+
let slotDef = parentComponent.slots.find(
|
|
2631
|
+
(s) => this.compareIds(s.id, slot, strict)
|
|
2632
|
+
);
|
|
2633
|
+
if (!slotDef) {
|
|
2634
|
+
this.logger.info(`Slot "${slot}" not found on component "${parentComponentType}", creating it`);
|
|
2635
|
+
slotDef = { id: slot, name: slot, allowedComponents: [] };
|
|
2636
|
+
parentComponent.slots.push(slotDef);
|
|
2637
|
+
}
|
|
2638
|
+
this.logger.info(`Loading component pattern: ${componentPatternId}`);
|
|
2639
|
+
const pattern = await this.loadComponentPattern(
|
|
2640
|
+
fullComponentPatternsDir,
|
|
2641
|
+
componentPatternId,
|
|
2642
|
+
strict
|
|
2643
|
+
);
|
|
2644
|
+
const patternDefinition = pattern.definition;
|
|
2645
|
+
if (!patternDefinition || !patternDefinition.type) {
|
|
2646
|
+
throw new TransformError(
|
|
2647
|
+
`Component pattern "${componentPatternId}" has no valid definition or missing type`
|
|
2648
|
+
);
|
|
2649
|
+
}
|
|
2650
|
+
let allowedComponentsUpdated = false;
|
|
2651
|
+
const componentTypeInPattern = patternDefinition.type;
|
|
2652
|
+
const slotIndex = parentComponent.slots?.findIndex(
|
|
2653
|
+
(s) => this.compareIds(s.id, slotDef.id, strict)
|
|
2654
|
+
);
|
|
2655
|
+
if (slotIndex !== void 0 && slotIndex >= 0) {
|
|
2656
|
+
const actualSlot = parentComponent.slots[slotIndex];
|
|
2657
|
+
if (!actualSlot.allowedComponents) {
|
|
2658
|
+
actualSlot.allowedComponents = [];
|
|
2659
|
+
}
|
|
2660
|
+
const isAlreadyAllowed = actualSlot.allowedComponents.some(
|
|
2661
|
+
(c) => this.compareIds(c, componentTypeInPattern, strict)
|
|
2662
|
+
);
|
|
2663
|
+
if (!isAlreadyAllowed) {
|
|
2664
|
+
this.logger.action(
|
|
2665
|
+
whatIf,
|
|
2666
|
+
"UPDATE",
|
|
2667
|
+
`Adding "${componentTypeInPattern}" to allowedComponents for slot "${slot}" on component "${parentComponentType}"`
|
|
2668
|
+
);
|
|
2669
|
+
actualSlot.allowedComponents.push(componentTypeInPattern);
|
|
2670
|
+
if (!whatIf) {
|
|
2671
|
+
await this.componentService.loadComponent(fullComponentsDir, parentComponentType, findOptions).then(
|
|
2672
|
+
({ filePath }) => this.componentService.saveComponent(filePath, parentComponent)
|
|
2673
|
+
);
|
|
2674
|
+
}
|
|
2675
|
+
allowedComponentsUpdated = true;
|
|
2676
|
+
}
|
|
2677
|
+
}
|
|
2678
|
+
const newInstance = this.cloneComponentInstance(patternDefinition);
|
|
2679
|
+
const compositionsResult = await this.addComponentToDirectory(
|
|
2680
|
+
fullCompositionsDir,
|
|
2681
|
+
parentComponentType,
|
|
2682
|
+
slot,
|
|
2683
|
+
newInstance,
|
|
2684
|
+
whatIf,
|
|
2685
|
+
strict,
|
|
2686
|
+
"composition"
|
|
2687
|
+
);
|
|
2688
|
+
const compositionPatternsResult = await this.addComponentToDirectory(
|
|
2689
|
+
fullCompositionPatternsDir,
|
|
2690
|
+
parentComponentType,
|
|
2691
|
+
slot,
|
|
2692
|
+
newInstance,
|
|
2693
|
+
whatIf,
|
|
2694
|
+
strict,
|
|
2695
|
+
"compositionPattern"
|
|
2696
|
+
);
|
|
2697
|
+
const componentPatternsResult = await this.addComponentToDirectory(
|
|
2698
|
+
fullComponentPatternsDir,
|
|
2699
|
+
parentComponentType,
|
|
2700
|
+
slot,
|
|
2701
|
+
newInstance,
|
|
2702
|
+
whatIf,
|
|
2703
|
+
strict,
|
|
2704
|
+
"componentPattern"
|
|
2705
|
+
);
|
|
2706
|
+
this.logger.info("");
|
|
2707
|
+
this.logger.info(
|
|
2708
|
+
`Summary: ${allowedComponentsUpdated ? "1 component definition updated, " : ""}${compositionsResult} composition(s), ${compositionPatternsResult} composition pattern(s), ${componentPatternsResult} component pattern(s) updated. ${compositionsResult + compositionPatternsResult + componentPatternsResult} instance(s) added.`
|
|
2709
|
+
);
|
|
2710
|
+
return {
|
|
2711
|
+
allowedComponentsUpdated,
|
|
2712
|
+
compositionsModified: compositionsResult,
|
|
2713
|
+
compositionPatternsModified: compositionPatternsResult,
|
|
2714
|
+
componentPatternsModified: componentPatternsResult,
|
|
2715
|
+
instancesAdded: compositionsResult + compositionPatternsResult + componentPatternsResult
|
|
2716
|
+
};
|
|
2717
|
+
}
|
|
2718
|
+
async loadComponentPattern(componentPatternsDir, patternId, strict) {
|
|
2719
|
+
const jsonPath = this.fileSystem.joinPath(componentPatternsDir, `${patternId}.json`);
|
|
2720
|
+
const yamlPath = this.fileSystem.joinPath(componentPatternsDir, `${patternId}.yaml`);
|
|
2721
|
+
const ymlPath = this.fileSystem.joinPath(componentPatternsDir, `${patternId}.yml`);
|
|
2722
|
+
if (await this.fileSystem.fileExists(jsonPath)) {
|
|
2723
|
+
return this.fileSystem.readFile(jsonPath);
|
|
2724
|
+
}
|
|
2725
|
+
if (await this.fileSystem.fileExists(yamlPath)) {
|
|
2726
|
+
return this.fileSystem.readFile(yamlPath);
|
|
2727
|
+
}
|
|
2728
|
+
if (await this.fileSystem.fileExists(ymlPath)) {
|
|
2729
|
+
return this.fileSystem.readFile(ymlPath);
|
|
2730
|
+
}
|
|
2731
|
+
if (!strict) {
|
|
2732
|
+
const files = await this.fileSystem.findFiles(componentPatternsDir, "*.{json,yaml,yml}");
|
|
2733
|
+
for (const filePath of files) {
|
|
2734
|
+
const basename2 = this.fileSystem.getBasename(filePath);
|
|
2735
|
+
const nameWithoutExt = basename2.replace(/\.(json|yaml|yml)$/i, "");
|
|
2736
|
+
if (nameWithoutExt.toLowerCase() === patternId.toLowerCase()) {
|
|
2737
|
+
return this.fileSystem.readFile(filePath);
|
|
2738
|
+
}
|
|
2739
|
+
}
|
|
2740
|
+
}
|
|
2741
|
+
throw new TransformError(`Component pattern "${patternId}" not found in ${componentPatternsDir}`);
|
|
2742
|
+
}
|
|
2743
|
+
async addComponentToDirectory(directory, parentComponentType, slot, newInstance, whatIf, strict, dirType) {
|
|
2744
|
+
const exists = await this.fileSystem.fileExists(directory);
|
|
2745
|
+
if (!exists) {
|
|
2746
|
+
this.logger.detail(`${dirType} directory does not exist, skipping`);
|
|
2747
|
+
return 0;
|
|
2748
|
+
}
|
|
2749
|
+
const files = await this.fileSystem.findFiles(directory, "**/*.{json,yaml,yml}");
|
|
2750
|
+
let filesModified = 0;
|
|
2751
|
+
for (const filePath of files) {
|
|
2752
|
+
try {
|
|
2753
|
+
const content = await this.fileSystem.readFile(filePath);
|
|
2754
|
+
let composition = null;
|
|
2755
|
+
let isComponentPattern = false;
|
|
2756
|
+
if (dirType === "componentPattern" && content && typeof content === "object" && "definition" in content) {
|
|
2757
|
+
isComponentPattern = true;
|
|
2758
|
+
const pattern = content;
|
|
2759
|
+
if (pattern.definition && pattern.definition.slots) {
|
|
2760
|
+
composition = {
|
|
2761
|
+
composition: {
|
|
2762
|
+
_id: "pattern-root",
|
|
2763
|
+
type: pattern.definition.type,
|
|
2764
|
+
slots: pattern.definition.slots
|
|
2765
|
+
}
|
|
2766
|
+
};
|
|
2767
|
+
}
|
|
2768
|
+
} else {
|
|
2769
|
+
composition = content;
|
|
2770
|
+
}
|
|
2771
|
+
if (!composition?.composition) {
|
|
2772
|
+
continue;
|
|
2773
|
+
}
|
|
2774
|
+
const rootInstance = composition.composition;
|
|
2775
|
+
let modified = false;
|
|
2776
|
+
if (this.compareIds(rootInstance.type, parentComponentType, strict)) {
|
|
2777
|
+
if (!rootInstance.slots) {
|
|
2778
|
+
rootInstance.slots = {};
|
|
2779
|
+
}
|
|
2780
|
+
const instanceCopy = JSON.parse(JSON.stringify(newInstance));
|
|
2781
|
+
this.regenerateInstanceIds(instanceCopy);
|
|
2782
|
+
this.addComponentToSlot(rootInstance.slots, slot, instanceCopy);
|
|
2783
|
+
modified = true;
|
|
2784
|
+
}
|
|
2785
|
+
if (rootInstance.slots) {
|
|
2786
|
+
const nestedModified = this.addComponentToNestedSlots(
|
|
2787
|
+
rootInstance.slots,
|
|
2788
|
+
parentComponentType,
|
|
2789
|
+
slot,
|
|
2790
|
+
newInstance,
|
|
2791
|
+
strict
|
|
2792
|
+
);
|
|
2793
|
+
if (nestedModified) {
|
|
2794
|
+
modified = true;
|
|
2795
|
+
}
|
|
2796
|
+
}
|
|
2797
|
+
if (modified) {
|
|
2798
|
+
this.logger.action(
|
|
2799
|
+
whatIf,
|
|
2800
|
+
"UPDATE",
|
|
2801
|
+
`Adding "${newInstance.type}" to slot "${slot}" in ${dirType}/${this.fileSystem.getBasename(filePath)}`
|
|
2802
|
+
);
|
|
2803
|
+
if (!whatIf) {
|
|
2804
|
+
if (isComponentPattern && content && typeof content === "object" && "definition" in content) {
|
|
2805
|
+
const pattern = content;
|
|
2806
|
+
if (rootInstance.slots) {
|
|
2807
|
+
pattern.definition.slots = rootInstance.slots;
|
|
2808
|
+
}
|
|
2809
|
+
}
|
|
2810
|
+
await this.fileSystem.writeFile(filePath, content);
|
|
2811
|
+
}
|
|
2812
|
+
filesModified++;
|
|
2813
|
+
}
|
|
2814
|
+
} catch (error) {
|
|
2815
|
+
if (error instanceof Error && !error.message.includes("skipping")) {
|
|
2816
|
+
this.logger.detail(`Skipping ${filePath}: ${error.message}`);
|
|
2817
|
+
}
|
|
2818
|
+
}
|
|
2819
|
+
}
|
|
2820
|
+
return filesModified;
|
|
2821
|
+
}
|
|
2822
|
+
addComponentToNestedSlots(slots, parentComponentType, slot, newInstance, strict) {
|
|
2823
|
+
let modified = false;
|
|
2824
|
+
for (const slotInstances of Object.values(slots)) {
|
|
2825
|
+
if (!Array.isArray(slotInstances)) continue;
|
|
2826
|
+
for (const instance of slotInstances) {
|
|
2827
|
+
if (this.compareIds(instance.type, parentComponentType, strict)) {
|
|
2828
|
+
if (!instance.slots) {
|
|
2829
|
+
instance.slots = {};
|
|
2830
|
+
}
|
|
2831
|
+
const instanceCopy = JSON.parse(JSON.stringify(newInstance));
|
|
2832
|
+
this.regenerateInstanceIds(instanceCopy);
|
|
2833
|
+
this.addComponentToSlot(instance.slots, slot, instanceCopy);
|
|
2834
|
+
modified = true;
|
|
2835
|
+
}
|
|
2836
|
+
if (instance.slots) {
|
|
2837
|
+
const nestedModified = this.addComponentToNestedSlots(
|
|
2838
|
+
instance.slots,
|
|
2839
|
+
parentComponentType,
|
|
2840
|
+
slot,
|
|
2841
|
+
newInstance,
|
|
2842
|
+
strict
|
|
2843
|
+
);
|
|
2844
|
+
if (nestedModified) {
|
|
2845
|
+
modified = true;
|
|
2846
|
+
}
|
|
2847
|
+
}
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2850
|
+
return modified;
|
|
2851
|
+
}
|
|
2852
|
+
};
|
|
2853
|
+
|
|
2854
|
+
// src/cli/commands/add-component.ts
|
|
2855
|
+
function createAddComponentCommand() {
|
|
2856
|
+
const command = new Command7("add-component");
|
|
2857
|
+
command.description("Adds a component instance to existing component slots across all compositions.").option("--parentComponentType <type>", "The component type that owns the slot").option("--slot <slotId>", "The slot ID where the component will be added").option("--newComponentType <type>", "The component type to add").option("--parameters <params>", "Pipe-separated parameter assignments (key1:value1|key2:value2)").hook("preAction", (thisCommand) => {
|
|
2858
|
+
const opts = thisCommand.opts();
|
|
2859
|
+
const requiredOptions = [
|
|
2860
|
+
{ name: "parentComponentType", flag: "--parentComponentType" },
|
|
2861
|
+
{ name: "slot", flag: "--slot" },
|
|
2862
|
+
{ name: "newComponentType", flag: "--newComponentType" }
|
|
2863
|
+
];
|
|
2864
|
+
const missing = requiredOptions.filter((opt) => !opts[opt.name]).map((opt) => opt.flag);
|
|
2865
|
+
if (missing.length > 0) {
|
|
2866
|
+
console.error(`error: missing required options: ${missing.join(", ")}`);
|
|
2867
|
+
process.exit(1);
|
|
2868
|
+
}
|
|
2869
|
+
}).action(async (opts, cmd) => {
|
|
2870
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
2871
|
+
const options = {
|
|
2872
|
+
...globalOpts,
|
|
2873
|
+
parentComponentType: opts.parentComponentType,
|
|
2874
|
+
slot: opts.slot,
|
|
2875
|
+
newComponentType: opts.newComponentType,
|
|
2876
|
+
parameters: opts.parameters
|
|
2877
|
+
};
|
|
2878
|
+
const logger = new Logger();
|
|
2879
|
+
const fileSystem = new FileSystemService();
|
|
2880
|
+
const componentService = new ComponentService(fileSystem);
|
|
2881
|
+
const adder = new ComponentAdderService(fileSystem, componentService, logger);
|
|
2882
|
+
try {
|
|
2883
|
+
const result = await adder.addComponent({
|
|
2884
|
+
rootDir: options.rootDir,
|
|
2885
|
+
componentsDir: options.componentsDir,
|
|
2886
|
+
compositionsDir: options.compositionsDir,
|
|
2887
|
+
compositionPatternsDir: options.compositionPatternsDir,
|
|
2888
|
+
componentPatternsDir: options.componentPatternsDir,
|
|
2889
|
+
parentComponentType: options.parentComponentType,
|
|
2890
|
+
slot: options.slot,
|
|
2891
|
+
newComponentType: options.newComponentType,
|
|
2892
|
+
parameters: options.parameters,
|
|
2893
|
+
whatIf: options.whatIf ?? false,
|
|
2894
|
+
strict: options.strict ?? false
|
|
2895
|
+
});
|
|
2896
|
+
logger.success(
|
|
2897
|
+
`Added component: ${result.allowedComponentsUpdated ? "1 component definition updated, " : ""}${result.instancesAdded} instance(s) added across ${result.compositionsModified} composition(s), ${result.compositionPatternsModified} composition pattern(s), ${result.componentPatternsModified} component pattern(s)`
|
|
2898
|
+
);
|
|
2899
|
+
} catch (error) {
|
|
2900
|
+
if (error instanceof TransformError) {
|
|
2901
|
+
logger.error(error.message);
|
|
2902
|
+
process.exit(1);
|
|
2903
|
+
}
|
|
2904
|
+
throw error;
|
|
2905
|
+
}
|
|
2906
|
+
});
|
|
2907
|
+
return command;
|
|
2908
|
+
}
|
|
2909
|
+
|
|
2910
|
+
// src/cli/commands/add-component-pattern.ts
|
|
2911
|
+
import { Command as Command8 } from "commander";
|
|
2912
|
+
function createAddComponentPatternCommand() {
|
|
2913
|
+
const command = new Command8("add-component-pattern");
|
|
2914
|
+
command.description("Adds a component pattern instance to existing component slots across all compositions.").option("--parentComponentType <type>", "The component type that owns the slot").option("--slot <slotId>", "The slot ID where the component pattern will be added").option("--componentPatternId <id>", "The component pattern ID to add").option("--parameters <params>", "Pipe-separated parameter assignments (key1:value1|key2:value2)").hook("preAction", (thisCommand) => {
|
|
2915
|
+
const opts = thisCommand.opts();
|
|
2916
|
+
const requiredOptions = [
|
|
2917
|
+
{ name: "parentComponentType", flag: "--parentComponentType" },
|
|
2918
|
+
{ name: "slot", flag: "--slot" },
|
|
2919
|
+
{ name: "componentPatternId", flag: "--componentPatternId" }
|
|
2920
|
+
];
|
|
2921
|
+
const missing = requiredOptions.filter((opt) => !opts[opt.name]).map((opt) => opt.flag);
|
|
2922
|
+
if (missing.length > 0) {
|
|
2923
|
+
console.error(`error: missing required options: ${missing.join(", ")}`);
|
|
2924
|
+
process.exit(1);
|
|
2925
|
+
}
|
|
2926
|
+
}).action(async (opts, cmd) => {
|
|
2927
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
2928
|
+
const options = {
|
|
2929
|
+
...globalOpts,
|
|
2930
|
+
parentComponentType: opts.parentComponentType,
|
|
2931
|
+
slot: opts.slot,
|
|
2932
|
+
componentPatternId: opts.componentPatternId,
|
|
2933
|
+
parameters: opts.parameters
|
|
2934
|
+
};
|
|
2935
|
+
const logger = new Logger();
|
|
2936
|
+
const fileSystem = new FileSystemService();
|
|
2937
|
+
const componentService = new ComponentService(fileSystem);
|
|
2938
|
+
const adder = new ComponentAdderService(fileSystem, componentService, logger);
|
|
2939
|
+
try {
|
|
2940
|
+
const result = await adder.addComponentPattern({
|
|
2941
|
+
rootDir: options.rootDir,
|
|
2942
|
+
componentsDir: options.componentsDir,
|
|
2943
|
+
compositionsDir: options.compositionsDir,
|
|
2944
|
+
compositionPatternsDir: options.compositionPatternsDir,
|
|
2945
|
+
componentPatternsDir: options.componentPatternsDir,
|
|
2946
|
+
parentComponentType: options.parentComponentType,
|
|
2947
|
+
slot: options.slot,
|
|
2948
|
+
componentPatternId: options.componentPatternId,
|
|
2949
|
+
parameters: options.parameters,
|
|
2950
|
+
whatIf: options.whatIf ?? false,
|
|
2951
|
+
strict: options.strict ?? false
|
|
2952
|
+
});
|
|
2953
|
+
logger.success(
|
|
2954
|
+
`Added component pattern: ${result.allowedComponentsUpdated ? "1 component definition updated, " : ""}${result.instancesAdded} instance(s) added across ${result.compositionsModified} composition(s), ${result.compositionPatternsModified} composition pattern(s), ${result.componentPatternsModified} component pattern(s)`
|
|
2955
|
+
);
|
|
2956
|
+
} catch (error) {
|
|
2957
|
+
if (error instanceof TransformError) {
|
|
2958
|
+
logger.error(error.message);
|
|
2959
|
+
process.exit(1);
|
|
2960
|
+
}
|
|
2961
|
+
throw error;
|
|
2962
|
+
}
|
|
2963
|
+
});
|
|
2964
|
+
return command;
|
|
2965
|
+
}
|
|
2966
|
+
|
|
2967
|
+
// src/cli/commands/propagate-root-component-slot.ts
|
|
2968
|
+
import { Command as Command9 } from "commander";
|
|
2969
|
+
|
|
2970
|
+
// src/core/services/slot-propagator.service.ts
|
|
2971
|
+
var SlotPropagatorService = class {
|
|
2972
|
+
constructor(fileSystem, componentService, compositionService, logger) {
|
|
2973
|
+
this.fileSystem = fileSystem;
|
|
2974
|
+
this.componentService = componentService;
|
|
2975
|
+
this.compositionService = compositionService;
|
|
2976
|
+
this.logger = logger;
|
|
2977
|
+
}
|
|
2978
|
+
async propagate(options) {
|
|
2979
|
+
const {
|
|
2980
|
+
rootDir,
|
|
2981
|
+
componentsDir,
|
|
2982
|
+
compositionsDir,
|
|
2983
|
+
compositionType,
|
|
2984
|
+
slot,
|
|
2985
|
+
targetComponentType,
|
|
2986
|
+
targetSlot,
|
|
2987
|
+
whatIf,
|
|
2988
|
+
strict,
|
|
2989
|
+
deleteSourceSlot
|
|
2990
|
+
} = options;
|
|
2991
|
+
const findOptions = { strict };
|
|
2992
|
+
const fullComponentsDir = this.fileSystem.resolvePath(rootDir, componentsDir);
|
|
2993
|
+
const fullCompositionsDir = this.fileSystem.resolvePath(rootDir, compositionsDir);
|
|
2994
|
+
this.logger.info(`Loading component: ${compositionType}`);
|
|
2995
|
+
const { component: sourceComponent, filePath: sourceFilePath } = await this.componentService.loadComponent(fullComponentsDir, compositionType, findOptions);
|
|
2996
|
+
this.logger.info(`Loading component: ${targetComponentType}`);
|
|
2997
|
+
const { component: targetComponent, filePath: targetFilePath } = await this.componentService.loadComponent(fullComponentsDir, targetComponentType, findOptions);
|
|
2998
|
+
const slotNames = slot.split("|").map((s) => s.trim());
|
|
2999
|
+
const resolvedSlots = [];
|
|
3000
|
+
const notFound = [];
|
|
3001
|
+
for (const slotName of slotNames) {
|
|
3002
|
+
const slotDef = this.componentService.findSlot(sourceComponent, slotName, findOptions);
|
|
3003
|
+
if (slotDef) {
|
|
3004
|
+
resolvedSlots.push(slotDef);
|
|
3005
|
+
} else {
|
|
3006
|
+
notFound.push(slotName);
|
|
3007
|
+
}
|
|
3008
|
+
}
|
|
3009
|
+
if (notFound.length > 0) {
|
|
3010
|
+
throw new PropertyNotFoundError(`Slot "${notFound.join(", ")}"`, compositionType);
|
|
3011
|
+
}
|
|
3012
|
+
const resolvedSlotIds = resolvedSlots.map((s) => s.id);
|
|
3013
|
+
this.logger.info(`Resolved slots: ${resolvedSlotIds.join(", ")}`);
|
|
3014
|
+
let modifiedComponent = { ...targetComponent };
|
|
3015
|
+
let componentModified = false;
|
|
3016
|
+
const existingSlot = this.componentService.findSlot(modifiedComponent, targetSlot, findOptions);
|
|
3017
|
+
if (!existingSlot) {
|
|
3018
|
+
const mergedAllowedComponents = this.mergeAllowedComponents(resolvedSlots);
|
|
3019
|
+
this.logger.action(whatIf, "CREATE", `Slot "${targetSlot}" on ${targetComponentType}`);
|
|
3020
|
+
modifiedComponent = this.componentService.addSlot(modifiedComponent, {
|
|
3021
|
+
id: targetSlot,
|
|
3022
|
+
name: targetSlot,
|
|
3023
|
+
allowedComponents: mergedAllowedComponents
|
|
3024
|
+
});
|
|
3025
|
+
componentModified = true;
|
|
3026
|
+
} else {
|
|
3027
|
+
const mergedAllowedComponents = this.mergeAllowedComponents([existingSlot, ...resolvedSlots]);
|
|
3028
|
+
const existingAllowed = existingSlot.allowedComponents ?? [];
|
|
3029
|
+
if (mergedAllowedComponents.length > existingAllowed.length) {
|
|
3030
|
+
this.logger.action(
|
|
3031
|
+
whatIf,
|
|
3032
|
+
"UPDATE",
|
|
3033
|
+
`Slot "${targetSlot}" allowedComponents on ${targetComponentType}`
|
|
3034
|
+
);
|
|
3035
|
+
modifiedComponent = this.componentService.updateSlotAllowedComponents(
|
|
3036
|
+
modifiedComponent,
|
|
3037
|
+
targetSlot,
|
|
3038
|
+
mergedAllowedComponents,
|
|
3039
|
+
findOptions
|
|
3040
|
+
);
|
|
3041
|
+
componentModified = true;
|
|
3042
|
+
} else {
|
|
3043
|
+
this.logger.info(`Slot "${targetSlot}" already exists on ${targetComponentType}`);
|
|
3044
|
+
}
|
|
3045
|
+
}
|
|
3046
|
+
if (componentModified && !whatIf) {
|
|
3047
|
+
await this.componentService.saveComponent(targetFilePath, modifiedComponent);
|
|
3048
|
+
}
|
|
3049
|
+
const compositions = await this.compositionService.findCompositionsByType(
|
|
3050
|
+
fullCompositionsDir,
|
|
3051
|
+
compositionType,
|
|
3052
|
+
findOptions
|
|
3053
|
+
);
|
|
3054
|
+
let modifiedCompositions = 0;
|
|
3055
|
+
let propagatedInstances = 0;
|
|
3056
|
+
for (const { composition, filePath } of compositions) {
|
|
3057
|
+
const rootSlots = composition.composition.slots ?? {};
|
|
3058
|
+
const instances = this.compositionService.findComponentInstances(
|
|
3059
|
+
composition,
|
|
3060
|
+
targetComponentType,
|
|
3061
|
+
findOptions
|
|
3062
|
+
);
|
|
3063
|
+
if (instances.length === 0) {
|
|
3064
|
+
continue;
|
|
3065
|
+
}
|
|
3066
|
+
const componentsToPropagate = [];
|
|
3067
|
+
for (const slotDef of resolvedSlots) {
|
|
3068
|
+
const slotContent = rootSlots[slotDef.id] ?? [];
|
|
3069
|
+
componentsToPropagate.push(...slotContent);
|
|
3070
|
+
}
|
|
3071
|
+
if (componentsToPropagate.length === 0) {
|
|
3072
|
+
continue;
|
|
3073
|
+
}
|
|
3074
|
+
let compositionModified = false;
|
|
3075
|
+
const relativePath = filePath.replace(fullCompositionsDir, "").replace(/^[/\\]/, "");
|
|
3076
|
+
const instanceUpdates = [];
|
|
3077
|
+
for (const { instance, instanceId } of instances) {
|
|
3078
|
+
const instanceName = instance._id ?? instanceId;
|
|
3079
|
+
const clonedComponents = this.deepCloneComponents(componentsToPropagate);
|
|
3080
|
+
this.addComponentsToInstanceSlot(instance, targetSlot, clonedComponents);
|
|
3081
|
+
compositionModified = true;
|
|
3082
|
+
propagatedInstances++;
|
|
3083
|
+
instanceUpdates.push(
|
|
3084
|
+
`${targetComponentType} "${instanceName}": ${componentsToPropagate.length} component(s) \u2192 ${targetSlot}`
|
|
3085
|
+
);
|
|
3086
|
+
}
|
|
3087
|
+
if (compositionModified) {
|
|
3088
|
+
this.logger.action(whatIf, "UPDATE", `composition/${relativePath}`);
|
|
3089
|
+
for (const update of instanceUpdates) {
|
|
3090
|
+
this.logger.detail(`\u2192 ${update}`);
|
|
3091
|
+
}
|
|
3092
|
+
if (!whatIf) {
|
|
3093
|
+
await this.compositionService.saveComposition(filePath, composition);
|
|
3094
|
+
}
|
|
3095
|
+
modifiedCompositions++;
|
|
3096
|
+
}
|
|
3097
|
+
}
|
|
3098
|
+
let sourceComponentModified = false;
|
|
3099
|
+
if (deleteSourceSlot) {
|
|
3100
|
+
let modifiedSource = { ...sourceComponent };
|
|
3101
|
+
for (const slotDef of resolvedSlots) {
|
|
3102
|
+
this.logger.action(whatIf, "DELETE", `Slot "${slotDef.id}" from ${compositionType}`);
|
|
3103
|
+
modifiedSource = this.componentService.removeSlot(modifiedSource, slotDef.id, findOptions);
|
|
3104
|
+
sourceComponentModified = true;
|
|
3105
|
+
}
|
|
3106
|
+
if (sourceComponentModified && !whatIf) {
|
|
3107
|
+
await this.componentService.saveComponent(sourceFilePath, modifiedSource);
|
|
3108
|
+
}
|
|
3109
|
+
for (const { composition, filePath } of compositions) {
|
|
3110
|
+
const relativePath = filePath.replace(fullCompositionsDir, "").replace(/^[/\\]/, "");
|
|
3111
|
+
let cleared = false;
|
|
3112
|
+
for (const slotDef of resolvedSlots) {
|
|
3113
|
+
if (composition.composition.slots?.[slotDef.id]?.length) {
|
|
3114
|
+
composition.composition.slots[slotDef.id] = [];
|
|
3115
|
+
cleared = true;
|
|
3116
|
+
}
|
|
3117
|
+
}
|
|
3118
|
+
if (cleared) {
|
|
3119
|
+
this.logger.action(whatIf, "CLEAR", `Root slots in composition/${relativePath}`);
|
|
3120
|
+
this.logger.detail(`\u2192 Cleared: ${resolvedSlotIds.join(", ")}`);
|
|
3121
|
+
if (!whatIf) {
|
|
3122
|
+
await this.compositionService.saveComposition(filePath, composition);
|
|
3123
|
+
}
|
|
3124
|
+
}
|
|
3125
|
+
}
|
|
3126
|
+
}
|
|
3127
|
+
return {
|
|
3128
|
+
modifiedComponents: (componentModified ? 1 : 0) + (sourceComponentModified ? 1 : 0),
|
|
3129
|
+
modifiedCompositions,
|
|
3130
|
+
propagatedInstances
|
|
3131
|
+
};
|
|
3132
|
+
}
|
|
3133
|
+
mergeAllowedComponents(slots) {
|
|
3134
|
+
const allowed = /* @__PURE__ */ new Set();
|
|
3135
|
+
for (const slot of slots) {
|
|
3136
|
+
for (const comp of slot.allowedComponents ?? []) {
|
|
3137
|
+
allowed.add(comp);
|
|
3138
|
+
}
|
|
3139
|
+
}
|
|
3140
|
+
return Array.from(allowed).sort();
|
|
3141
|
+
}
|
|
3142
|
+
deepCloneComponents(components) {
|
|
3143
|
+
return JSON.parse(JSON.stringify(components));
|
|
3144
|
+
}
|
|
3145
|
+
addComponentsToInstanceSlot(instance, slotName, components) {
|
|
3146
|
+
if (!instance.slots) {
|
|
3147
|
+
instance.slots = {};
|
|
3148
|
+
}
|
|
3149
|
+
if (!instance.slots[slotName]) {
|
|
3150
|
+
instance.slots[slotName] = [];
|
|
3151
|
+
}
|
|
3152
|
+
instance.slots[slotName].push(...components);
|
|
3153
|
+
}
|
|
3154
|
+
};
|
|
3155
|
+
|
|
3156
|
+
// src/cli/commands/propagate-root-component-slot.ts
|
|
3157
|
+
function createPropagateRootComponentSlotCommand() {
|
|
3158
|
+
const command = new Command9("propagate-root-component-slot");
|
|
3159
|
+
command.description(
|
|
3160
|
+
"Copies slot definitions from a composition type's root component to a target component type, then moves all component instances from that slot across all matching compositions."
|
|
3161
|
+
).option("--compositionType <type>", "The composition type to process (e.g., HomePage)").option("--slot <slots>", "Pipe-separated list of slot names to copy from the source component").option(
|
|
3162
|
+
"--targetComponentType <type>",
|
|
3163
|
+
"The component type that will receive the copied slots"
|
|
3164
|
+
).option(
|
|
3165
|
+
"--targetSlot <slot>",
|
|
3166
|
+
"The slot name on the target component where the contents will be placed"
|
|
3167
|
+
).option(
|
|
3168
|
+
"--deleteSourceSlot",
|
|
3169
|
+
"Delete the original slots from the source component after propagation"
|
|
3170
|
+
).hook("preAction", (thisCommand) => {
|
|
3171
|
+
const opts = thisCommand.opts();
|
|
3172
|
+
const requiredOptions = [
|
|
3173
|
+
{ name: "compositionType", flag: "--compositionType" },
|
|
3174
|
+
{ name: "slot", flag: "--slot" },
|
|
3175
|
+
{ name: "targetComponentType", flag: "--targetComponentType" },
|
|
3176
|
+
{ name: "targetSlot", flag: "--targetSlot" }
|
|
3177
|
+
];
|
|
3178
|
+
const missing = requiredOptions.filter((opt) => !opts[opt.name]).map((opt) => opt.flag);
|
|
3179
|
+
if (missing.length > 0) {
|
|
3180
|
+
console.error(`error: missing required options: ${missing.join(", ")}`);
|
|
3181
|
+
process.exit(1);
|
|
3182
|
+
}
|
|
3183
|
+
}).action(async (opts, cmd) => {
|
|
3184
|
+
const globalOpts = cmd.optsWithGlobals();
|
|
3185
|
+
const options = {
|
|
3186
|
+
...globalOpts,
|
|
3187
|
+
compositionType: opts.compositionType,
|
|
3188
|
+
slot: opts.slot,
|
|
3189
|
+
targetComponentType: opts.targetComponentType,
|
|
3190
|
+
targetSlot: opts.targetSlot,
|
|
3191
|
+
deleteSourceSlot: opts.deleteSourceSlot
|
|
3192
|
+
};
|
|
3193
|
+
const logger = new Logger();
|
|
3194
|
+
const fileSystem = new FileSystemService();
|
|
3195
|
+
const componentService = new ComponentService(fileSystem);
|
|
3196
|
+
const compositionService = new CompositionService(fileSystem);
|
|
3197
|
+
const propagator = new SlotPropagatorService(
|
|
3198
|
+
fileSystem,
|
|
3199
|
+
componentService,
|
|
3200
|
+
compositionService,
|
|
3201
|
+
logger
|
|
3202
|
+
);
|
|
3203
|
+
try {
|
|
3204
|
+
const result = await propagator.propagate({
|
|
3205
|
+
rootDir: options.rootDir,
|
|
3206
|
+
componentsDir: options.componentsDir,
|
|
3207
|
+
compositionsDir: options.compositionsDir,
|
|
3208
|
+
compositionType: options.compositionType,
|
|
3209
|
+
slot: options.slot,
|
|
3210
|
+
targetComponentType: options.targetComponentType,
|
|
3211
|
+
targetSlot: options.targetSlot,
|
|
3212
|
+
whatIf: options.whatIf ?? false,
|
|
3213
|
+
strict: options.strict ?? false,
|
|
3214
|
+
deleteSourceSlot: options.deleteSourceSlot ?? false
|
|
3215
|
+
});
|
|
3216
|
+
logger.success(
|
|
3217
|
+
`Modified ${result.modifiedComponents} component(s), ${result.modifiedCompositions} composition(s)`
|
|
3218
|
+
);
|
|
3219
|
+
} catch (error) {
|
|
3220
|
+
if (error instanceof TransformError) {
|
|
3221
|
+
logger.error(error.message);
|
|
3222
|
+
process.exit(1);
|
|
3223
|
+
}
|
|
3224
|
+
throw error;
|
|
3225
|
+
}
|
|
3226
|
+
});
|
|
3227
|
+
return command;
|
|
3228
|
+
}
|
|
3229
|
+
|
|
2380
3230
|
// src/cli/index.ts
|
|
2381
|
-
var program = new
|
|
3231
|
+
var program = new Command10();
|
|
2382
3232
|
program.name("uniform-transform").description("CLI tool for transforming Uniform.dev serialization files offline").version("1.0.0");
|
|
2383
3233
|
program.requiredOption("--rootDir <path>", "Path to the serialization project root").option("--what-if", "Dry run mode - preview changes without modifying files", false).option("--strict", "Enable strict mode for case-sensitive matching", false).option("--compositionsDir <dir>", "Compositions directory name", "composition").option("--componentsDir <dir>", "Components directory name", "component").option("--contentTypesDir <dir>", "Content types directory name", "contentType").option("--assetsDir <dir>", "Assets directory name", "asset").option("--categoriesDir <dir>", "Categories directory name", "category").option("--componentPatternsDir <dir>", "Component patterns directory name", "componentPattern").option(
|
|
2384
3234
|
"--compositionPatternsDir <dir>",
|
|
@@ -2395,5 +3245,8 @@ program.addCommand(createUnpackSerializationCommand());
|
|
|
2395
3245
|
program.addCommand(createPackSerializationCommand());
|
|
2396
3246
|
program.addCommand(createRenameSlotCommand());
|
|
2397
3247
|
program.addCommand(createRenameComponentCommand());
|
|
3248
|
+
program.addCommand(createAddComponentCommand());
|
|
3249
|
+
program.addCommand(createAddComponentPatternCommand());
|
|
3250
|
+
program.addCommand(createPropagateRootComponentSlotCommand());
|
|
2398
3251
|
program.parse();
|
|
2399
3252
|
//# sourceMappingURL=index.js.map
|