package-integrity.js 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /**
  2. * Verify the integrity of each package - ensure package json matches
  3. * imports
  4. */
  5. var readFileSync = require("fs").readFileSync;
  6. var writeFileSync = require("fs").writeFileSync;
  7. var ts = require("typescript");
  8. var glob = require("glob");
  9. var childProcess = require('child_process');
  10. var path = require('path');
  11. // Packages to ignore
  12. var IGNORE = ['..', '.', 'd3', 'vega', 'vega-lite', 'font-awesome', 'es6-promise', 'path'];
  13. /**
  14. * Extract the module imports from a TypeScript source file.
  15. */
  16. function getImports(sourceFile) {
  17. var imports = [];
  18. handleNode(sourceFile);
  19. function handleNode(node) {
  20. switch (node.kind) {
  21. case ts.SyntaxKind.ImportDeclaration:
  22. imports.push(node.moduleSpecifier.text);
  23. break;
  24. case ts.SyntaxKind.ImportEqualsDeclaration:
  25. imports.push(node.moduleReference.expression.text);
  26. break;
  27. }
  28. ts.forEachChild(node, handleNode);
  29. }
  30. return imports;
  31. }
  32. /**
  33. * Validate the integrity of a package in a directory.
  34. */
  35. function validate(dname) {
  36. filenames = glob.sync(dname + '/src/*.ts*');
  37. filenames = filenames.concat(glob.sync(dname + '/src/**/*.ts*'));
  38. if (filenames.length == 0) {
  39. return [];
  40. }
  41. var imports = [];
  42. try {
  43. var pkg = require(path.resolve(dname) + '/package.json');
  44. } catch (e) {
  45. return [];
  46. }
  47. var deps = pkg['dependencies'];
  48. // Extract all of the imports from the TypeScript files.
  49. filenames.forEach(fileName => {
  50. var sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true);
  51. imports = imports.concat(getImports(sourceFile));
  52. });
  53. var names = Array.from(new Set(imports)).sort();
  54. names = names.map(function(name) {
  55. var parts = name.split('/');
  56. if (name.indexOf('@') === 0) {
  57. return parts[0] + '/' + parts[1];
  58. }
  59. return parts[0];
  60. })
  61. var problems = [];
  62. names.forEach(function(name) {
  63. if (IGNORE.indexOf(name) !== -1) {
  64. return;
  65. }
  66. if (!deps[name]) {
  67. problems.push('Missing package: ' + name);
  68. }
  69. });
  70. Object.keys(deps).forEach(function(name) {
  71. if (versions[name]) {
  72. var desired = '^' + versions[name];
  73. if (deps[name] !== desired) {
  74. problems.push('Bad core version: ' + name + ' should be ' + desired);
  75. }
  76. }
  77. if (IGNORE.indexOf(name) !== -1) {
  78. return;
  79. }
  80. if (names.indexOf(name) === -1) {
  81. problems.push('Unused package: ' + name);
  82. }
  83. });
  84. return problems;
  85. }
  86. // Find all of the packages.
  87. var basePath = path.resolve('.');
  88. var lernaConfig = require(path.join(basePath, 'lerna.json'));
  89. // Gather the versions of each package.
  90. var versions = {};
  91. lernaConfig.packages.forEach(function(spec) {
  92. var dirs = glob.sync(path.join(basePath, spec));
  93. dirs.forEach(function(dname) {
  94. try {
  95. var pkg = require(path.resolve(dname) + '/package.json');
  96. versions[pkg['name']] = pkg['version'];
  97. } catch (e) {
  98. return;
  99. }
  100. });
  101. });
  102. var errors = {};
  103. // Validate each package.
  104. lernaConfig.packages.forEach(function(spec) {
  105. var dirs = glob.sync(path.join(basePath, spec));
  106. dirs.forEach(function(dname) {
  107. var name = path.relative('.', dname);
  108. var problems = validate(dname);
  109. if (problems.length > 0) {
  110. errors[name] = problems;
  111. }
  112. });
  113. });
  114. // Handle any errors.
  115. if (Object.keys(errors).length > 0) {
  116. console.log('Package integrity failures:')
  117. console.log(JSON.stringify(errors, null, 2));
  118. process.exit(1);
  119. }