feat: release design system engine, studio and component contracts

This commit is contained in:
Clintchiz committed 2026-10-19 13:09:03 +05:30
1 parent ff1065fb27
commit 3943b946d6
693 files changed
+175546 -3894

No files matched your search

+61 -8
View File
@@ -24,14 +24,23 @@ import {
rmSync,
writeFileSync,
} from "node:fs";
import { dirname, join } from "node:path";
import { basename, dirname, join, resolve } from "node:path";
import { fileURLToPath } from "node:url";
import process from "node:process";
import { validateAndHashStage, type StagedPackageIntegrity } from "./lib/package-integrity.ts";
const repoRoot = join(dirname(fileURLToPath(import.meta.url)), "..");
const packagesDir = join(repoRoot, "packages");
const stageRoot = join(repoRoot, ".publish");
const stageArgument =
process.argv.find((arg) => arg.startsWith("--stage-root="))?.slice(13) ?? ".publish";
const stageRoot = resolve(repoRoot, stageArgument);
if (
dirname(stageRoot) !== resolve(repoRoot) ||
!/^\.publish(?:-[a-z0-9-]+)?$/.test(basename(stageRoot))
)
throw Error(
"Stage root must be a .publish or .publish-NAME directory directly inside this workspace.",
);
const REGISTRY = process.env.WRNEXUS_NPM_REGISTRY ?? "https://registry.npmjs.org/";
// First release is published PRIVATE ("restricted") so we can test before the
// world sees it; flip to public with `npm access public @wrnexus/<name>` (or set
@@ -44,6 +53,7 @@ const HOMEPAGE = "https://wrnexusjs.dev";
/** Extra (non-code) files each package must ship, relative to the package root. */
const ASSETS: Record<string, string[]> = {
"@wrnexus/design-studio": ["assets"],
"@wrnexus/ui": [
"components",
"styles",
@@ -97,7 +107,11 @@ function topoSort(pkgs: Pkg[]): Pkg[] {
const visit = (p: Pkg) => {
if (seen.has(p.name)) return;
seen.add(p.name);
for (const dep of Object.keys(p.manifest.dependencies ?? {})) {
for (const dep of Object.keys({
...p.manifest.dependencies,
...p.manifest.optionalDependencies,
...p.manifest.peerDependencies,
})) {
const d = byName.get(dep);
if (d) visit(d);
}
@@ -121,6 +135,7 @@ function entriesOf(dir: string, m: Record<string, any>): Record<string, string>
map[rel] = join(dir, v.replace(/^\.\//, "")).replace(/\\/g, "/");
};
add(m.main);
for (const runtime of m.wrnexus?.clientRuntimes ?? []) add(runtime.entry);
if (m.bin) Object.values(m.bin).forEach(add);
if (m.exports) for (const v of Object.values(m.exports)) add(v);
if (m.wrnexus?.plugin) {
@@ -205,6 +220,8 @@ function publishManifest(
out.exports = { ".": { types: out.types, import: out.main } };
}
if (m.peerDependenciesMeta) out.peerDependenciesMeta = m.peerDependenciesMeta;
if (m.bin) {
out.bin = {};
for (const [k, v] of Object.entries(m.bin)) out.bin[k] = js(v as string);
@@ -223,6 +240,11 @@ function publishManifest(
if (m.wrnexus) {
out.wrnexus = structuredClone(m.wrnexus);
for (const runtime of out.wrnexus.clientRuntimes ?? []) {
if (typeof runtime.entry === "string" && runtime.entry.endsWith(".ts")) {
runtime.entry = js(runtime.entry);
}
}
const plugin = out.wrnexus?.plugin?.plugin;
if (typeof plugin === "string" && plugin.endsWith(".ts")) {
out.wrnexus.plugin.plugin = js(plugin);
@@ -237,7 +259,9 @@ function publishManifest(
}
async function main() {
const filter = process.argv.slice(2);
const filter = process.argv
.slice(2)
.filter((arg) => !arg.startsWith("--stage-root=") && arg !== "--with-dependencies");
const allPackages = readPackages([]);
const workspaceVersions = new Map(
allPackages.map((pkg) => [pkg.name, String(pkg.manifest.version)]),
@@ -247,6 +271,22 @@ async function main() {
(pkg) => filter.includes(pkg.dir.split(/[\\/]/).pop()!) || filter.includes(pkg.name),
)
: allPackages;
if (process.argv.includes("--with-dependencies")) {
const visited = new Set(selected.map((pkg) => pkg.name));
for (let index = 0; index < selected.length; index++) {
for (const name of Object.keys({
...selected[index]!.manifest.dependencies,
...selected[index]!.manifest.optionalDependencies,
...selected[index]!.manifest.peerDependencies,
})) {
if (!name.startsWith("@wrnexus/") || visited.has(name)) continue;
const dependency = allPackages.find((pkg) => pkg.name === name);
if (!dependency) throw Error(`Missing workspace dependency ${name}.`);
visited.add(name);
selected.push(dependency);
}
}
}
const pkgs = topoSort(selected);
if (!pkgs.length) {
console.error("No @wrnexus packages matched.");
@@ -265,7 +305,7 @@ async function main() {
entry: entries,
outDir: join(p.dir, "dist"),
format: ["esm"],
dts: true,
dts: { compilerOptions: { ignoreDeprecations: "6.0" } },
external: [
/^@wrnexus\//,
/^bun:/,
@@ -307,9 +347,20 @@ async function main() {
for (const a of packageAssets(p.manifest)) {
if (existsSync(join(p.dir, a))) cpSync(join(p.dir, a), join(stage, a), { recursive: true });
}
if (p.name === "@wrnexus/design-studio") {
const browser = await Bun.build({
entrypoints: [join(p.dir, "src", "client.ts")],
target: "browser",
minify: true,
});
if (!browser.success || browser.outputs.length !== 1)
throw Error("Studio browser asset build failed.");
mkdirSync(join(stage, "assets"), { recursive: true });
writeFileSync(join(stage, "assets", "studio-client.js"), await browser.outputs[0]!.text());
}
const manifest = publishManifest(p.manifest, p.manifest.version, workspaceVersions);
writeFileSync(join(stage, "package.json"), JSON.stringify(manifest, null, 2) + "\n");
if (p.manifest.wrnexus && !manifest.wrnexus?.plugin?.plugin) {
if (p.manifest.wrnexus?.plugin && !manifest.wrnexus?.plugin?.plugin) {
throw new Error(`${p.name} lost its wrnexus.plugin metadata while staging.`);
}
for (const asset of packageAssets(p.manifest)) {
@@ -347,11 +398,13 @@ async function main() {
);
console.log(
`\n✓ Staged and verified ${order.length} package(s) under .publish/ (access: ${ACCESS})`,
`\n✓ Staged and verified ${order.length} package(s) under ${basename(stageRoot)}/ (access: ${ACCESS})`,
);
console.log("Publish order (deps first):");
for (const n of order) {
console.log(` npm publish .publish/${n.replace("@wrnexus/", "")} --access ${ACCESS}`);
console.log(
` npm publish ${basename(stageRoot)}/${n.replace("@wrnexus/", "")} --access ${ACCESS}`,
);
}
if (ACCESS === "restricted") {
console.log("\nAfter testing, flip every package to public with:");