tunnckoCore / asia

:eight_spoked_asterisk: Blazingly fast, magical and minimalist testing framework for Today :date: and Tomorrow :crystal_ball: Try `npm i -D asia@next` for pre-v1
Apache License 2.0
1 stars 0 forks source link

monorepo tools: resolves workspaces and make runners #76

Open tunnckoCore opened 2 years ago

tunnckoCore commented 2 years ago
import path from "node:path";
import fastGlob from "fast-glob";
import fs from "node:fs/promises";
import { serial, parallel } from "@tunnckocore/p-all";

import Tinypool from "tinypool";

// const map = {
//   "@hela/core": {
//     resolved: "projects/hela/core",
//   },
//   yaro: {
//     resolved: "packages/yaro",
//     dependencies: ["@hela/core"],
//   },
// };

async function readJSON(filepath) {
  return JSON.parse(await fs.readFile(filepath, "utf-8"));
}

const stream = fastGlob.stream([
  // "packages/@tunnckocore/*/package.json", // ! works
  // "projects/@hela/*/package.json", // ! works
  "@tunnckocore/*/package.json",
  "@hela/*/package.json",
  "packages/*/package.json",
  "configs/*/package.json",
]);

const packagesRoots = {};
const graph = {};

for await (const pkgJsonPath of stream) {
  const pkgRoot = path.dirname(pkgJsonPath);
  const {
    name,
    dependencies = {},
    engines = {}, // ? should we?
    license,
    version,
  } = await readJSON(pkgJsonPath);

  graph[name] = {
    name,
    resolved: pkgRoot,
    dependencies,
    engines,
    license,
    version,
  };
}

for (const item of Object.values(graph)) {
  const requiredDeps = Object.keys(item.dependencies);
  requiredDeps.forEach((depName) => {
    if (graph[depName]) {
      graph[depName].dependents = graph[depName].dependents ?? [];
      graph[depName].dependents.push({
        name: item.name,
        resolved: item.resolved,
        dependents: item.dependents,
      });
    }
  });
}

const workspacesResolved = Object.values(graph).map((x) => x.resolved);

console.log(JSON.stringify(graph, null, 2));

console.log(
  "Workspaces resolved (%s):",
  workspacesResolved.length,
  workspacesResolved
);

const affected = [];

async function affectedOf(name) {
  const pkgMeta = graph[name];
  affected.push(pkgMeta.resolved);

  if (pkgMeta.dependents) {
    await serial(pkgMeta.dependents, async ({ value: dependent }) => {
      await affectedOf(dependent.name);
    });
  }
}

await affectedOf("@tunnckocore/p-all");
console.log("Affected of @tunnckocore/p-all (%s):", affected.length, affected);

const pool = new Tinypool({
  filename: new URL(`./worker.js`, import.meta.url).href,
  minThreads: 4,
  maxThreads: 8,
});

await parallel(affected, ({ value: fp }) => {
  const url = new URL(`./${fp}`, import.meta.url);

  return pool
    .run({ min: 400, max: 4000, filepath: url.pathname })
    .then((x) => console.log(url.pathname, "done", x));
});

// console.log(new URL(`./packages/asia-core`, import.meta.url));