testTcmLibrariesHoldWhatTheyUse
A tcm library (npm: false): released only if its namespace holds everything its code uses, so a codebase that adds
it has every definition named; a package of its codebase that uses it carries its code rather than depending on it
from npm; and it isn't packed itself.
import { codebase } from "#codebase/tcmts/cli/test/e2e/releases"; import assert from "node:assert/strict"; import fs from "node:fs"; import path_1 from "node:path"; export const testTcmLibrariesHoldWhatTheyUse = () => { const alice = codebase("tcm library"); alice.save(`// tcm: namespace util\nexport const square = (n: number) => n * n;\n`, "add"); alice.save( `// tcm: namespace geo\nimport { square } from "#codebase/util";\nexport const manifest = { name: "geo", npm: false };\n/** A square's area. */\nexport const area = (side: number) => square(side);\n`, "add", ); // geo uses util.square, which isn't its own: a codebase adding it would have that unnamed const refused = alice.run("release", "geo"); assert.notEqual(refused.status, 0); assert.match(refused.out, /geo is a tcm library, and it uses what isn't its own: util\.square/); const checked = alice.run("release", "check", "geo"); assert.notEqual(checked.status, 0); assert.match( checked.out, /geo's first release: 0\.1\.0[\s\S]*not released as it stands: geo is a tcm library/, ); // moved in, it's released (with a README: a file kept with it, which isn't its API) alice.tcm("mv", "util.square", "geo.square"); fs.writeFileSync(alice.file("README.md"), "<!-- tcm: path geo.README -->\n# geo\n\nShapes.\n"); alice.tcm("add", "README.md"); assert.match(alice.tcm("release", "geo"), /released geo@0\.1\.0/); alice.tcm("patch", "geo.square", "--old", "n * n", "--new", "n ** 2"); const next = alice.tcm("release", "check", "geo"); assert.match(next, /geo's next release: 0\.1\.1/); assert.doesNotMatch(next, /README/); // not packed for npm, and another package of the codebase carries it rather than depending on it assert.match(alice.run("pack", "geo").out, /geo is a tcm library \(npm: false\)/); alice.save( `// tcm: namespace shapes\nimport { area } from "#codebase/geo";\nexport const manifest = { name: "shapes" };\nexport const tile = () => area(3);\n`, "add", ); alice.tcm("pack", "shapes"); const packed = path_1.join(alice.dir, ".tcm", "pack", "shapes"); const pkg = JSON.parse(fs.readFileSync(path_1.join(packed, "package.json"), "utf8")) as { dependencies?: Record<string, string>; }; assert.equal(pkg.dependencies?.geo, undefined, JSON.stringify(pkg)); // a fresh codebase adds it: every definition it brings is named there const me = codebase("adds a tcm library"); me.save(`// tcm: namespace app\nexport const greeting = "hi";\n`, "add"); assert.match(me.tcm("lib", "add", alice.dir, "geo@0.1.0"), /added app\.lib\.geo: geo@0\.1\.0/); const deps = me.tcm("deps", "app.lib.geo.area"); assert.match(deps, /app\.lib\.geo\.square/); assert.doesNotMatch(deps, /^#/m, deps); me.save( `// tcm: namespace app\nimport { area } from "#codebase/app/lib/geo";\nexport const total = () => area(4);\n`, "add", ); assert.equal(me.tcm("run", "app.total").trim(), "16"); }