@@ -10,19 +10,35 @@ import (
1010 "github.com/stainless-api/stainless-api-go"
1111)
1212
13+ // Resolve converts a path to absolute, resolving it relative to baseDir if it's not already absolute
14+ func Resolve (baseDir , path string ) string {
15+ if filepath .IsAbs (path ) {
16+ return filepath .Clean (path )
17+ }
18+ return filepath .Clean (filepath .Join (baseDir , path ))
19+ }
20+
1321// TargetConfig stores configuration for a specific SDK target
1422type TargetConfig struct {
1523 OutputPath string `json:"output_path"`
1624}
1725
18- // WorkspaceConfig stores workspace-level configuration
19- type WorkspaceConfig struct {
20- Project string `json:"project"`
21- OpenAPISpec string `json:"openapi_spec,omitempty"`
22- StainlessConfig string `json:"stainless_config,omitempty"`
26+ // WorkspaceConfigExport represents the on-disk format with relative paths
27+ type WorkspaceConfigExport struct {
28+ Project string `json:"project"`
29+ OpenAPISpec string `json:"openapi_spec,omitempty"`
30+ StainlessConfig string `json:"stainless_config,omitempty"`
2331 Targets map [stainless.Target ]* TargetConfig `json:"targets,omitempty"`
32+ }
2433
25- ConfigPath string `json:"-"`
34+ // WorkspaceConfig stores workspace-level configuration with absolute paths
35+ type WorkspaceConfig struct {
36+ Project string
37+ OpenAPISpec string
38+ StainlessConfig string
39+ Targets map [stainless.Target ]* TargetConfig
40+
41+ ConfigPath string
2642}
2743
2844// Find searches for a stainless-workspace.json file starting from the current directory
@@ -82,20 +98,84 @@ func (config *WorkspaceConfig) Load(configPath string) error {
8298 return nil
8399 }
84100
85- if err := json .NewDecoder (file ).Decode (config ); err != nil {
101+ // Load into export format (with relative paths)
102+ var export WorkspaceConfigExport
103+ if err := json .NewDecoder (file ).Decode (& export ); err != nil {
86104 return fmt .Errorf ("failed to parse workspace config file %s: %w" , configPath , err )
87105 }
106+
107+ // Get the directory containing the config file
108+ configDir := filepath .Dir (configPath )
109+
110+ // Convert relative paths to absolute paths
111+ config .Project = export .Project
88112 config .ConfigPath = configPath
113+
114+ if export .OpenAPISpec != "" {
115+ config .OpenAPISpec = Resolve (configDir , export .OpenAPISpec )
116+ }
117+
118+ if export .StainlessConfig != "" {
119+ config .StainlessConfig = Resolve (configDir , export .StainlessConfig )
120+ }
121+
122+ // Convert target paths to absolute
123+ if export .Targets != nil {
124+ config .Targets = make (map [stainless.Target ]* TargetConfig , len (export .Targets ))
125+ for target , targetConfig := range export .Targets {
126+ config .Targets [target ] = & TargetConfig {
127+ OutputPath : Resolve (configDir , targetConfig .OutputPath ),
128+ }
129+ }
130+ }
131+
89132 return nil
90133}
91134
92135func (config * WorkspaceConfig ) Save () error {
93136 // Create parent directories if they don't exist
94- dir := filepath .Dir (config .ConfigPath )
95- if err := os .MkdirAll (dir , 0755 ); err != nil {
137+ configDir := filepath .Dir (config .ConfigPath )
138+ if err := os .MkdirAll (configDir , 0755 ); err != nil {
96139 return fmt .Errorf ("failed to create directory for config file: %w" , err )
97140 }
98141
142+ // Convert absolute paths to relative paths for export
143+ export := WorkspaceConfigExport {
144+ Project : config .Project ,
145+ }
146+
147+ // Convert paths to relative (fallback to absolute if conversion fails)
148+ if config .OpenAPISpec != "" {
149+ if relPath , err := filepath .Rel (configDir , config .OpenAPISpec ); err == nil {
150+ export .OpenAPISpec = relPath
151+ } else {
152+ println (err .Error ())
153+ export .OpenAPISpec = config .OpenAPISpec
154+ }
155+ }
156+
157+ if config .StainlessConfig != "" {
158+ if relPath , err := filepath .Rel (configDir , config .StainlessConfig ); err == nil {
159+ export .StainlessConfig = relPath
160+ } else {
161+ println (err .Error ())
162+ export .StainlessConfig = config .StainlessConfig
163+ }
164+ }
165+
166+ if config .Targets != nil {
167+ export .Targets = make (map [stainless.Target ]* TargetConfig , len (config .Targets ))
168+ for target , targetConfig := range config .Targets {
169+ outputPath := targetConfig .OutputPath
170+ if relPath , err := filepath .Rel (configDir , outputPath ); err == nil {
171+ outputPath = relPath
172+ }
173+ export .Targets [target ] = & TargetConfig {
174+ OutputPath : outputPath ,
175+ }
176+ }
177+ }
178+
99179 file , err := os .Create (config .ConfigPath )
100180 if err != nil {
101181 return err
@@ -104,7 +184,7 @@ func (config *WorkspaceConfig) Save() error {
104184
105185 encoder := json .NewEncoder (file )
106186 encoder .SetIndent ("" , " " )
107- return encoder .Encode (config )
187+ return encoder .Encode (export )
108188}
109189
110190func NewWorkspaceConfig (projectName , openAPISpecPath , stainlessConfigPath string ) (WorkspaceConfig , error ) {
@@ -113,10 +193,21 @@ func NewWorkspaceConfig(projectName, openAPISpecPath, stainlessConfigPath string
113193 return WorkspaceConfig {}, err
114194 }
115195
196+ // Convert paths to absolute
197+ absOpenAPISpec , err := filepath .Abs (openAPISpecPath )
198+ if err != nil {
199+ return WorkspaceConfig {}, fmt .Errorf ("failed to get absolute path for OpenAPI spec: %w" , err )
200+ }
201+
202+ absStainlessConfig , err := filepath .Abs (stainlessConfigPath )
203+ if err != nil {
204+ return WorkspaceConfig {}, fmt .Errorf ("failed to get absolute path for Stainless config: %w" , err )
205+ }
206+
116207 return WorkspaceConfig {
117208 Project : projectName ,
118- OpenAPISpec : openAPISpecPath ,
119- StainlessConfig : stainlessConfigPath ,
209+ OpenAPISpec : absOpenAPISpec ,
210+ StainlessConfig : absStainlessConfig ,
120211 Targets : nil ,
121212 ConfigPath : filepath .Join (dir , ".stainless" , "workspace.json" ),
122213 }, nil
0 commit comments