sdk

Radroots SDK and bindings
git clone https://radroots.dev/git/sdk.git
Log | Files | Refs | README

radroots_sdk_artifact_lib.mjs (2517B)


      1 import { lstatSync, readFileSync, realpathSync } from "node:fs";
      2 import { isAbsolute, resolve } from "node:path";
      3 import { spawnSync } from "node:child_process";
      4 
      5 export const ARTIFACT_ROUTES = Object.freeze({
      6   typescript: Object.freeze({
      7     target: "typescript",
      8     language: "typescript",
      9     output: "contracts/provenance/sdk/typescript.json",
     10   }),
     11   wasm: Object.freeze({
     12     target: "wasm",
     13     language: "javascript",
     14     output: "contracts/provenance/sdk/wasm.json",
     15   }),
     16   swift: Object.freeze({
     17     target: "ffi",
     18     language: "swift",
     19     output: "contracts/provenance/sdk/swift.json",
     20   }),
     21   kotlin: Object.freeze({
     22     target: "ffi",
     23     language: "kotlin",
     24     output: "contracts/provenance/sdk/kotlin.json",
     25   }),
     26 });
     27 
     28 export function validateConsumerRoot(root) {
     29   const marker = readFileSync(resolve(root, ".radroots-consumer-root"), "utf8");
     30   if (marker !== "sdk\n") {
     31     throw new Error("consumer marker must contain exactly sdk followed by LF");
     32   }
     33 }
     34 
     35 export function resolveCanonicalSourceRoot(raw) {
     36   if (!raw || !isAbsolute(raw)) {
     37     throw new Error("RADROOTS_LIB_SOURCE_ROOT must be an absolute path");
     38   }
     39   const requested = resolve(raw);
     40   const metadata = lstatSync(requested);
     41   if (!metadata.isDirectory() || metadata.isSymbolicLink()) {
     42     throw new Error("RADROOTS_LIB_SOURCE_ROOT must be a real directory");
     43   }
     44   const canonical = realpathSync(requested);
     45   if (canonical !== requested) {
     46     throw new Error("RADROOTS_LIB_SOURCE_ROOT must not traverse symlinks");
     47   }
     48   return canonical;
     49 }
     50 
     51 export function artifactRoute(name) {
     52   const route = ARTIFACT_ROUTES[name];
     53   if (!route) {
     54     throw new Error(`unsupported SDK artifact route: ${name ?? "<missing>"}`);
     55   }
     56   return route;
     57 }
     58 
     59 export function run(command, args, options = {}) {
     60   const result = spawnSync(command, args, {
     61     cwd: options.cwd,
     62     env: options.env,
     63     stdio: options.capture ? "pipe" : "inherit",
     64     encoding: options.capture ? "utf8" : undefined,
     65   });
     66   if (result.error) {
     67     throw result.error;
     68   }
     69   if (result.status !== 0) {
     70     throw new Error(`${command} exited with status ${result.status ?? "unknown"}`);
     71   }
     72   return options.capture ? result.stdout.trim() : "";
     73 }
     74 
     75 export function sourceDateEpoch(sourceRoot, revision, env) {
     76   const value = run(
     77     "git",
     78     ["show", "-s", "--format=%ct", revision],
     79     { cwd: sourceRoot, env, capture: true },
     80   );
     81   if (!/^[0-9]+$/.test(value)) {
     82     throw new Error("canonical source commit timestamp is invalid");
     83   }
     84   return value;
     85 }