testLibrariesFromAnotherCodebase

tcmts.cli.test.e2e.libraries.testLibrariesFromAnotherCodebase · #5qdap3id · term

a library is another codebase's release (or namespace, by hash), mounted read-only: code uses it like its own, its packages stay its own, it's removed only when nothing uses it, and it travels with history

import { codebase } from "#codebase/tcmts/cli/test/e2e/releases";
import assert from "node:assert/strict";

export const testLibrariesFromAnotherCodebase = () => {
  const alice = codebase("alice");
  alice.save(
    `// tcm: namespace geo\nexport const manifest = { name: "geo" };\n/** A square's area. */\nexport const area = (side: number) => side * side;\nexport const double = (side: number) => 2 * area(side);\n`,
    "add",
  );
  alice.tcm("release", "geo@1.0.0");

  const me = codebase("me");
  me.save(`// tcm: namespace app\nexport const greeting = "hi";\n`, "add");
  // in the project's root namespace, by its newest release, everything it uses received and checked
  assert.match(
    me.tcm("lib", "add", alice.dir, "geo"),
    /added app\.lib\.geo: geo@1\.0\.0 from .*\(3 names; 3 definitions received/,
  );
  assert.match(me.tcm("lib"), /app\.lib\.geo {2}geo@1\.0\.0 {2}from /);
  assert.match(me.tcm("history", "1"), /lib add app\.lib\.geo\n(.*\n)*\s+app\.lib\.libraries +\+/);
  // code uses it like its own
  me.save(
    `// tcm: namespace app\nimport { area, double } from "#codebase/app/lib/geo";\nexport const total = () => area(2) + double(3);\n`,
    "add",
  );
  assert.equal(me.tcm("run", "app.total").trim(), "22");
  // and its package is its own, not this codebase's
  assert.match(me.tcm("releases"), /no packages yet/);

  // read-only: its names, and the record saying what it is
  const patched = me.run("patch", "app.lib.geo.area", "--old", "side * side", "--new", "side ** 2");
  assert.notEqual(patched.status, 0);
  assert.match(
    patched.out,
    /app\.lib\.geo\.area is in the library app\.lib\.geo \(geo@1\.0\.0\), which is read-only/,
  );
  assert.match(me.run("mv", "app.lib.geo", "app.geo").out, /read-only/);
  assert.match(me.run("rm", "app.lib.libraries").out, /records the libraries mounted beside it/);
  // a copy of its own changes; the library keeps what it had
  me.tcm("alias", "app.lib.geo.area", "app.myArea");
  me.tcm("patch", "app.myArea", "--old", "side * side", "--new", "side * side + 1");
  assert.match(
    me.tcm("view", "app.lib.geo.double"),
    /import \{ area \} from "#codebase\/app\/lib\/geo"/,
  );
  assert.match(me.tcm("lib"), /geo@1\.0\.0 {2}from [^\n]*$/m);
  assert.doesNotMatch(me.tcm("lib"), /aren't the namespace/);

  // by its namespace's hash, wherever it's asked for; removed again, as nothing uses what only it names
  const hash = /"namespace": "(\w+)"/.exec(me.tcm("view", "app.lib.libraries"))![1]!;
  // (a hash names no package to be called after: it says so, and is called what it's told)
  assert.match(
    me.run("lib", "add", alice.dir, `#${hash}`).out,
    /a library by hash has no package to be called after: say what to call it \(--as <name>\)/,
  );
  assert.match(
    me.run("lib", "add", alice.dir).out,
    /which library\? tcm lib add .* <package>\[@<version>\]/,
  );
  assert.match(
    me.tcm("lib", "add", alice.dir, `#${hash}`, "--as", "copy", "--at", "vendor.geo"),
    /added vendor\.geo: #\w{8} from /,
  );
  assert.match(
    me.run("lib", "add", alice.dir, "geo", "--at", "vendor.geo").out,
    /vendor\.geo is in the library vendor\.geo/,
  );
  assert.match(me.tcm("lib", "rm", "vendor.geo"), /removed vendor\.geo \(3 names\)/);
  assert.match(me.tcm("ls", "vendor"), /nothing under vendor/);
  // but not while code uses it
  assert.match(me.run("lib", "rm", "geo").out, /app\.lib\.geo is used by app\.total/);
  assert.match(
    me.run("lib", "add", alice.dir, "geo").out,
    /app\.lib\.geo is in the library app\.lib\.geo/,
  );
  assert.match(
    me.run("lib", "add", alice.dir, "geo@9.9.9", "--at", "old.geo").out,
    /has no geo@9\.9\.9; it has 1\.0\.0/,
  );
  // and formatting leaves it as it was released
  assert.match(me.tcm("fmt"), /no hashes changed/);

  // a codebase pulling this one has it too, as read-only there
  const other = codebase("other");
  other.tcm("remote", "add", "origin", me.dir);
  other.tcm("pull");
  assert.match(other.tcm("lib"), /app\.lib\.geo {2}geo@1\.0\.0/);
  assert.match(other.run("rm", "app.lib.geo.double", "--force").out, /read-only/);
}

uses