index.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. 'use strict';
  2. const fs = require('fs');
  3. const path = require('path');
  4. const is = require('is-type-of');
  5. const glob = require('glob');
  6. const resolveFiles = require('resolve-files');
  7. const debug = require('debug')('ypkgfiles');
  8. const assert = require('assert');
  9. const defaults = {
  10. cwd: process.cwd(),
  11. entry: [],
  12. files: [],
  13. check: false,
  14. strict: false,
  15. };
  16. module.exports = options => {
  17. options = Object.assign({}, defaults, options);
  18. const cwd = options.cwd;
  19. const pkg = options.pkg = readPackage(path.join(cwd, 'package.json'));
  20. const isCheck = options.check;
  21. // ignore if it's private
  22. if (pkg.private === true) return;
  23. const entry = resolveEntry(options);
  24. debug('get entry %s', entry);
  25. let files = resolveFiles({ entry, ignoreModules: true });
  26. debug('get files %s', files);
  27. files = getFiles(files, cwd);
  28. if (isCheck) return check(files, pkg.files || [], options.strict);
  29. pkg.files = files;
  30. debug('get pkg.files %s', pkg.files);
  31. writePackage(path.join(cwd, 'package.json'), pkg);
  32. };
  33. function readPackage(pkgPath) {
  34. const content = fs.readFileSync(pkgPath, 'utf8');
  35. return JSON.parse(content);
  36. }
  37. function writePackage(pkgPath, obj) {
  38. const content = JSON.stringify(obj, null, 2) + '\n';
  39. fs.writeFileSync(pkgPath, content);
  40. }
  41. // return entries with fullpath based on options.entry
  42. function resolveEntry(options) {
  43. const cwd = options.cwd;
  44. const pkg = options.pkg;
  45. let entries = [];
  46. if (is.array(options.entry)) entries = options.entry;
  47. if (is.string(options.entry)) entries.push(options.entry);
  48. const result = new Set();
  49. try {
  50. // set the entry that module exports
  51. result.add(require.resolve(cwd));
  52. } catch (_) {
  53. // ignore
  54. }
  55. for (let entry of entries) {
  56. const dir = path.join(cwd, entry);
  57. // if entry is directory, find all js in the directory
  58. if (fs.existsSync(dir) && fs.statSync(dir).isDirectory()) {
  59. entry = path.join(entry, '**/*.js');
  60. }
  61. const files = glob.sync(entry, { cwd });
  62. for (const file of files) {
  63. result.add(path.join(cwd, file));
  64. }
  65. }
  66. if (pkg.bin) {
  67. const keys = Object.keys(pkg.bin);
  68. for (const key of keys) {
  69. result.add(path.join(cwd, pkg.bin[key]));
  70. }
  71. }
  72. const dts = path.join(cwd, 'index.d.ts');
  73. if (fs.existsSync(dts)) {
  74. result.add(dts);
  75. }
  76. return Array.from(result);
  77. }
  78. function getFiles(files, cwd) {
  79. const result = new Set();
  80. for (let file of files) {
  81. file = path.relative(cwd, file).split(path.sep)[0];
  82. if (file !== 'package.json') result.add(file);
  83. }
  84. return Array.from(result);
  85. }
  86. function check(files, originalFiles, strict) {
  87. const msg = `pkg.files should equal to ${toArray(files)}, but got ${toArray(originalFiles)}`;
  88. if (strict) assert(files.length === originalFiles.length, msg);
  89. for (const file of files) {
  90. assert(originalFiles.indexOf(file) > -1, msg);
  91. }
  92. }
  93. function toArray(arr) {
  94. return `[ ${arr.join(', ')} ]`;
  95. }