"use strict";
/* Socket Lib - Built with rolldown */
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const require_primordials_error = require('../primordials/error.js');
const require_primordials_string = require('../primordials/string.js');
const require_integrity = require('../integrity.js');
const require_primordials_array = require('../primordials/array.js');
const require_primordials_object = require('../primordials/object.js');
const require_fs_read_json = require('../fs/read-json.js');

//#region src/external-tools/manifest.ts
/**
* @file Reader for `external-tools.json` — the fleet manifest describing
*   downloadable external binaries (sfw, zizmor, etc.) with pinned versions,
*   per-platform asset names, and integrity hashes. The manifest itself is
*   hand-maintained in each fleet repo's root (`<repo>/external-tools.json`)
*   and consumed by the setup-and-install GitHub action. This reader gives
*   in-process consumers (external- tools resolvers, ad-hoc scripts) the same
*   typed view without each one re-implementing the JSON-parse + shape check +
*   integrity-string validation. Shape: { "<tool-name>": { "description":
*   "human-readable summary", "version": "1.7.2", "release": "asset" |
*   "tarball" | ..., "repository": "github:owner/repo", "notes": [...],
*   "checksums": { "<platform-arch>": { "asset": "<asset-filename>",
*   "integrity": "sha256-base64=" } } } } Some tools have flavor variants (e.g.
*   sfw's `free` / `enterprise`) that wrap the `{repository, binaryName,
*   checksums}` triple under a flavor key. Use `getToolFlavor` for those. Some
*   entries (e.g. `rust`) describe a system tool with a different shape —
*   they're skipped by `getTool` and fully readable only via the raw
*   `readManifest` returning unknown.
*/
/**
* Lookup helper — return the plain tool entry for `toolName`, or `undefined` if
* the manifest doesn't have it or the entry is flavored / other-shape.
*/
function getTool(manifest, toolName) {
	const entry = manifest.tools[toolName];
	return entry?.kind === "tool" ? entry.entry : void 0;
}
/**
* Lookup helper — return the specific flavor of a flavored tool, or `undefined`
* if the tool isn't flavored or the flavor doesn't exist.
*/
function getToolFlavor(manifest, toolName, flavor) {
	const entry = manifest.tools[toolName];
	if (entry?.kind !== "flavored") return;
	return entry.entry.flavors[flavor];
}
function isObject(value) {
	return typeof value === "object" && value !== null && !require_primordials_array.ArrayIsArray(value);
}
function parseChecksum(raw, toolName, platformKey) {
	if (!isObject(raw)) throw new require_primordials_error.ErrorCtor(`external-tools.json: tool '${toolName}' checksum entry '${platformKey}' must be an object, got: ${typeof raw}`);
	const r = raw;
	if (typeof r.asset !== "string" || r.asset.length === 0) throw new require_primordials_error.ErrorCtor(`external-tools.json: tool '${toolName}' platform '${platformKey}' is missing a non-empty 'asset' string`);
	if (typeof r.integrity !== "string" || !require_integrity.isIntegrityString(r.integrity)) throw new require_primordials_error.ErrorCtor(`external-tools.json: tool '${toolName}' platform '${platformKey}' has an invalid 'integrity' (expected SRI sha512 or sha256 form): ${r.integrity}`);
	return {
		asset: r.asset,
		integrity: r.integrity
	};
}
function parseChecksums(raw, toolName) {
	if (!isObject(raw)) throw new require_primordials_error.ErrorCtor(`external-tools.json: tool '${toolName}' is missing a 'checksums' object`);
	const out = {};
	for (const platformKey of require_primordials_object.ObjectKeys(raw)) out[platformKey] = parseChecksum(raw[platformKey], toolName, platformKey);
	return out;
}
function parseToolEntry(raw, toolName) {
	if (!isObject(raw)) return {
		kind: "other",
		raw
	};
	const r = raw;
	if (isObject(r.checksums)) {
		if (typeof r.description !== "string" || typeof r.version !== "string" || typeof r.release !== "string" || typeof r.repository !== "string") return {
			kind: "other",
			raw
		};
		return {
			kind: "tool",
			entry: {
				description: r.description,
				version: r.version,
				release: r.release,
				repository: r.repository,
				binaryName: typeof r.binaryName === "string" ? r.binaryName : void 0,
				notes: require_primordials_array.ArrayIsArray(r.notes) ? r.notes : void 0,
				checksums: parseChecksums(r.checksums, toolName)
			}
		};
	}
	const flavored = tryParseFlavored(raw, toolName);
	if (flavored) return {
		kind: "flavored",
		entry: flavored
	};
	return {
		kind: "other",
		raw
	};
}
/**
* Read an `external-tools.json` file from disk and return the parsed manifest.
* Throws on malformed JSON or invalid integrity strings; unknown-shape entries
* (rust components, future variants) come back as `{kind: 'other', raw}` so
* callers can handle them out-of-band without blocking the manifest read.
*/
async function readExternalToolsManifest(filepath) {
	const raw = await /* @__PURE__ */ require_fs_read_json.readJson(filepath);
	if (!isObject(raw)) throw new require_primordials_error.ErrorCtor(`external-tools.json: expected top-level object, got: ${typeof raw}`);
	const tools = {};
	for (const toolName of require_primordials_object.ObjectKeys(raw)) {
		if (require_primordials_string.StringPrototypeStartsWith(toolName, "$")) continue;
		tools[toolName] = parseToolEntry(raw[toolName], toolName);
	}
	return { tools };
}
function tryParseFlavored(raw, toolName) {
	const flavors = {};
	for (const key of require_primordials_object.ObjectKeys(raw)) {
		const value = raw[key];
		if (!isObject(value)) continue;
		const rf = value;
		if (!isObject(rf.checksums)) continue;
		if (typeof rf.repository !== "string") continue;
		flavors[key] = {
			repository: rf.repository,
			binaryName: typeof rf.binaryName === "string" ? rf.binaryName : void 0,
			checksums: parseChecksums(rf.checksums, `${toolName}.${key}`)
		};
	}
	if (require_primordials_object.ObjectKeys(flavors).length === 0) return;
	return {
		description: String(raw["description"] ?? ""),
		version: String(raw["version"] ?? ""),
		release: String(raw["release"] ?? ""),
		notes: require_primordials_array.ArrayIsArray(raw["notes"]) ? raw["notes"] : void 0,
		flavors
	};
}

//#endregion
exports.getTool = getTool;
exports.getToolFlavor = getToolFlavor;
exports.isObject = isObject;
exports.parseChecksum = parseChecksum;
exports.parseChecksums = parseChecksums;
exports.parseToolEntry = parseToolEntry;
exports.readExternalToolsManifest = readExternalToolsManifest;
exports.tryParseFlavored = tryParseFlavored;