nodef/extra-set

View on GitHub
build.js

Summary

Maintainability
A
25 mins
Test Coverage
const fs    = require('fs');
const build = require('extra-build');

const owner  = 'nodef';
const repo   = build.readMetadata('.').name;
const srcts  = 'index.ts';
const LOCATIONS = [
  'src/index.ts',
];




// Get keywords for main/sub package.
function keywords(ds, less=false) {
  var rkind = /namespace|function/i;
  var ds = less? ds.filter(d => rkind.test(d.kind)) : ds;
  var m  = build.readMetadata('.');
  var s  = new Set([...m.keywords, ...ds.map(d => d.name)]);
  return Array.from(s);
}


// Publish a root package to NPM, GitHub.
function publishRootPackage(ds, ver, typ) {
  var _package = build.readDocument('package.json');
  var _readme  = build.readDocument('README.md');
  var m  = build.readMetadata('.');
  var md = build.readFileText('README.md');
  m.version  = ver;
  m.keywords = keywords(ds);
  if (typ) {
    m.name = `${m.name}.${typ}`;
    m.description = m.description.replace(/\.$/, ` {${typ}}.`);
    md = md.replace(/(unpkg\.com\/)(\S+?)(\/\))/, `$1$2.${typ}$3`);
  }
  build.writeMetadata('.', m);
  build.writeFileText('README.md', md);
  build.publish('.');
  try { build.publishGithub('.', owner); }
  catch {}
  build.writeDocument(_package);
  build.writeDocument(_readme);
}


// Transform JSDoc in .d.ts file.
function transformJsdoc(x, dm) {
  if (!dm.has(x.name)) return null;
  var link = `[📘](https://github.com/${owner}/${repo}/wiki/${x.name})`;
  x.description = x.description.replace(/\[📘\]\(.+?\)/g, '');
  x.description = x.description.trim() + '\n' + link;
  return x;
}


// Bundle script for test or publish.
function bundleScript(ds) {
  var dm = new Map(ds.map(d => [d.name, d]));
  build.exec(`tsc`);
  build.bundleScript(`.build/${srcts}`);
  build.jsdocifyScript('index.d.ts', 'index.d.ts', x => transformJsdoc(x, dm));
}


// Publish root packages to NPM, GitHub.
function publishRootPackages(ds, ver) {
  var m   = build.readMetadata('.');
  var sym = build.symbolname(m.name);
  bundleScript(ds);
  publishRootPackage(ds, ver, '');
  build.webifyScript('index.mjs', 'index.mjs', {format: 'esm'});
  build.webifyScript('index.js',  'index.js',  {format: 'cjs', symbol: sym});
  publishRootPackage(ds, ver, 'web');
}


// Publish docs.
function publishDocs(ds) {
  build.updateGithubRepoDetails({owner, repo, topics: keywords(ds, true)});
  build.generateDocs(`src/${srcts}`);
  build.publishDocs();
}


// Pushish root, sub packages to NPM, GitHub.
function publishPackages(ds) {
  var m   = build.readMetadata('.');
  var ver = build.nextUnpublishedVersion(m.name, m.version);
  publishRootPackages(ds, ver);
}


// Generate wiki for all exported symbols.
function generateWiki(ds) {
  var rkind = /namespace|function/i, useWiki = true;
  var dm = new Map(ds.map(d => [d.name, d]));
  for (var d of ds) {
    var f = `wiki/${d.name}.md`;
    if (!rkind.test(d.kind)) continue;
    if (!fs.existsSync(f))  {
      var txt = build.wikiMarkdown(d, {owner, repo, useWiki});
      build.writeFileText(f, txt);
    }
    else {
      var txt = build.readFileText(f);
      txt = build.wikiUpdateDescription(txt, d);
      txt = build.wikiUpdateCodeReference(txt, d, {owner, repo, useWiki})
      txt = build.wikiUpdateLinkReferences(txt, dm, {owner, repo, useWiki});
      build.writeFileText(f, txt);
    }
  }
}


// Get README index descriptions.
function readmeDescription(d) {
  var rkind = /namespace|function/i;
  var sname = /a?sync$/i;
  if (!rkind.test(d.kind)) return '';
  if (sname.test(d.name) && d.name!=='spawnAsync') return '';
  var a = d.description.replace(/The.+method/, 'This method');
  a = a.replace(', with command-line arguments in ', ' and ');
  a = a.replace(/(\S)`(.*?)`/, '$1 `$2`');
  return a;
}


// Sort docs details by original order.
function compareLocation(a, b) {
  if (a.kind!==b.kind) return 0;
  var alocn = a.location.replace(/.*?@types\/node.*?\:/, 'src/_file.ts:');
  var blocn = b.location.replace(/.*?@types\/node.*?\:/, 'src/_file.ts:');
  var [afile] = alocn.split(':');
  var [bfile] = blocn.split(':');
  return LOCATIONS.indexOf(afile) - LOCATIONS.indexOf(bfile) || alocn.localeCompare(blocn);
}


// Update README.
function updateReadme(ds) {
  var m  = build.readMetadata('.');
  var repo = m.name;
  var ds = ds.slice().sort(compareLocation);
  var dm = new Map(ds.map(d => [d.name, d]));
  var txt = build.readFileText('README.md');
  txt = build.wikiUpdateIndex(txt, dm, readmeDescription);
  txt = build.wikiUpdateLinkReferences(txt, dm, {owner, repo, useWiki: true});
  build.writeFileText('README.md', txt);
}


// Finally.
function main(a) {
  var p  = build.loadDocs([`src/${srcts}`]);
  var ds = p.children.map(build.docsDetails);
  if (a[2]==='wiki') generateWiki(ds);
  else if (a[2]==='readme') updateReadme(ds);
  else if (a[2]==='publish-docs') publishDocs(ds);
  else if (a[2]==='publish-packages') publishPackages(ds);
  else bundleScript(ds);
}
main(process.argv);