OLD | NEW |
---|---|
1 import "dart:io"; | 1 import "dart:io"; |
2 import "dart:async"; | 2 import "dart:async"; |
3 | 3 |
4 import '../discovery_api_dart_client_generator/lib/generator.dart'; | 4 import '../discovery_api_dart_client_generator/lib/generator.dart'; |
5 import 'package:google_discovery_v1_api/discovery_v1_api_client.dart'; | 5 import 'package:google_discovery_v1_api/discovery_v1_api_client.dart'; |
6 import 'package:yaml/yaml.dart'; | 6 import 'package:yaml/yaml.dart'; |
7 | 7 |
8 class Package { | 8 class Package { |
9 final String name; | 9 final String name; |
10 final List<String> apis; | 10 final List<String> apis; |
11 final Pubspec pubspec; | 11 final Pubspec pubspec; |
12 final String readme; | 12 final String readme; |
13 final String license; | 13 final String license; |
14 | 14 |
15 Package(this.name, this.apis, this.pubspec, this.readme, this.license); | 15 Package(this.name, this.apis, this.pubspec, this.readme, this.license); |
16 } | 16 } |
17 | 17 |
18 String generateReadme(String readmeFile, List<DirectoryListItems> items) { | 18 /** |
19 var sb = new StringBuffer(); | 19 * Configuration of a set of packages generated from a set of APIs exposed by |
20 if (readmeFile != null) { | 20 * a Discovery Service. |
21 sb.write(new File(readmeFile).readAsStringSync()); | 21 */ |
22 } | 22 class DiscoveryPackagesConfiguration { |
23 sb.writeln(''' | 23 Map<String, Package> packages = {}; |
24 | 24 Iterable<String> excessApis; |
25 ## Available Google APIs | 25 Iterable<String> missingApis; |
26 | 26 |
27 The following is a list of APIs that are currently available inside this | 27 /** |
28 package. | 28 * Create a new discovery packages configuration. |
29 '''); | 29 * |
30 for (DirectoryListItems item in items) { | 30 * [config] is the path to the YAML configuration file. |
31 sb.write("#### "); | 31 * |
32 if (item.icons != null && item.icons.x16 != null) { | 32 * [allApis] is the list of all supported APIs returned by the Discovery |
33 sb.write(" "); | 33 * Service. |
34 } | 34 * |
35 sb..writeln('${item.title} - ${item.name} ${item.version}') | 35 * The format of a YAML document describing a number of packages looks |
36 ..writeln() | 36 * like this: |
37 ..writeln('${item.description}') | 37 * |
38 ..writeln(); | 38 * packages: |
39 if (item.documentationLink != null) { | 39 * - googleapis: |
40 sb.writeln( | 40 * version: 0.1.0 |
41 'Official API documentation: ${item.documentationLink}'); | 41 * author: Dart Team <misc@dartlang.org> |
42 sb.writeln(); | 42 * homepage: http://www.dartlang.org |
43 } | 43 * readme: resources/README.md |
44 } | 44 * license: resources/LICENSE |
45 return sb.toString(); | 45 * apis: |
46 } | 46 * - analytics:v3 |
47 | 47 * - bigquery:v2 |
48 main() { | 48 * - googleapis_beta: |
49 listFromYaml(value) => value != null ? value : []; | 49 * version: 0.1.0 |
50 | 50 * author: Dart Team <misc@dartlang.org> |
51 // Set up paths to directories 'discovery' and 'generated'. | 51 * homepage: http://www.dartlang.org |
52 var discoveryDocsDir = Platform.script.resolve('discovery').path; | 52 * readme: resources/README.md |
53 var generatedApisDir = Platform.script.resolve('generated').path; | 53 * license: resources/LICENSE |
54 | 54 * apis: |
55 // Read the configuration. | 55 * - datastore:v1beta2 |
56 var configFile = Platform.script.resolve('config.yaml').path; | 56 * - dns:v1beta1 |
57 var config = loadYaml(new File(configFile).readAsStringSync()); | 57 * skipped_apis: |
58 | 58 * - adexchangebuyer:v1 |
59 listAllApis().then((List<DirectoryListItems> items) { | 59 * |
60 var pkgs = config['packages']; | 60 * Each package to build is listed under the key `packages:`. |
61 var packages = {}; | 61 * |
62 var supportedApis = []; | 62 * The key `skipped_apis` is used to list APIs returned buy the Discovery |
63 pkgs.forEach((package) { | 63 * Service but is not part of any generated packages. |
64 package.forEach((name, values) { | 64 * |
65 var apis = listFromYaml(values['apis']); | 65 * The file names for the content of readme and license files are resolved |
66 var version = | 66 * relative to the configuration file. |
67 values['version'] != null ? values['version'] : '0.1.0-dev'; | 67 */ |
68 var author = values['author']; | 68 DiscoveryPackagesConfiguration( |
69 var homepage = values['homepage']; | 69 String configFile, List<DirectoryListItems> allApis) { |
70 var readmeFile; | 70 var configYaml = new File(configFile).readAsStringSync(); |
71 if (values['readme'] != null) { | 71 var yaml = loadYaml(configYaml); |
72 readmeFile = Platform.script.resolve(values['readme']).path; | 72 packages = _packagesFromYaml(yaml['packages'], configFile, allApis); |
73 } | 73 var knownApis = _calculateKnownApis(packages, |
74 var licenseFile; | 74 _listFromYaml(yaml['skipped_apis'])); |
75 if (values['license'] != null) { | 75 missingApis = _calculateMissingApis(knownApis, allApis); |
76 licenseFile = Platform.script.resolve(values['license']).path; | 76 excessApis = _calculateExcessApis(knownApis, allApis); |
77 } | 77 } |
78 | 78 |
79 | 79 /** |
80 // Generate package description. | 80 * Generate packages from the configuration. |
81 var apiDescriptions = []; | 81 * |
82 var sb = new StringBuffer() | 82 * [discoveryDocsDir] is the directory where all the downloaded discovery |
83 ..write('"Auto-generated client libraries for accessing ' | 83 * documents are stored. |
84 'the following APIs:\\n'); | 84 * |
85 items.forEach((DirectoryListItems apiDescription) { | 85 * [generatedApisDir] is the directory where the packages are generated. |
86 if (apis.contains(apiDescription.id)) { | 86 * Each package is generated in a sub-directory. |
87 sb..writeln('') | 87 */ |
88 ..write(' ') | 88 Future generate(String discoveryDocsDir, String generatedApisDir) { |
89 ..write(apiDescription.id) | 89 // Delete all downloaded discovery documents. |
90 ..write(' - ') | |
91 ..write(apiDescription.description) | |
92 ..write('\\n'); | |
93 apiDescriptions.add(apiDescription); | |
94 } | |
95 }); | |
96 sb.write('"'); | |
97 | |
98 // Generate the README.md file content. | |
99 var readme = generateReadme(readmeFile, apiDescriptions); | |
100 | |
101 // Read the LICENSE | |
102 var license = new File(licenseFile).readAsStringSync(); | |
103 | |
104 // Create package description with pubspec.yaml information. | |
105 var pubspec = new Pubspec( | |
106 name, version, sb.toString(), author: author, homepage: homepage); | |
107 packages[name] = new Package(name, apis, pubspec, readme, license); | |
108 }); | |
109 }); | |
110 | |
111 // Check that all APIs are mentioned in the configuration. | |
112 var skippedApis = listFromYaml(config['skipped_apis']); | |
113 packages.forEach((_, package) => supportedApis.addAll(package.apis)); | |
114 var knownApis = new Set(); | |
115 knownApis.addAll(supportedApis); | |
116 knownApis.addAll(skippedApis); | |
117 var excessApis = new Set.from(knownApis); | |
118 | |
119 var missingApis = []; | |
120 items.forEach((item) { | |
121 if (!knownApis.contains(item.id)) missingApis.add(item.id); | |
122 excessApis.remove(item.id); | |
123 }); | |
124 | |
125 if (missingApis.isNotEmpty) { | |
126 print('WARNING: No configuration for the following APIs:'); | |
127 missingApis.forEach((id) => print('- $id')); | |
128 } | |
129 | |
130 if (excessApis.isNotEmpty) { | |
131 print('WARNING: The following APIs does not exist:'); | |
132 excessApis.forEach((id) => print('- $id')); | |
133 } | |
134 | |
135 // Delete downloaded discovery documents. | |
136 var dir = new Directory(discoveryDocsDir); | 90 var dir = new Directory(discoveryDocsDir); |
137 if (dir.existsSync()) dir.deleteSync(recursive: true); | 91 if (dir.existsSync()) dir.deleteSync(recursive: true); |
138 | 92 |
139 // Download the discovery documents for the packages to build. | 93 // Download the discovery documents for the packages to build. |
140 var futures = []; | 94 var futures = []; |
141 packages.forEach((name, package) { | 95 packages.forEach((name, package) { |
142 futures.add(downloadDiscoveryDocuments('$discoveryDocsDir/$name', | 96 futures.add(downloadDiscoveryDocuments('$discoveryDocsDir/$name', |
143 ids: package.apis)); | 97 ids: package.apis)); |
144 }); | 98 }); |
145 | 99 |
146 Future.wait(futures).then((_) { | 100 return Future.wait(futures).then((_) { |
147 packages.forEach((name, package) { | 101 packages.forEach((name, package) { |
148 print('Generating library $name'); | |
149 generateAllLibraries('$discoveryDocsDir/$name', | 102 generateAllLibraries('$discoveryDocsDir/$name', |
150 '$generatedApisDir/$name', | 103 '$generatedApisDir/$name', |
151 package.pubspec); | 104 package.pubspec); |
152 new File('$generatedApisDir/$name/README.md') | 105 new File('$generatedApisDir/$name/README.md') |
153 .writeAsStringSync(package.readme); | 106 .writeAsStringSync(package.readme); |
154 if (package.license != null) { | 107 if (package.license != null) { |
155 new File('$generatedApisDir/$name/LICENSE') | 108 new File('$generatedApisDir/$name/LICENSE') |
156 .writeAsStringSync(package.license); | 109 .writeAsStringSync(package.license); |
157 } | 110 } |
158 }); | 111 }); |
159 print('DONE'); | 112 }); |
160 }); | 113 } |
114 | |
115 // Return empty list for YAML null value. | |
116 static List _listFromYaml(value) => value != null ? value : []; | |
117 | |
118 static String _generateReadme( | |
119 String readmeFile, List<DirectoryListItems> items) { | |
120 var sb = new StringBuffer(); | |
121 if (readmeFile != null) { | |
122 sb.write(new File(readmeFile).readAsStringSync()); | |
123 } | |
124 sb.writeln(''' | |
125 | |
126 ## Available Google APIs | |
127 | |
128 The following is a list of APIs that are currently available inside this | |
129 package. | |
130 '''); | |
131 for (DirectoryListItems item in items) { | |
132 sb.write("#### "); | |
133 if (item.icons != null && item.icons.x16 != null) { | |
134 sb.write(" "); | |
135 } | |
136 sb..writeln('${item.title} - ${item.name} ${item.version}') | |
137 ..writeln() | |
138 ..writeln('${item.description}') | |
139 ..writeln(); | |
140 if (item.documentationLink != null) { | |
141 sb.writeln( | |
142 'Official API documentation: ${item.documentationLink}'); | |
143 sb.writeln(); | |
144 } | |
145 } | |
146 return sb.toString(); | |
147 } | |
148 | |
149 static Map<String, Package>_packagesFromYaml( | |
150 YamlList configPackages, | |
151 String configFile, | |
152 List<DirectoryListItems> allApis) { | |
153 var supportedApis = []; | |
154 var packages = {}; | |
155 configPackages.forEach((package) { | |
156 package.forEach((name, values) { | |
157 packages[name] = _packageFromYaml(name, values, configFile, allApis); | |
158 }); | |
159 }); | |
160 | |
161 return packages; | |
162 } | |
163 | |
164 static Package _packageFromYaml(String name, | |
165 YamlMap values, | |
166 String configFile, | |
167 List<DirectoryListItems> allApis) { | |
168 var apis = _listFromYaml(values['apis']); | |
169 var version = | |
170 values['version'] != null ? values['version'] : '0.1.0-dev'; | |
171 var author = values['author']; | |
172 var homepage = values['homepage']; | |
173 var readmeFile; | |
174 if (values['readme'] != null) { | |
175 readmeFile = new Uri.file(configFile).resolve(values['readme']).path; | |
176 } | |
177 var licenseFile; | |
178 if (values['license'] != null) { | |
179 licenseFile = | |
180 new Uri.file(configFile).resolve(values['license']).path; | |
181 } | |
182 | |
183 // Generate package description. | |
184 var apiDescriptions = []; | |
185 var sb = new StringBuffer() | |
186 ..write('"Auto-generated client libraries for accessing ' | |
187 'the following APIs:\\n'); | |
188 allApis.forEach((DirectoryListItems apiDescription) { | |
189 if (apis.contains(apiDescription.id)) { | |
190 sb..writeln('') | |
191 ..write(' ') | |
192 ..write(apiDescription.id) | |
193 ..write(' - ') | |
194 ..write(apiDescription.description) | |
195 ..write('\\n'); | |
196 apiDescriptions.add(apiDescription); | |
197 } | |
198 }); | |
199 sb.write('"'); | |
200 | |
201 // Generate the README.md file content. | |
202 var readme = _generateReadme(readmeFile, apiDescriptions); | |
203 | |
204 // Read the LICENSE | |
205 var license = new File(licenseFile).readAsStringSync(); | |
206 | |
207 // Create package description with pubspec.yaml information. | |
208 var pubspec = new Pubspec( | |
209 name, version, sb.toString(), author: author, homepage: homepage); | |
210 return new Package(name, apis, pubspec, readme, license); | |
211 } | |
212 | |
213 /// The known APIs are the APis mentioned in each package together with | |
214 /// the APIs explicitly skipped. | |
215 static Set<String> _calculateKnownApis(Map<String, Package> packages, | |
216 YamlList skippedApis) { | |
217 var knownApis = new Set(); | |
218 knownApis.addAll(skippedApis); | |
219 packages.forEach((_, package) => knownApis.addAll(package.apis)); | |
220 return knownApis; | |
221 } | |
222 | |
223 /// The missing APIs are the APIs returned from the Discovery Service | |
224 /// but not mentioned in the configuration. | |
225 static Iterable<String> _calculateMissingApis( | |
226 Iterable<String> knownApis, List<DirectoryListItems> allApis) { | |
227 var missingApis = []; | |
228 allApis.forEach((item) { | |
229 if (!knownApis.contains(item.id)) missingApis.add(item.id); | |
230 }); | |
kustermann
2014/08/26 14:27:14
Maybe a bit easier like this?
return allApis
Søren Gjesse
2014/08/27 07:13:10
Done.
| |
231 return missingApis; | |
232 } | |
233 | |
234 /// The excess APIs are the APIs mentioned in the configuration but not | |
235 /// returned from the Discovery Service. | |
236 static Iterable<String> _calculateExcessApis( | |
237 Iterable<String> knownApis, List<DirectoryListItems> allApis) { | |
238 var excessApis = new Set.from(knownApis); | |
239 allApis.forEach((item) => excessApis.remove(item.id)); | |
240 return excessApis; | |
241 } | |
242 } | |
243 | |
244 main() { | |
245 listAllApis().then((List<DirectoryListItems> items) { | |
246 var configuration = new DiscoveryPackagesConfiguration( | |
247 Platform.script.resolve('config.yaml').path, items); | |
248 | |
249 // Print warnings for APIs not mentioned. | |
250 if (configuration.missingApis.isNotEmpty) { | |
251 print('WARNING: No configuration for the following APIs:'); | |
252 configuration.missingApis.forEach((id) => print('- $id')); | |
253 } | |
254 if (configuration.excessApis.isNotEmpty) { | |
255 print('WARNING: The following APIs does not exist:'); | |
kustermann
2014/08/26 14:27:14
does -> do
Søren Gjesse
2014/08/27 07:13:10
Done.
| |
256 configuration.excessApis.forEach((id) => print('- $id')); | |
257 } | |
258 | |
259 // Generate the packages. | |
260 configuration.generate(Platform.script.resolve('discovery').path, | |
261 Platform.script.resolve('generated').path) | |
262 .then((_) => print('Done!')); | |
161 }); | 263 }); |
162 } | 264 } |
OLD | NEW |