"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_array = require('../primordials/array.js');
const require_primordials_json = require('../primordials/json.js');
const require_promises_retry = require('../promises/retry.js');
const require_http_request_request = require('../http-request/request.js');
const require_releases_github_assets = require('./github-assets.js');
const require_releases_github_auth = require('./github-auth.js');
const require_releases_github_retry_config = require('./github-retry-config.js');

//#region src/releases/github-asset-url.ts
/**
* @file Per-release asset-URL discovery for GitHub releases. Split out of
*   `releases/github-api.ts` for size hygiene. Holds the "fetch this specific
*   tag's downloadable asset URL" path (REST with GraphQL fallback for ES-index
*   incidents):
*
*   - `fetchReleaseAssetsViaGraphQL` — GraphQL fallback when REST's per-tag
*     endpoint returns 200 + empty body
*   - `getReleaseAssetUrl` — REST per-tag lookup + pattern matcher + GraphQL
*     fallback The list-all-releases path lives in `./github-listing`.
*/
/**
* Fetch the assets of a single release identified by tag via GraphQL.
*
* Why this exists: `getReleaseAssetUrl` uses REST `/releases/tags/:tag` to look
* up a single release and find a downloadable asset. During GitHub incidents
* that endpoint can return 200 + empty body the same way the listing endpoint
* does (the per-tag lookup joins against the same listing index for asset
* discovery). This helper hits GraphQL `repository.release(tagName)` which uses
* a different backend.
*
* Field shape diff we normalize: GraphQL returns REST equivalent
* `releaseAssets.nodes[].downloadUrl` `assets[].browser_download_url`
*
* Same URL, different field name and one extra connection-wrapper level. The
* mapping at the bottom converts so the asset-matcher in `getReleaseAssetUrl`
* can run unchanged.
*
* Return contract:
*
* - Array of assets (REST shape) when the release exists.
* - `undefined` when the release with that tag genuinely doesn't exist (GraphQL
*   returned `release: null` over the wire — we translate that to undefined per
*   the codebase convention). The caller throws a clean "tag not found" error
*   in that case.
* - Throws on transport errors (non-OK HTTP, GraphQL errors[], or even the
*   GraphQL backend ALSO returning empty body — at that point both transports
*   are degraded and we want the pRetry wrapper to back off and retry).
*/
async function fetchReleaseAssetsViaGraphQL(owner, repo, tag) {
	const response = await require_http_request_request.httpRequest("https://api.github.com/graphql", {
		body: require_primordials_json.JSONStringify({
			query: `query($owner: String!, $repo: String!, $tag: String!) {
        repository(owner: $owner, name: $repo) {
          release(tagName: $tag) {
            tagName
            releaseAssets(first: 100) { nodes { name downloadUrl } }
          }
        }
      }`,
			variables: {
				owner,
				repo,
				tag
			}
		}),
		headers: {
			...require_releases_github_auth.getAuthHeaders(),
			"Content-Type": "application/json"
		},
		method: "POST"
	});
	if (!response.ok) throw new require_primordials_error.ErrorCtor(`Failed to fetch ${owner}/${repo} release ${tag} (GraphQL): ${response.status} ${response.statusText}`);
	if (response.body.byteLength === 0) throw new require_primordials_error.ErrorCtor(`Failed to fetch ${owner}/${repo} release ${tag}: GraphQL returned empty body`);
	let parsed;
	try {
		parsed = require_primordials_json.JSONParse(response.body.toString("utf8"));
	} catch (cause) {
		throw new require_primordials_error.ErrorCtor(`Failed to parse ${owner}/${repo} release ${tag} response (GraphQL)`, { cause });
	}
	/* c8 ignore next 4 */
	if (parsed.errors?.length) throw new require_primordials_error.ErrorCtor(`GraphQL repository.release(${owner}/${repo}, ${tag}) returned errors: ${parsed.errors.map((e) => e.message).join("; ")}`);
	const release = parsed.data?.repository?.release;
	if (!release) return;
	/* c8 ignore start */
	return (release.releaseAssets?.nodes ?? []).map((n) => ({
		browser_download_url: n.downloadUrl,
		name: n.name
	}));
	/* c8 ignore stop */
}
/**
* Get download URL for a specific release asset. Supports pattern matching for
* dynamic asset discovery.
*
* @example
*   ;```typescript
*   const url = await getReleaseAssetUrl('v1.0.0', 'tool-linux-x64', {
*     owner: 'SocketDev',
*     repo: 'socket-btm',
*   })
*   ```
*
* @param tag - Release tag name.
* @param assetPattern - Asset name or pattern (glob string, prefix/suffix
*   object, or RegExp)
* @param repoConfig - Repository configuration (owner/repo)
* @param options - Additional options.
* @param options.nothrow - If true, return undefined instead of throwing when
*   both REST and GraphQL backends are degraded. Default: false.
*
* @returns Browser download URL for the asset, or undefined when not found.
*
* @throws {Error} If both REST and GraphQL backends are degraded and nothrow is
*   false.
*/
async function getReleaseAssetUrl(tag, assetPattern, repoConfig, options = {}) {
	const { nothrow = false } = options;
	const { owner, repo } = repoConfig;
	/* c8 ignore start */
	const isMatch = typeof assetPattern === "string" && !assetPattern.includes("*") && !assetPattern.includes("{") ? (input) => input === assetPattern : require_releases_github_assets.createAssetMatcher(assetPattern);
	/* c8 ignore stop */
	const assets = await /* @__PURE__ */ require_promises_retry.pRetry(async () => {
		const response = await require_http_request_request.httpRequest(`https://api.github.com/repos/${owner}/${repo}/releases/tags/${tag}`, { headers: require_releases_github_auth.getAuthHeaders() });
		if (!response.ok) throw new require_primordials_error.ErrorCtor(`Failed to fetch ${owner}/${repo} release ${tag}: ${response.status}`);
		let assets;
		if (response.body.byteLength === 0) {
			let fallbackAssets;
			try {
				fallbackAssets = await fetchReleaseAssetsViaGraphQL(owner, repo, tag);
			} catch (cause) {
				/* c8 ignore next 7 - Both backends degraded; needs real
				network failure on both REST and GraphQL. */
				if (nothrow) return;
				throw new require_primordials_error.ErrorCtor(`Failed to fetch ${owner}/${repo} release ${tag}: both REST and GraphQL backends degraded`, { cause });
			}
			/* c8 ignore start */
			if (fallbackAssets === void 0) {
				if (nothrow) return;
				throw new require_primordials_error.ErrorCtor(`Release ${tag} not found in ${owner}/${repo}`);
			}
			assets = fallbackAssets;
		} else {
			let release;
			try {
				release = require_primordials_json.JSONParse(response.body.toString("utf8"));
			} catch (cause) {
				throw new require_primordials_error.ErrorCtor(`Failed to parse ${owner}/${repo} release ${tag} response`, { cause });
			}
			if (!require_primordials_array.ArrayIsArray(release.assets)) throw new require_primordials_error.ErrorCtor(`Release ${tag} has no assets in ${owner}/${repo}`);
			assets = release.assets;
		}
		return assets;
	}, require_releases_github_retry_config.GITHUB_RETRY_CONFIG);
	if (!assets) {
		if (nothrow) return;
		throw new require_primordials_error.ErrorCtor(`Release ${tag} not found in ${owner}/${repo}`);
	}
	const asset = assets.find((a) => isMatch(a.name));
	/* c8 ignore start */
	if (!asset) {
		if (nothrow) return;
		throw new require_primordials_error.ErrorCtor(`Asset ${typeof assetPattern === "string" ? assetPattern : "matching pattern"} not found in release ${tag}`);
	}
	/* c8 ignore stop */
	return asset.browser_download_url;
}

//#endregion
exports.fetchReleaseAssetsViaGraphQL = fetchReleaseAssetsViaGraphQL;
exports.getReleaseAssetUrl = getReleaseAssetUrl;