← Files FreakUIARCHIVED FILE

skills/create-app/scripts/materialize-blueprint.mjs

12.5 KB · Sep 30, 2026 · 23:02 UTC

↓ Download file

#!/usr/bin/env node

import { createHash, randomUUID } from "node:crypto";
import {
  access,
  mkdir,
  readFile,
  readdir,
  rename,
  rm,
  rmdir,
  stat,
  writeFile,
} from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import process from "node:process";
import { pathToFileURL } from "node:url";

const CONTRACT_VERSION = 1;
const RECIPE_VERSION = "1.1.1";
const CORE_VERSION = "0.5.0-beta";
const SHA256 = /^[a-f0-9]{64}$/u;

export class MaterializationError extends Error {
  constructor(code, message, suggestion) {
    super(message);
    this.name = "MaterializationError";
    this.code = code;
    this.suggestion = suggestion;
  }
}

function fail(code, message, suggestion) {
  throw new MaterializationError(code, message, suggestion);
}

function sha256(value) {
  return createHash("sha256").update(value).digest("hex");
}

function sortValue(value) {
  if (Array.isArray(value)) {
    return value.map(sortValue);
  }
  if (value !== null && typeof value === "object") {
    return Object.fromEntries(
      Object.entries(value)
        .sort(([left], [right]) => left.localeCompare(right))
        .map(([key, entry]) => [key, sortValue(entry)]),
    );
  }
  return value;
}

export function canonicalJson(value) {
  return `${JSON.stringify(sortValue(value), null, 2)}\n`;
}

function requireObject(value, label) {
  if (value === null || typeof value !== "object" || Array.isArray(value)) {
    fail("INVALID_BLUEPRINT", `${label} must be an object.`);
  }
  return value;
}

function requireExactKeys(value, expected, label) {
  const keys = Object.keys(value).sort();
  const allowed = [...expected].sort();
  if (keys.length !== allowed.length || keys.some((key, index) => key !== allowed[index])) {
    fail(
      "INVALID_BLUEPRINT",
      `${label} has an unexpected shape. Expected keys: ${allowed.join(", ")}.`,
    );
  }
}

function requireString(value, label) {
  if (typeof value !== "string" || value.length === 0) {
    fail("INVALID_BLUEPRINT", `${label} must be a nonempty string.`);
  }
  return value;
}

function requireSha(value, label) {
  if (typeof value !== "string" || !SHA256.test(value)) {
    fail("INVALID_BLUEPRINT", `${label} must be a lowercase SHA-256 checksum.`);
  }
  return value;
}

function validateRelativePath(value, label) {
  const candidate = requireString(value, label);
  if (
    candidate.includes("\\") ||
    path.posix.isAbsolute(candidate) ||
    path.posix.normalize(candidate) !== candidate ||
    candidate === "." ||
    candidate.split("/").some((part) => part === "" || part === "." || part === "..")
  ) {
    fail("UNSAFE_PATH", `${label} must be a normalized relative POSIX path.`);
  }
  return candidate;
}

function assertInside(root, candidate, label) {
  const relative = path.relative(root, candidate);
  if (relative === "" || relative.startsWith(`..${path.sep}`) || relative === ".." || path.isAbsolute(relative)) {
    fail("UNSAFE_PATH", `${label} escapes the staging directory.`);
  }
}

