1
1
import YAML from "yaml" ;
2
- import { Plugin , PluginConfig , Uses , With } from "../types/plugins" ;
2
+ import { Plugin , PluginConfig } from "../types/plugins" ;
3
3
import { Octokit } from "@octokit/rest" ;
4
+ const repo = ".ubiquity-os" ;
5
+ const path = `.github/.ubiquity-os.config.yml` ;
4
6
5
7
export class ConfigParser {
6
- currentConfig : string | null = null ;
7
- newConfig : string | null = null ;
8
+ repoConfig : string | null = null ;
9
+ repoConfigSha : string | null = null ;
10
+ newConfigYml : string | null = null ;
8
11
9
- async pushConfigToRepo ( org : string , env : "development" | "production" , octokit : Octokit ) {
10
- const repo = ".ubiquity-os" ;
11
- const path = `.github/.ubiquity-os.config.yml` ;
12
- const content = this . currentConfig ;
12
+ async fetchUserInstalledConfig ( org : string , env : "development" | "production" , octokit : Octokit ) {
13
+ const content = this . loadConfig ( ) ;
13
14
if ( ! content ) {
14
15
throw new Error ( "No content to push" ) ;
15
16
}
@@ -20,53 +21,81 @@ export class ConfigParser {
20
21
path : env === "production" ? path : path . replace ( ".yml" , ".dev.yml" ) ,
21
22
} ) ;
22
23
23
- let extContent , extSha ;
24
-
25
24
if ( existingConfig && "content" in existingConfig . data ) {
26
- extContent = atob ( existingConfig . data . content ) ;
27
- extSha = existingConfig . data . sha ;
25
+ this . repoConfigSha = existingConfig . data . sha ;
26
+ this . repoConfig = atob ( existingConfig . data . content ) ;
27
+ } else {
28
+ throw new Error ( "No existing config found" ) ; // todo create repo/dirs/files
28
29
}
30
+ }
29
31
30
- if ( existingConfig ) {
31
- return this . updateConfig ( org , repo , path , env , content , octokit , {
32
- extContent,
33
- extSha,
34
- } ) ;
35
- } else {
36
- return this . createConfig ( org , repo , path , env , content , octokit ) ;
32
+ parseConfig ( config ?: string | null ) : PluginConfig {
33
+ if ( config ) {
34
+ return YAML . parse ( config ) ;
35
+ }
36
+ if ( ! this . newConfigYml ) {
37
+ this . loadConfig ( ) ;
37
38
}
39
+ return YAML . parse ( `${ this . newConfigYml } ` ) ;
38
40
}
39
41
40
- async updateConfig (
41
- org : string ,
42
- repo : string ,
43
- path : string ,
44
- env : "development" | "production" ,
45
- content : string ,
46
- octokit : Octokit ,
47
- existingConfig : { extContent ?: string ; extSha ?: string }
48
- ) {
49
- const newContent = existingConfig ? `${ existingConfig . extContent } \n${ content } ` : content ;
50
- return octokit . repos . createOrUpdateFileContents ( {
42
+ async updateConfig ( org : string , env : "development" | "production" , octokit : Octokit ) {
43
+ const repoPlugins = this . parseConfig ( this . repoConfig ) . plugins ;
44
+ const newPlugins = this . parseConfig ( ) . plugins ;
45
+
46
+ if ( ! newPlugins ) {
47
+ throw new Error ( "No plugins found in the config" ) ;
48
+ }
49
+
50
+ const newPluginNames = newPlugins . map ( ( p ) => p . uses [ 0 ] . plugin ) ;
51
+ if ( newPluginNames . length === 0 ) {
52
+ throw new Error ( "No plugins found in the config" ) ;
53
+ }
54
+
55
+ for ( const plugin of newPlugins ) {
56
+ const repoPlugin = repoPlugins . find ( ( p ) => p . uses [ 0 ] . plugin === plugin . uses [ 0 ] . plugin ) ;
57
+ if ( repoPlugin ) {
58
+ repoPlugin . uses = plugin . uses ;
59
+ } else {
60
+ repoPlugins . push ( plugin ) ;
61
+ }
62
+ }
63
+
64
+ this . newConfigYml = YAML . stringify ( { plugins : repoPlugins } ) ;
65
+ this . saveConfig ( ) ;
66
+ return this . createOrUpdateFileContents ( org , repo , path , env , octokit ) ;
67
+ }
68
+
69
+ async createOrUpdateFileContents ( org : string , repo : string , path : string , env : "development" | "production" , octokit : Octokit ) {
70
+ const recentSha = await octokit . repos . getContent ( {
51
71
owner : org ,
52
72
repo : repo ,
53
73
path : env === "production" ? path : path . replace ( ".yml" , ".dev.yml" ) ,
54
- message : `chore: updating ${ env } config` ,
55
- content : btoa ( newContent ) ,
56
- sha : existingConfig ?. extSha ,
57
74
} ) ;
58
- }
59
75
60
- async createConfig ( org : string , repo : string , path : string , env : "development" | "production" , content : string , octokit : Octokit ) {
76
+ const sha = "sha" in recentSha . data ? recentSha . data . sha : null ;
77
+
61
78
return octokit . repos . createOrUpdateFileContents ( {
62
79
owner : org ,
63
80
repo : repo ,
64
81
path : env === "production" ? path : path . replace ( ".yml" , ".dev.yml" ) ,
65
82
message : `chore: creating ${ env } config` ,
66
- content : btoa ( content ) ,
83
+ content : btoa ( `${ this . newConfigYml } ` ) ,
84
+ sha : `${ sha } ` ,
67
85
} ) ;
68
86
}
69
87
88
+ addPlugin ( plugin : Plugin ) {
89
+ const config = this . loadConfig ( ) ;
90
+ const parsedConfig = YAML . parse ( config ) ;
91
+ if ( ! parsedConfig . plugins ) {
92
+ parsedConfig . plugins = [ ] ;
93
+ }
94
+ parsedConfig . plugins . push ( plugin ) ;
95
+ this . newConfigYml = YAML . stringify ( parsedConfig ) ;
96
+ this . saveConfig ( ) ;
97
+ }
98
+
70
99
/**
71
100
* Loads the current config from local storage or
72
101
* creates a new one if it doesn't exist.
@@ -76,83 +105,33 @@ export class ConfigParser {
76
105
* the ubiquity-os.config.yml file.
77
106
*/
78
107
loadConfig ( ) {
79
- if ( ! this . currentConfig ) {
80
- this . currentConfig = localStorage . getItem ( "config" ) ;
108
+ if ( this . repoConfig ) {
109
+ return this . repoConfig ;
81
110
}
82
111
83
- if ( ! this . currentConfig ) {
84
- this . writeBlankConfig ( ) ;
112
+ if ( ! this . newConfigYml ) {
113
+ this . newConfigYml = localStorage . getItem ( "config" ) ;
85
114
}
86
115
87
- this . newConfig = this . currentConfig ;
88
-
89
- return this . currentConfig ;
90
- }
91
-
92
- saveConfig ( ) {
93
- if ( this . newConfig ) {
94
- localStorage . setItem ( "config" , this . newConfig ) ;
95
- this . currentConfig = this . newConfig ;
96
- this . newConfig = null ;
116
+ if ( ! this . newConfigYml ) {
117
+ this . writeBlankConfig ( ) ;
97
118
}
98
- }
99
119
100
- parseConfig ( ) : PluginConfig {
101
- if ( ! this . currentConfig ) {
102
- return { plugins : [ ] } ;
120
+ if ( ! this . repoConfig && this . newConfigYml ) {
121
+ this . repoConfig = YAML . parse ( this . newConfigYml ) ;
103
122
}
104
- return YAML . parse ( this . currentConfig ) as PluginConfig ;
105
- }
106
123
107
- writeBlankConfig ( ) {
108
- this . newConfig = YAML . stringify ( { plugins : [ ] } ) ;
109
- this . saveConfig ( ) ;
124
+ return this . newConfigYml as string ;
110
125
}
111
126
112
- addPlugin ( plugin : Plugin ) {
113
- this . loadConfig ( ) ;
114
- const config = this . parseConfig ( ) ;
115
- if ( ! config . plugins . some ( ( p ) => p . uses [ 0 ] . plugin === plugin . uses [ 0 ] . plugin ) ) {
116
- config . plugins . push ( plugin ) ;
127
+ saveConfig ( ) {
128
+ if ( this . newConfigYml ) {
129
+ localStorage . setItem ( "config" , this . newConfigYml ) ;
117
130
}
118
- this . newConfig = YAML . stringify ( config ) ;
119
- this . saveConfig ( ) ;
120
131
}
121
132
122
- removePlugin ( pluginName : string ) {
123
- this . loadConfig ( ) ;
124
- const config = this . parseConfig ( ) ;
125
- config . plugins = config . plugins . filter ( ( p ) => p . uses [ 0 ] . plugin !== pluginName ) ;
126
- this . newConfig = YAML . stringify ( config ) ;
127
- this . saveConfig ( ) ;
128
- }
129
-
130
- updatePlugin ( plugin : Plugin ) {
131
- this . loadConfig ( ) ;
132
- const config = this . parseConfig ( ) ;
133
- const index = config . plugins . findIndex ( ( p ) => p . uses [ 0 ] . plugin === plugin . uses [ 0 ] . plugin ) ;
134
- if ( index !== - 1 ) {
135
- config . plugins [ index ] = plugin ;
136
- } else {
137
- config . plugins . push ( plugin ) ;
138
- }
139
- this . newConfig = YAML . stringify ( config ) ;
133
+ writeBlankConfig ( ) {
134
+ this . newConfigYml = YAML . stringify ( { plugins : [ ] } ) ;
140
135
this . saveConfig ( ) ;
141
136
}
142
-
143
- extractPlugin ( pluginName : string ) : Plugin | null {
144
- this . loadConfig ( ) ;
145
- const config = this . parseConfig ( ) ;
146
- return config . plugins . find ( ( p ) => p . uses . some ( ( u ) => u . plugin === pluginName ) ) || null ;
147
- }
148
-
149
- extractUses ( pluginName : string ) : Uses [ ] {
150
- const plugin = this . extractPlugin ( pluginName ) ;
151
- return plugin ? plugin . uses : [ ] ;
152
- }
153
-
154
- extractWith ( pluginName : string ) : With [ ] {
155
- const uses = this . extractUses ( pluginName ) ;
156
- return uses . map ( ( u ) => u . with ) ;
157
- }
158
137
}
0 commit comments