Browse Source

bug-fix

main
Silberengel 4 weeks ago
parent
commit
8860c2754b
  1. 6
      src/app.css
  2. 2
      src/lib/services/git/commit-signer.ts
  3. 4
      src/lib/services/git/repo-manager.ts
  4. 2
      src/lib/services/nostr/maintainer-service.ts
  5. 22
      src/lib/services/nostr/nostr-client.ts
  6. 4
      src/lib/services/nostr/ownership-transfer-service.ts
  7. 2
      src/lib/services/nostr/repo-verification.ts
  8. 5
      src/routes/api/repos/[npub]/[repo]/branches/+server.ts
  9. 1
      src/routes/api/repos/[npub]/[repo]/download/+server.ts
  10. 6
      src/routes/api/repos/[npub]/[repo]/tags/+server.ts
  11. 2
      src/routes/api/repos/[npub]/[repo]/tree/+server.ts

6
src/app.css

@ -1,3 +1,6 @@
/* Import fonts - IBM Plex Serif for classic Roman feel with modern tech aesthetic */
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Serif:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&family=IBM+Plex+Mono:wght@400;500;600;700&display=swap');
/* GitRepublic Theme - Light/Dark Mode with Royal Plum Palette */ /* GitRepublic Theme - Light/Dark Mode with Royal Plum Palette */
:root { :root {
@ -78,9 +81,6 @@
--warning-text: #fbbf24; --warning-text: #fbbf24;
} }
/* Import fonts - IBM Plex Serif for classic Roman feel with modern tech aesthetic */
@import url('https://fonts.googleapis.com/css2?family=IBM+Plex+Serif:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&family=IBM+Plex+Mono:wght@400;500;600;700&display=swap');
/* Base styles */ /* Base styles */
* { * {
box-sizing: border-box; box-sizing: border-box;

2
src/lib/services/git/commit-signer.ts

@ -6,7 +6,7 @@
* - Direct nsec/hex keys (for server-side signing) * - Direct nsec/hex keys (for server-side signing)
*/ */
import { nip19, getPublicKey, finalizeEvent, getEventHash } from 'nostr-tools'; import { nip19, getPublicKey, finalizeEvent } from 'nostr-tools';
import { createHash } from 'crypto'; import { createHash } from 'crypto';
import type { NostrEvent } from '../../types/nostr.js'; import type { NostrEvent } from '../../types/nostr.js';
import { KIND } from '../../types/nostr.js'; import { KIND } from '../../types/nostr.js';

4
src/lib/services/git/repo-manager.ts

@ -312,7 +312,7 @@ export class RepoManager {
); );
commitMessage = signedMessage; commitMessage = signedMessage;
} catch (err) { } catch (err) {
logger.warn({ error: err, repoPath: repoPath.fullPath }, 'Failed to sign initial commit'); logger.warn({ error: err, repoPath }, 'Failed to sign initial commit');
// Continue without signature if signing fails // Continue without signature if signing fails
} }
} }
@ -332,7 +332,7 @@ export class RepoManager {
// Clean up // Clean up
await rm(workDir, { recursive: true, force: true }); await rm(workDir, { recursive: true, force: true });
} catch (error) { } catch (error) {
logger.error({ error, repoPath: repoPath.fullPath }, 'Failed to create verification file'); logger.error({ error, repoPath }, 'Failed to create verification file');
// Don't throw - verification file creation is important but shouldn't block provisioning // Don't throw - verification file creation is important but shouldn't block provisioning
} }
} }

2
src/lib/services/nostr/maintainer-service.ts

