You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
80 lines
3.0 KiB
80 lines
3.0 KiB
/** |
|
* API endpoint for Issues (NIP-34 kind 1621) |
|
*/ |
|
|
|
import { json, error } from '@sveltejs/kit'; |
|
import type { RequestHandler } from './$types'; |
|
import { IssuesService } from '$lib/services/nostr/issues-service.js'; |
|
import { DEFAULT_NOSTR_RELAYS } from '$lib/config.js'; |
|
import { nip19 } from 'nostr-tools'; |
|
import { requireNpubHex } from '$lib/utils/npub-utils.js'; |
|
import { handleApiError, handleValidationError, handleNotFoundError, handleAuthorizationError } from '$lib/utils/error-handler.js'; |
|
|
|
export const GET: RequestHandler = async ({ params, url, request }) => { |
|
const { npub, repo } = params; |
|
const userPubkey = url.searchParams.get('userPubkey') || request.headers.get('x-user-pubkey'); |
|
|
|
if (!npub || !repo) { |
|
return handleValidationError('Missing npub or repo parameter', { operation: 'getIssues' }); |
|
} |
|
|
|
try { |
|
// Convert npub to pubkey |
|
let repoOwnerPubkey: string; |
|
try { |
|
repoOwnerPubkey = requireNpubHex(npub); |
|
} catch { |
|
return handleValidationError('Invalid npub format', { operation: 'getIssues', npub }); |
|
} |
|
|
|
// Check repository privacy |
|
const { checkRepoAccess } = await import('$lib/utils/repo-privacy.js'); |
|
const access = await checkRepoAccess(npub, repo, userPubkey || null); |
|
if (!access.allowed) { |
|
return handleAuthorizationError(access.error || 'Access denied', { operation: 'getIssues', npub, repo }); |
|
} |
|
|
|
const issuesService = new IssuesService(DEFAULT_NOSTR_RELAYS); |
|
const issues = await issuesService.getIssues(repoOwnerPubkey, repo); |
|
|
|
return json(issues); |
|
} catch (err) { |
|
return handleApiError(err, { operation: 'getIssues', npub, repo }, 'Failed to fetch issues'); |
|
} |
|
}; |
|
|
|
export const POST: RequestHandler = async ({ params, request }) => { |
|
// For creating issues, we accept a pre-signed event from the client |
|
// since NIP-07 signing must happen client-side |
|
const { npub, repo } = params; |
|
|
|
if (!npub || !repo) { |
|
return handleValidationError('Missing npub or repo parameter', { operation: 'createIssue' }); |
|
} |
|
|
|
try { |
|
const body = await request.json(); |
|
const { event } = body; |
|
|
|
if (!event) { |
|
return handleValidationError('Missing event in request body', { operation: 'createIssue', npub, repo }); |
|
} |
|
|
|
// Verify the event is properly signed (basic check) |
|
if (!event.sig || !event.id) { |
|
return handleValidationError('Invalid event: missing signature or ID', { operation: 'createIssue', npub, repo }); |
|
} |
|
|
|
// Publish the event to relays |
|
const issuesService = new IssuesService(DEFAULT_NOSTR_RELAYS); |
|
const result = await issuesService['nostrClient'].publishEvent(event, DEFAULT_NOSTR_RELAYS); |
|
|
|
if (result.failed.length > 0 && result.success.length === 0) { |
|
return handleApiError(new Error('Failed to publish issue to all relays'), { operation: 'createIssue', npub, repo }, 'Failed to publish issue to all relays'); |
|
} |
|
|
|
return json({ success: true, event, published: result }); |
|
} catch (err) { |
|
return handleApiError(err, { operation: 'createIssue', npub, repo }, 'Failed to create issue'); |
|
} |
|
};
|
|
|