export function validateEnvelope(rawEnvelope) {
  const envelope = requireObject(rawEnvelope, "structuredContent");
  requireExactKeys(envelope, ["requestId", "resultSha256", "blueprint"], "structuredContent");
  requireString(envelope.requestId, "requestId");
  requireSha(envelope.resultSha256, "resultSha256");

  const blueprint = requireObject(envelope.blueprint, "blueprint");
  requireExactKeys(
    blueprint,
    [
      "contractVersion",
      "recipeVersion",
      "freakUICoreVersion",
      "requestSha256",
      "rootDirectoryName",
      "files",
      "requiredLocalAssets",
    ],
    "blueprint",
  );

  if (blueprint.contractVersion !== CONTRACT_VERSION) {
    fail("UNSUPPORTED_CONTRACT", `Expected contract ${CONTRACT_VERSION}.`);
  }
  if (blueprint.recipeVersion !== RECIPE_VERSION) {
    fail("UNSUPPORTED_RECIPE", `Expected recipe ${RECIPE_VERSION}.`);
  }
  if (blueprint.freakUICoreVersion !== CORE_VERSION) {
    fail("UNSUPPORTED_CORE", `Expected FreakUI Core ${CORE_VERSION}.`);
  }
  requireSha(blueprint.requestSha256, "blueprint.requestSha256");
  requireString(blueprint.rootDirectoryName, "blueprint.rootDirectoryName");

  if (!Array.isArray(blueprint.files) || blueprint.files.length === 0) {
    fail("INVALID_BLUEPRINT", "blueprint.files must be a nonempty array.");
  }
  if (!Array.isArray(blueprint.requiredLocalAssets)) {
    fail("INVALID_BLUEPRINT", "blueprint.requiredLocalAssets must be an array.");
  }

  const outputPaths = new Set();
  for (const [index, rawFile] of blueprint.files.entries()) {
    const file = requireObject(rawFile, `blueprint.files[${index}]`);
    requireExactKeys(file, ["path", "content", "encoding", "sha256"], `blueprint.files[${index}]`);
    const filePath = validateRelativePath(file.path, `blueprint.files[${index}].path`);
    if (outputPaths.has(filePath)) {
      fail("DUPLICATE_PATH", `Blueprint path “${filePath}” appears more than once.`);
    }
    outputPaths.add(filePath);
    if (file.encoding !== "utf8") {
      fail("INVALID_BLUEPRINT", `Blueprint file “${filePath}” must use UTF-8 encoding.`);
    }
    if (typeof file.content !== "string") {
      fail("INVALID_BLUEPRINT", `Blueprint file “${filePath}” must contain text.`);
    }
    const expected = requireSha(file.sha256, `blueprint.files[${index}].sha256`);
    if (sha256(Buffer.from(file.content, "utf8")) !== expected) {
      fail("BLUEPRINT_CHECKSUM_MISMATCH", `Blueprint file “${filePath}” failed its checksum.`);
    }
  }

  for (const [index, rawAsset] of blueprint.requiredLocalAssets.entries()) {
    const asset = requireObject(rawAsset, `blueprint.requiredLocalAssets[${index}]`);
    requireExactKeys(
      asset,
      ["kind", "fileName", "targetPath", "sha256"],
      `blueprint.requiredLocalAssets[${index}]`,
    );
    if (asset.kind !== "font") {
      fail("INVALID_BLUEPRINT", `Local asset ${index} must be a font.`);
    }
    const fileName = requireString(asset.fileName, `blueprint.requiredLocalAssets[${index}].fileName`);
    if (path.basename(fileName) !== fileName || !/\.(?:otf|ttf)$/iu.test(fileName)) {
      fail("UNSAFE_PATH", `Local font “${fileName}” must be a .otf or .ttf filename without a path.`);
    }
    const targetPath = validateRelativePath(
      asset.targetPath,
      `blueprint.requiredLocalAssets[${index}].targetPath`,
    );
    if (outputPaths.has(targetPath)) {
      fail("DUPLICATE_PATH", `Blueprint output path “${targetPath}” is duplicated.`);
    }
    outputPaths.add(targetPath);
    requireSha(asset.sha256, `blueprint.requiredLocalAssets[${index}].sha256`);
  }

  if (sha256(canonicalJson(blueprint)) !== envelope.resultSha256) {
    fail("RESULT_CHECKSUM_MISMATCH", "The blueprint envelope does not match resultSha256.");
  }

  return envelope;
}

async function exists(target) {
  try {
    await access(target);
    return true;
  } catch {
    return false;
  }
}

async function assertDestinationAvailable(destination) {
  if (!(await exists(destination))) {
    return false;
  }
  const destinationStat = await stat(destination);
  if (!destinationStat.isDirectory() || (await readdir(destination)).length > 0) {
    fail(
      "DESTINATION_NOT_EMPTY",
      `Destination “${destination}” already exists and is not an empty directory.`,
      "Choose an absent or empty destination. FreakUI never overwrites or merges projects.",
    );
  }
  return true;
}