@ -110,7 +110,7 @@ export class MaintainerService {
this.cache.set(cacheKey, { ...result, timestamp: Date.now() }); this.cache.set(cacheKey, { ...result, timestamp: Date.now() });
return result; return result;
} catch (error) { } catch (error) {
logger.error({ error, ownerPubkey, repoName }, 'Error fetching maintainers'); logger.error({ error, repoOwnerPubkey, repoId }, 'Error fetching maintainers');
// Fallback: only owner is maintainer, repo is public by default // Fallback: only owner is maintainer, repo is public by default
const result = { owner: repoOwnerPubkey, maintainers: [repoOwnerPubkey], isPrivate: false }; const result = { owner: repoOwnerPubkey, maintainers: [repoOwnerPubkey], isPrivate: false };
this.cache.set(cacheKey, { ...result, timestamp: Date.now() }); this.cache.set(cacheKey, { ...result, timestamp: Date.now() });

22
src/lib/services/nostr/nostr-client.ts

@ -3,20 +3,26 @@
*/ */
import type { NostrEvent, NostrFilter } from '../../types/nostr.js'; import type { NostrEvent, NostrFilter } from '../../types/nostr.js';
import { createRequire } from 'module';
import logger from '../logger.js'; import logger from '../logger.js';
// Polyfill WebSocket for Node.js environments (lazy initialization) // Polyfill WebSocket for Node.js environments (lazy initialization)
let wsPolyfillInitialized = false; let wsPolyfillInitialized = false;
function initializeWebSocketPolyfill() { async function initializeWebSocketPolyfill() {
if (wsPolyfillInitialized) return; if (wsPolyfillInitialized) return;
if (typeof global === 'undefined' || typeof global.WebSocket !== 'undefined') { if (typeof global === 'undefined' || typeof global.WebSocket !== 'undefined') {
wsPolyfillInitialized = true; wsPolyfillInitialized = true;
return; return;
} }
// Only run in Node.js/server environment
if (typeof process === 'undefined' || !process.versions?.node) {
wsPolyfillInitialized = true;
return;
}
try { try {
// Use createRequire for ES modules compatibility // Dynamic import to avoid bundling for browser
const { createRequire } = await import('module');
const requireFunc = createRequire(import.meta.url); const requireFunc = createRequire(import.meta.url);
const WebSocketImpl = requireFunc('ws'); const WebSocketImpl = requireFunc('ws');
global.WebSocket = WebSocketImpl as any; global.WebSocket = WebSocketImpl as any;
@ -28,9 +34,11 @@ function initializeWebSocketPolyfill() {
} }
} }
// Initialize on module load if in Node.js // Initialize on module load if in Node.js (fire and forget)
if (typeof process !== 'undefined' && process.versions?.node) { if (typeof process !== 'undefined' && process.versions?.node) {
initializeWebSocketPolyfill(); initializeWebSocketPolyfill().catch(() => {
// Ignore errors during initialization
});
} }
export class NostrClient { export class NostrClient {
@ -66,7 +74,7 @@ export class NostrClient {
private async fetchFromRelay(relay: string, filters: NostrFilter[]): Promise<NostrEvent[]> { private async fetchFromRelay(relay: string, filters: NostrFilter[]): Promise<NostrEvent[]> {
// Ensure WebSocket polyfill is initialized // Ensure WebSocket polyfill is initialized
initializeWebSocketPolyfill(); await initializeWebSocketPolyfill();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const ws = new WebSocket(relay); const ws = new WebSocket(relay);
@ -164,7 +172,7 @@ export class NostrClient {
private async publishToRelay(relay: string, nostrEvent: NostrEvent): Promise<void> { private async publishToRelay(relay: string, nostrEvent: NostrEvent): Promise<void> {
// Ensure WebSocket polyfill is initialized // Ensure WebSocket polyfill is initialized
initializeWebSocketPolyfill(); await initializeWebSocketPolyfill();
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
const ws = new WebSocket(relay); const ws = new WebSocket(relay);

4
src/lib/services/nostr/ownership-transfer-service.ts

@ -101,7 +101,7 @@ export class OwnershipTransferService {
this.cache.set(cacheKey, { owner: currentOwner, timestamp: Date.now() }); this.cache.set(cacheKey, { owner: currentOwner, timestamp: Date.now() });
return currentOwner; return currentOwner;
} catch (error) { } catch (error) {
logger.error({ error, originalOwnerPubkey, repoName }, 'Error fetching ownership transfers'); logger.error({ error, originalOwnerPubkey, repoId }, 'Error fetching ownership transfers');
// Fallback to original owner // Fallback to original owner
return originalOwnerPubkey; return originalOwnerPubkey;
} }
@ -306,7 +306,7 @@ export class OwnershipTransferService {
transfers.sort((a, b) => b.timestamp - a.timestamp); transfers.sort((a, b) => b.timestamp - a.timestamp);
return transfers; return transfers;
} catch (error) { } catch (error) {
logger.error({ error, ownerPubkey, repoName }, 'Error fetching transfer history'); logger.error({ error, originalOwnerPubkey, repoId }, 'Error fetching transfer history');
return []; return [];
} }
} }

2
src/lib/services/nostr/repo-verification.ts

@ -3,7 +3,7 @@
* Creates and verifies cryptographic proof linking repo announcements to git repos * Creates and verifies cryptographic proof linking repo announcements to git repos
*/ */
import { getEventHash, verifyEvent } from 'nostr-tools'; import { verifyEvent } from 'nostr-tools';
import type { NostrEvent } from '../../types/nostr.js'; import type { NostrEvent } from '../../types/nostr.js';
import { nip19 } from 'nostr-tools'; import { nip19 } from 'nostr-tools';

5
src/routes/api/repos/[npub]/[repo]/branches/+server.ts

@ -42,9 +42,12 @@ export const POST: RequestHandler = async ({ params, request }: { params: { npub
return error(400, 'Missing npub or repo parameter'); return error(400, 'Missing npub or repo parameter');
} }
let branchName: string | undefined;
let fromBranch: string | undefined;
let userPubkey: string | undefined;
try { try {
const body = await request.json(); const body = await request.json();
const { branchName, fromBranch, userPubkey } = body; ({ branchName, fromBranch, userPubkey } = body);
if (!branchName) { if (!branchName) {
return error(400, 'Missing branchName parameter'); return error(400, 'Missing branchName parameter');

1
src/routes/api/repos/[npub]/[repo]/download/+server.ts

@ -12,7 +12,6 @@ import { exec } from 'child_process';
import { promisify } from 'util'; import { promisify } from 'util';
import { existsSync, readFileSync } from 'fs'; import { existsSync, readFileSync } from 'fs';
import { join } from 'path'; import { join } from 'path';
import { createReadStream } from 'fs';
import logger from '$lib/services/logger.js'; import logger from '$lib/services/logger.js';
const execAsync = promisify(exec); const execAsync = promisify(exec);

6
src/routes/api/repos/[npub]/[repo]/tags/+server.ts

@ -50,9 +50,13 @@ export const POST: RequestHandler = async ({ params, request }: { params: { npub
return error(400, 'Missing npub or repo parameter'); return error(400, 'Missing npub or repo parameter');
} }
let tagName: string | undefined;
let ref: string | undefined;
let message: string | undefined;
let userPubkey: string | undefined;
try { try {
const body = await request.json(); const body = await request.json();
const { tagName, ref, message, userPubkey } = body; ({ tagName, ref, message, userPubkey } = body);
if (!tagName) { if (!tagName) {
return error(400, 'Missing tagName parameter'); return error(400, 'Missing tagName parameter');

2
src/routes/api/repos/[npub]/[repo]/tree/+server.ts

@ -50,7 +50,7 @@ export const GET: RequestHandler = async ({ params, url, request }) => {
const files = await fileManager.listFiles(npub, repo, ref, path); const files = await fileManager.listFiles(npub, repo, ref, path);
return json(files); return json(files);
} catch (err) { } catch (err) {
logger.error({ error: err, npub, repo, path, branch }, 'Error listing files'); logger.error({ error: err, npub, repo, path, ref }, 'Error listing files');
return error(500, err instanceof Error ? err.message : 'Failed to list files'); return error(500, err instanceof Error ? err.message : 'Failed to list files');
} }
}; };

Loading…
Cancel
Save