| OLD | NEW |
| (Empty) |
| 1 import "dart:io"; | |
| 2 import "dart:async"; | |
| 3 | |
| 4 import '../discovery_api_dart_client_generator/lib/generator.dart'; | |
| 5 import 'package:google_discovery_v1_api/discovery_v1_api_client.dart'; | |
| 6 import 'package:yaml/yaml.dart'; | |
| 7 | |
| 8 class Package { | |
| 9 final String name; | |
| 10 final List<String> apis; | |
| 11 final Pubspec pubspec; | |
| 12 final String readme; | |
| 13 final String license; | |
| 14 | |
| 15 Package(this.name, this.apis, this.pubspec, this.readme, this.license); | |
| 16 } | |
| 17 | |
| 18 /** | |
| 19 * Configuration of a set of packages generated from a set of APIs exposed by | |
| 20 * a Discovery Service. | |
| 21 */ | |
| 22 class DiscoveryPackagesConfiguration { | |
| 23 Map<String, Package> packages = {}; | |
| 24 Iterable<String> excessApis; | |
| 25 Iterable<String> missingApis; | |
| 26 | |
| 27 /** | |
| 28 * Create a new discovery packages configuration. | |
| 29 * | |
| 30 * [config] is the path to the YAML configuration file. | |
| 31 * | |
| 32 * [allApis] is the list of all supported APIs returned by the Discovery | |
| 33 * Service. | |
| 34 * | |
| 35 * The format of a YAML document describing a number of packages looks | |
| 36 * like this: | |
| 37 * | |
| 38 * packages: | |
| 39 * - googleapis: | |
| 40 * version: 0.1.0 | |
| 41 * author: Dart Team <misc@dartlang.org> | |
| 42 * homepage: http://www.dartlang.org | |
| 43 * readme: resources/README.md | |
| 44 * license: resources/LICENSE | |
| 45 * apis: | |
| 46 * - analytics:v3 | |
| 47 * - bigquery:v2 | |
| 48 * - googleapis_beta: | |
| 49 * version: 0.1.0 | |
| 50 * author: Dart Team <misc@dartlang.org> | |
| 51 * homepage: http://www.dartlang.org | |
| 52 * readme: resources/README.md | |
| 53 * license: resources/LICENSE | |
| 54 * apis: | |
| 55 * - datastore:v1beta2 | |
| 56 * - dns:v1beta1 | |
| 57 * skipped_apis: | |
| 58 * - adexchangebuyer:v1 | |
| 59 * | |
| 60 * Each package to build is listed under the key `packages:`. | |
| 61 * | |
| 62 * The key `skipped_apis` is used to list APIs returned buy the Discovery | |
| 63 * Service but is not part of any generated packages. | |
| 64 * | |
| 65 * The file names for the content of readme and license files are resolved | |
| 66 * relative to the configuration file. | |
| 67 */ | |
| 68 DiscoveryPackagesConfiguration( | |
| 69 String configFile, List<DirectoryListItems> allApis) { | |
| 70 var configYaml = new File(configFile).readAsStringSync(); | |
| 71 var yaml = loadYaml(configYaml); | |
| 72 packages = _packagesFromYaml(yaml['packages'], configFile, allApis); | |
| 73 var knownApis = _calculateKnownApis(packages, | |
| 74 _listFromYaml(yaml['skipped_apis'])); | |
| 75 missingApis = _calculateMissingApis(knownApis, allApis); | |
| 76 excessApis = _calculateExcessApis(knownApis, allApis); | |
| 77 } | |
| 78 | |
| 79 /** | |
| 80 * Generate packages from the configuration. | |
| 81 * | |
| 82 * [discoveryDocsDir] is the directory where all the downloaded discovery | |
| 83 * documents are stored. | |
| 84 * | |
| 85 * [generatedApisDir] is the directory where the packages are generated. | |
| 86 * Each package is generated in a sub-directory. | |
| 87 */ | |
| 88 Future generate(String discoveryDocsDir, String generatedApisDir) { | |
| 89 // Delete all downloaded discovery documents. | |
| 90 var dir = new Directory(discoveryDocsDir); | |
| 91 if (dir.existsSync()) dir.deleteSync(recursive: true); | |
| 92 | |
| 93 // Download the discovery documents for the packages to build. | |
| 94 var futures = []; | |
| 95 packages.forEach((name, package) { | |
| 96 futures.add(downloadDiscoveryDocuments('$discoveryDocsDir/$name', | |
| 97 ids: package.apis)); | |
| 98 }); | |
| 99 | |
| 100 return Future.wait(futures).then((_) { | |
| 101 packages.forEach((name, package) { | |
| 102 generateAllLibraries('$discoveryDocsDir/$name', | |
| 103 '$generatedApisDir/$name', | |
| 104 package.pubspec); | |
| 105 new File('$generatedApisDir/$name/README.md') | |
| 106 .writeAsStringSync(package.readme); | |
| 107 if (package.license != null) { | |
| 108 new File('$generatedApisDir/$name/LICENSE') | |
| 109 .writeAsStringSync(package.license); | |
| 110 } | |
| 111 }); | |
| 112 }); | |
| 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 return allApis | |
| 228 .where((item) => !knownApis.contains(item.id)) | |
| 229 .map((item) => item.id); | |
| 230 } | |
| 231 | |
| 232 /// The excess APIs are the APIs mentioned in the configuration but not | |
| 233 /// returned from the Discovery Service. | |
| 234 static Iterable<String> _calculateExcessApis( | |
| 235 Iterable<String> knownApis, List<DirectoryListItems> allApis) { | |
| 236 var excessApis = new Set.from(knownApis); | |
| 237 allApis.forEach((item) => excessApis.remove(item.id)); | |
| 238 return excessApis; | |
| 239 } | |
| 240 } | |
| 241 | |
| 242 main() { | |
| 243 listAllApis().then((List<DirectoryListItems> items) { | |
| 244 var configuration = new DiscoveryPackagesConfiguration( | |
| 245 Platform.script.resolve('config.yaml').path, items); | |
| 246 | |
| 247 // Print warnings for APIs not mentioned. | |
| 248 if (configuration.missingApis.isNotEmpty) { | |
| 249 print('WARNING: No configuration for the following APIs:'); | |
| 250 configuration.missingApis.forEach((id) => print('- $id')); | |
| 251 } | |
| 252 if (configuration.excessApis.isNotEmpty) { | |
| 253 print('WARNING: The following APIs do not exist:'); | |
| 254 configuration.excessApis.forEach((id) => print('- $id')); | |
| 255 } | |
| 256 | |
| 257 // Generate the packages. | |
| 258 configuration.generate(Platform.script.resolve('discovery').path, | |
| 259 Platform.script.resolve('generated').path) | |
| 260 .then((_) => print('Done!')); | |
| 261 }); | |
| 262 } | |
| OLD | NEW |