export async function materializeEnvelope(rawEnvelope, options) {
  const envelope = validateEnvelope(rawEnvelope);
  if (typeof options?.destination !== "string" || !path.isAbsolute(options.destination)) {
    fail("UNSAFE_PATH", "The destination must be an absolute path.");
  }

  const destination = path.normalize(options.destination);
  if (destination === path.parse(destination).root || destination === path.normalize(os.homedir())) {
    fail("UNSAFE_PATH", "The destination cannot be a filesystem root or the user home directory.");
  }
  if (options.assets !== undefined && !path.isAbsolute(options.assets)) {
    fail("UNSAFE_PATH", "The local asset directory must be an absolute path.");
  }

  const destinationParent = path.dirname(destination);
  await mkdir(destinationParent, { recursive: true });
  const destinationExisted = await assertDestinationAvailable(destination);
  const stage = path.join(
    destinationParent,
    `.${path.basename(destination)}.freakui-stage-${randomUUID()}`,
  );
  await mkdir(stage, { recursive: false });
  let removedEmptyDestination = false;

  try {
    for (const file of envelope.blueprint.files) {
      const output = path.join(stage, ...file.path.split("/"));
      assertInside(stage, output, `Blueprint file “${file.path}”`);
      await mkdir(path.dirname(output), { recursive: true });
      await writeFile(output, file.content, { encoding: "utf8", flag: "wx" });
    }

    for (const asset of envelope.blueprint.requiredLocalAssets) {
      if (!options.assets) {
        fail(
          "MISSING_LOCAL_ASSET",
          `Generation requires local font file “${asset.fileName}”.`,
          "Pass --assets with the folder containing the verified local font files.",
        );
      }
      const source = path.join(options.assets, asset.fileName);
      if (!(await exists(source))) {
        fail("MISSING_LOCAL_ASSET", `Local font “${source}” was not found.`);
      }
      const bytes = await readFile(source);
      if (sha256(bytes) !== asset.sha256) {
        fail(
          "ASSET_CHECKSUM_MISMATCH",
          `Local font “${asset.fileName}” does not match its approved checksum.`,
        );
      }
      const output = path.join(stage, ...asset.targetPath.split("/"));
      assertInside(stage, output, `Local font target “${asset.targetPath}”`);
      await mkdir(path.dirname(output), { recursive: true });
      await writeFile(output, bytes, { flag: "wx" });
    }

    for (const file of envelope.blueprint.files) {
      const written = await readFile(path.join(stage, ...file.path.split("/")));
      if (sha256(written) !== file.sha256) {
        fail("WRITE_VERIFICATION_FAILED", `Written file “${file.path}” failed verification.`);
      }
    }

    if (destinationExisted) {
      await rmdir(destination);
      removedEmptyDestination = true;
    }
    await rename(stage, destination);
    removedEmptyDestination = false;

    return {
      requestId: envelope.requestId,
      resultSha256: envelope.resultSha256,
      contractVersion: envelope.blueprint.contractVersion,
      recipeVersion: envelope.blueprint.recipeVersion,
      freakUICoreVersion: envelope.blueprint.freakUICoreVersion,
      destination,
      generatedFileCount: envelope.blueprint.files.length,
      localAssetCount: envelope.blueprint.requiredLocalAssets.length,
    };
  } catch (error) {
    await rm(stage, { recursive: true, force: true });
    if (removedEmptyDestination && !(await exists(destination))) {
      await mkdir(destination, { recursive: false });
    }
    throw error;
  }
}

function parseArguments(argv) {
  const options = {};
  for (let index = 0; index < argv.length; index += 1) {
    const argument = argv[index];
    if (argument === "--input" || argument === "--destination" || argument === "--assets") {
      const value = argv[index + 1];
      if (!value || value.startsWith("--")) {
        fail("INVALID_ARGUMENT", `${argument} requires a value.`);
      }
      options[argument.slice(2)] = value;
      index += 1;
    } else {
      fail("INVALID_ARGUMENT", `Unknown argument: ${argument}`);
    }
  }
  if (!options.input || !options.destination) {
    fail(
      "INVALID_ARGUMENT",
      "Usage: materialize-blueprint.mjs --input <blueprint.json> --destination <absolute-path> [--assets <absolute-path>]",
    );
  }
  return options;
}

async function main() {
  const options = parseArguments(process.argv.slice(2));
  const raw = await readFile(options.input, "utf8");
  const envelope = JSON.parse(raw);
  const result = await materializeEnvelope(envelope, options);
  process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
}

if (process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
  main().catch((error) => {
    if (error instanceof SyntaxError) {
      process.stderr.write("INVALID_JSON: The blueprint input is not valid JSON.\n");
    } else if (error instanceof MaterializationError) {
      process.stderr.write(`${error.code}: ${error.message}\n`);
      if (error.suggestion) {
        process.stderr.write(`Next step: ${error.suggestion}\n`);
      }
    } else {
      process.stderr.write(`LOCAL_WRITE_FAILED: ${error instanceof Error ? error.message : String(error)}\n`);
    }
    process.exitCode = 1;
  });
}

SHA-256: 9cf0cf0fc0efb3e2fc456afc65495dccdd7c2bf860e0b040561a503d3ac3b512