feat: release design system engine, studio and component contracts
This commit is contained in:
1 parent
ff1065fb27
commit
3943b946d6
693 files changed
+175546
-3894
No files matched your search
@@ -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:");
|
||||
|
||||
Reference in new issue
Block a user