@@ -2,13 +2,15 @@ import type {
22 SpaceComponent ,
33 SpaceComponentGroup ,
44 SpaceComponentInternalTag ,
5+ SpaceComponentPreset ,
56} from '../../constants' ;
67import type { DependencyGraph , GraphBuildingContext , NodeData , NodeType , SchemaDependencies , TargetResourceInfo , UnifiedNode } from './types' ;
7- import { upsertComponent , upsertComponentGroup , upsertComponentInternalTag } from '../actions' ;
8+ import { upsertComponent , upsertComponentGroup , upsertComponentInternalTag , upsertComponentPreset } from '../actions' ;
89import {
910 generateContentHash ,
1011 normalizeComponentForComparison ,
1112 normalizeGroupForComparison ,
13+ normalizePresetForComparison ,
1214 normalizeTagForComparison ,
1315} from './comparison-utils' ;
1416
@@ -61,6 +63,21 @@ export function buildDependencyGraph(context: GraphBuildingContext): DependencyG
6163 graph . nodes . set ( nodeId , node ) ;
6264 } ) ;
6365
66+ // Create nodes for all presets with colocated target data
67+ spaceState . local . presets . forEach ( ( preset ) => {
68+ const nodeId = `preset:${ preset . name } ` ;
69+ const targetPreset = spaceState . target . presets . get ( preset . name ) ;
70+ const targetData = targetPreset
71+ ? {
72+ resource : targetPreset ,
73+ id : targetPreset . id ,
74+ hash : generateContentHash ( normalizePresetForComparison ( preset ) ) ,
75+ }
76+ : undefined ;
77+ const node = new PresetNode ( preset , targetData ) ;
78+ graph . nodes . set ( nodeId , node ) ;
79+ } ) ;
80+
6481 // Add group parent dependencies
6582 spaceState . local . groups . forEach ( ( group ) => {
6683 if ( group . parent_uuid ) {
@@ -111,6 +128,18 @@ export function buildDependencyGraph(context: GraphBuildingContext): DependencyG
111128 }
112129 } ) ;
113130
131+ // Add preset dependencies on components
132+ spaceState . local . presets . forEach ( ( preset ) => {
133+ const presetId = `preset:${ preset . name } ` ;
134+
135+ // Find the component this preset belongs to
136+ const component = spaceState . local . components . find ( c => c . id === preset . component_id ) ;
137+ if ( component ) {
138+ const componentId = `component:${ component . name } ` ;
139+ addDependency ( presetId , componentId ) ;
140+ }
141+ } ) ;
142+
114143 return graph ;
115144}
116145
@@ -589,3 +618,77 @@ export class ComponentNode extends GraphNode<SpaceComponent> {
589618 return result ;
590619 }
591620}
621+
622+ /**
623+ * Preset node implementation
624+ * Presets depend on components (via component_id)
625+ */
626+ class PresetNode implements UnifiedNode < SpaceComponentPreset > {
627+ public readonly id : string ;
628+ public readonly name : string ;
629+ public readonly type : NodeType = 'preset' ;
630+ public readonly sourceData : SpaceComponentPreset ;
631+ public targetData ?: TargetResourceInfo < SpaceComponentPreset > ;
632+ public readonly dependencies = new Set < string > ( ) ;
633+ public readonly dependents = new Set < string > ( ) ;
634+
635+ constructor ( preset : SpaceComponentPreset , targetData ?: TargetResourceInfo < SpaceComponentPreset > ) {
636+ this . sourceData = preset ;
637+ this . targetData = targetData ;
638+ this . id = `preset:${ preset . name } ` ;
639+ this . name = preset . name ;
640+ }
641+
642+ getName ( ) : string {
643+ return this . name ;
644+ }
645+
646+ normalize ( ) : any {
647+ return normalizePresetForComparison ( this . sourceData ) ;
648+ }
649+
650+ shouldSkip ( ) : boolean {
651+ if ( ! this . targetData ) { return false ; }
652+
653+ const sourceHash = generateContentHash ( this . normalize ( ) ) ;
654+ return sourceHash === this . targetData . hash ;
655+ }
656+
657+ resolveReferences ( graph : DependencyGraph ) : void {
658+ // Find the component this preset belongs to and update component_id
659+ const componentName = this . findComponentNameById ( this . sourceData . component_id , graph ) ;
660+ if ( componentName ) {
661+ const componentNode = graph . nodes . get ( `component:${ componentName } ` ) ;
662+ if ( componentNode ?. targetData ) {
663+ this . sourceData . component_id = componentNode . targetData . id as number ;
664+ }
665+ }
666+ }
667+
668+ private findComponentNameById ( componentId : number , graph : DependencyGraph ) : string | null {
669+ // Find component by matching source component_id
670+ for ( const [ _nodeId , node ] of graph . nodes ) {
671+ if ( node . type === 'component' && ( node . sourceData as SpaceComponent ) . id === componentId ) {
672+ return node . name ;
673+ }
674+ }
675+ return null ;
676+ }
677+
678+ async upsert ( space : string ) : Promise < SpaceComponentPreset > {
679+ const existingId = this . targetData ?. id as number | undefined ;
680+ const result = await upsertComponentPreset ( space , this . sourceData , existingId ) ;
681+ if ( ! result ) {
682+ throw new Error ( `Failed to upsert preset: ${ this . name } ` ) ;
683+ }
684+ return result ;
685+ }
686+
687+ updateTargetData ( result : SpaceComponentPreset ) : void {
688+ this . targetData = {
689+ resource : result ,
690+ id : result . id ,
691+ hash : generateContentHash ( this . normalize ( ) ) ,
692+ } ;
693+ }
694+ }
0 commit comments