package-integrity.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  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 = ['..', '.'];
  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. var dname = '../packages/all-packages';
  33. /**
  34. * Validate the integrity of a package in a directory.
  35. */
  36. function validate(dname) {
  37. filenames = glob.sync(dname + '/src/*.ts*');
  38. filenames = filenames.concat(glob.sync(dname + '/src/**/*.ts*'));
  39. if (filenames.length == 0) {
  40. return [];
  41. }
  42. var imports = [];
  43. try {
  44. var pkg = require(path.resolve(dname) + '/package.json');
  45. } catch (e) {
  46. return [];
  47. }
  48. var deps = pkg['dependencies'];
  49. // Extract all of the imports from the TypeScript files.
  50. filenames.forEach(fileName => {
  51. var sourceFile = ts.createSourceFile(fileName, readFileSync(fileName).toString(), ts.ScriptTarget.ES6, /*setParentNodes */ true);
  52. imports = imports.concat(getImports(sourceFile));
  53. });
  54. var names = Array.from(new Set(imports)).sort();
  55. names = names.map(function(name) {
  56. var parts = name.split('/');
  57. if (name.indexOf('@') === 0) {
  58. return parts[0] + '/' + parts[1];
  59. }
  60. return parts[0];
  61. })
  62. var problems = [];
  63. names.forEach(function(name) {
  64. if (IGNORE.indexOf(name) !== -1) {
  65. return;
  66. }
  67. if (!deps[name]) {
  68. problems.push('Missing package: ' + name);
  69. }
  70. });
  71. Object.keys(deps).forEach(function(name) {
  72. if (IGNORE.indexOf(name) !== -1) {
  73. return;
  74. }
  75. if (names.indexOf(name) === -1) {
  76. problems.push('Unused package: ' + name);
  77. }
  78. });
  79. return problems;
  80. }
  81. // Find all of the packages.
  82. var basePath = path.resolve('.');
  83. var lernaConfig = require(path.join(basePath, 'lerna.json'));
  84. var errors = {};
  85. // Validate each package.
  86. lernaConfig.packages.forEach(function(spec) {
  87. var dirs = glob.sync(path.join(basePath, spec));
  88. dirs.forEach(function(dname) {
  89. var name = path.relative('.', dname);
  90. var problems = validate(dname);
  91. if (problems.length > 0) {
  92. errors[name] = problems;
  93. }
  94. });
  95. });
  96. // Handle any errors.
  97. if (Object.keys(errors).length > 0) {
  98. console.log('Package integrity failures:')
  99. console.log(JSON.stringify(errors, null, 2));
  100. process.exit(1);
  101. }