Browse Source

refactor the refactor

Nostr-Signature: 62aafbdadfd37b20f1b16742a297e2b17d59dd3d6930e64e75d0d1b6a2f04bd6 573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc 050eaca1703b73443b51fd160932a2edfa04fc0a5efd3b5bb0a1e4c8b944caa60d444b2148c07b74f4ff4a589984fa524a7109a2a89c3eddf6c937b23b18c69b
main
Silberengel 2 weeks ago
parent
commit
82075b554a
  1. 1
      nostr/commit-signatures.jsonl
  2. 357
      src/routes/repos/[npub]/[repo]/+page.svelte
  3. 101
      src/routes/repos/[npub]/[repo]/services/branch-operations.ts
  4. 255
      src/routes/repos/[npub]/[repo]/services/file-operations.ts

1
nostr/commit-signatures.jsonl

@ -95,3 +95,4 @@
{"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772105581,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","fdix build"]],"content":"Signed commit: fdix build","id":"aa457cd97e3af5c7e7e6f8938d159f62de2eee27afcf9a9a415192a8b39cd038","sig":"1959bae547fefff3b3fd72e23071e989724ab71f2042bad9cb5a969133045119a068b529df17ded13db96b54372f662760df79a34f1b6072dcabf5d2f003000b"} {"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772105581,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","fdix build"]],"content":"Signed commit: fdix build","id":"aa457cd97e3af5c7e7e6f8938d159f62de2eee27afcf9a9a415192a8b39cd038","sig":"1959bae547fefff3b3fd72e23071e989724ab71f2042bad9cb5a969133045119a068b529df17ded13db96b54372f662760df79a34f1b6072dcabf5d2f003000b"}
{"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772106804,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","refactor 3"]],"content":"Signed commit: refactor 3","id":"a761c789227ef2368eff89f7062fa7889820c4846701667360978cfdad08c3d2","sig":"9d229200ab66d3f4a0a2a21112c9100ee14d0a5d9f8409a35fef36f195f5f73c8ac2344aa1175cc476f650336a5a10ea6ac0076c8ec2cb229fea7d600c5d4399"} {"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772106804,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","refactor 3"]],"content":"Signed commit: refactor 3","id":"a761c789227ef2368eff89f7062fa7889820c4846701667360978cfdad08c3d2","sig":"9d229200ab66d3f4a0a2a21112c9100ee14d0a5d9f8409a35fef36f195f5f73c8ac2344aa1175cc476f650336a5a10ea6ac0076c8ec2cb229fea7d600c5d4399"}
{"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772107667,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","fix build"]],"content":"Signed commit: fix build","id":"2a8db19aff5126547a397f7daf9121f711a3d61efcced642b496687d9afc48dc","sig":"7e0558fac1764e185b3f52450f5a34805b04342bdb0821b4d459b1627d057d7e2af397b3263a8831e9be2e615556ef09094bce808c22f6049261273004da74bc"} {"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772107667,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","fix build"]],"content":"Signed commit: fix build","id":"2a8db19aff5126547a397f7daf9121f711a3d61efcced642b496687d9afc48dc","sig":"7e0558fac1764e185b3f52450f5a34805b04342bdb0821b4d459b1627d057d7e2af397b3263a8831e9be2e615556ef09094bce808c22f6049261273004da74bc"}
{"kind":1640,"pubkey":"573634b648634cbad10f2451776089ea21090d9407f715e83c577b4611ae6edc","created_at":1772108817,"tags":[["author","Silberengel","silberengel7@protonmail.com"],["message","fix build"]],"content":"Signed commit: fix build","id":"a37754536125d75a5c55f6af3b5521f89839e797ad1bffb69e3d313939cb7b65","sig":"6bcca1a025e4478ae330d3664dd2b9cff55f4bec82065ab2afb5bfb92031f7dde3264657dd892fe844396990117048b19247b0ef7423139f89d4cbf46b47f828"}

357
src/routes/repos/[npub]/[repo]/+page.svelte

@ -77,6 +77,15 @@
getUserEmail as getUserEmailUtil, getUserEmail as getUserEmailUtil,
getUserName as getUserNameUtil getUserName as getUserNameUtil
} from './utils/user-profile.js'; } from './utils/user-profile.js';
import {
saveFile as saveFileService,
createFile as createFileService,
deleteFile as deleteFileService
} from './services/file-operations.js';
import {
createBranch as createBranchService,
deleteBranch as deleteBranchService
} from './services/branch-operations.js';
// Consolidated state - all state variables in one object // Consolidated state - all state variables in one object
let state = $state(createRepoState()); let state = $state(createRepoState());
@ -3013,88 +3022,12 @@
} }
async function saveFile() { async function saveFile() {
if (!state.files.currentFile || !state.forms.commit.message.trim()) { await saveFileService(state, {
alert('Please enter a commit message'); getUserEmail,
return; getUserName,
} loadFiles,
loadFile
if (!state.user.pubkey) {
alert('Please connect your NIP-07 extension to save state.files.list');
return;
}
// Validate branch selection
if (!state.git.currentBranch || typeof state.git.currentBranch !== 'string') {
alert('Please select a branch before state.saving the file');
return;
}
state.saving = true;
state.error = null;
try {
// Get user email and name (from profile or prompt)
const authorEmail = await getUserEmail();
const authorName = await getUserName();
// Sign commit with NIP-07 (client-side)
let commitSignatureEvent: NostrEvent | null = null;
if (isNIP07Available()) {
try {
const { KIND } = await import('$lib/types/nostr.js');
const timestamp = Math.floor(Date.now() / 1000);
const eventTemplate: Omit<NostrEvent, 'sig' | 'id'> = {
kind: KIND.COMMIT_SIGNATURE,
pubkey: '', // Will be filled by NIP-07
created_at: timestamp,
tags: [
['author', authorName, authorEmail],
['message', state.forms.commit.message.trim()]
],
content: `Signed commit: ${state.forms.commit.message.trim()}`
};
commitSignatureEvent = await signEventWithNIP07(eventTemplate);
} catch (err) {
console.warn('Failed to sign commit with NIP-07:', err);
// Continue without signature if signing fails
}
}
const response = await fetch(`/api/repos/${state.npub}/${state.repo}/file`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...buildApiHeaders()
},
body: JSON.stringify({
path: state.files.currentFile,
content: state.files.editedContent,
message: state.forms.commit.message.trim(),
authorName: authorName,
authorEmail: authorEmail,
branch: state.git.currentBranch,
userPubkey: state.user.pubkey,
commitSignatureEvent: commitSignatureEvent // Send the signed event to server
})
}); });
if (!response.ok) {
const errorData = await response.json().catch(() => ({ message: response.statusText }));
const errorMessage = errorData.message || errorData.state.error || 'Failed to save file';
throw new Error(errorMessage);
}
// Reload file to get updated content
await loadFile(state.files.currentFile);
state.forms.commit.message = '';
state.openDialog = null;
alert('File saved successfully!');
} catch (err) {
state.error = err instanceof Error ? err.message : 'Failed to save file';
console.error('Error state.saving file:', err);
} finally {
state.saving = false;
}
} }
function handleBranchChangeDirect(branch: string) { function handleBranchChangeDirect(branch: string) {
@ -3142,269 +3075,31 @@
} }
async function createFile() { async function createFile() {
if (!state.forms.file.fileName.trim()) { await createFileService(state, {
alert('Please enter a file name'); getUserEmail,
return; getUserName,
} loadFiles
if (!state.user.pubkey) {
alert('Please connect your NIP-07 extension');
return;
}
// Validate branch selection
if (!state.git.currentBranch || typeof state.git.currentBranch !== 'string') {
alert('Please select a branch before creating the file');
return;
}
state.saving = true;
state.error = null;
try {
// Get user email and name (from profile or prompt)
const authorEmail = await getUserEmail();
const authorName = await getUserName();
const filePath = state.files.currentPath ? `${state.files.currentPath}/${state.forms.file.fileName}` : state.forms.file.fileName;
const commitMsg = `Create ${state.forms.file.fileName}`;
// Sign commit with NIP-07 (client-side)
let commitSignatureEvent: NostrEvent | null = null;
if (isNIP07Available()) {
try {
const { KIND } = await import('$lib/types/nostr.js');
const timestamp = Math.floor(Date.now() / 1000);
const eventTemplate: Omit<NostrEvent, 'sig' | 'id'> = {
kind: KIND.COMMIT_SIGNATURE,
pubkey: '', // Will be filled by NIP-07
created_at: timestamp,
tags: [
['author', authorName, authorEmail],
['message', commitMsg]
],
content: `Signed commit: ${commitMsg}`
};
commitSignatureEvent = await signEventWithNIP07(eventTemplate);
} catch (err) {
console.warn('Failed to sign commit with NIP-07:', err);
// Continue without signature if signing fails
}
}
const response = await fetch(`/api/repos/${state.npub}/${state.repo}/file`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...buildApiHeaders()
},
body: JSON.stringify({
path: filePath,
content: state.forms.file.content,
message: commitMsg,
authorName: authorName,
authorEmail: authorEmail,
branch: state.git.currentBranch,
action: 'create',
userPubkey: state.user.pubkey,
commitSignatureEvent: commitSignatureEvent // Send the signed event to server
})
}); });
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || 'Failed to create file');
}
state.openDialog = null;
state.forms.file.fileName = '';
state.forms.file.content = '';
await loadFiles(state.files.currentPath);
alert('File created successfully!');
} catch (err) {
state.error = err instanceof Error ? err.message : 'Failed to create file';
} finally {
state.saving = false;
}
} }
async function deleteFile(filePath: string) { async function deleteFile(filePath: string) {
if (!confirm(`Are you sure you want to delete "${filePath}"?\n\nThis will permanently delete the file from the repository. This action cannot be undone.\n\nClick OK to delete, or Cancel to abort.`)) { await deleteFileService(filePath, state, {
return; getUserEmail,
} getUserName,
loadFiles
if (!state.user.pubkey) {
alert('Please connect your NIP-07 extension');
return;
}
// Validate branch selection
if (!state.git.currentBranch || typeof state.git.currentBranch !== 'string') {
alert('Please select a branch before deleting the file');
return;
}
state.saving = true;
state.error = null;
try {
// Get user email and name (from profile or prompt)
const authorEmail = await getUserEmail();
const authorName = await getUserName();
const commitMsg = `Delete ${filePath}`;
// Sign commit with NIP-07 (client-side)
let commitSignatureEvent: NostrEvent | null = null;
if (isNIP07Available()) {
try {
const { KIND } = await import('$lib/types/nostr.js');
const timestamp = Math.floor(Date.now() / 1000);
const eventTemplate: Omit<NostrEvent, 'sig' | 'id'> = {
kind: KIND.COMMIT_SIGNATURE,
pubkey: '', // Will be filled by NIP-07
created_at: timestamp,
tags: [
['author', authorName, authorEmail],
['message', commitMsg]
],
content: `Signed commit: ${commitMsg}`
};
commitSignatureEvent = await signEventWithNIP07(eventTemplate);
} catch (err) {
console.warn('Failed to sign commit with NIP-07:', err);
// Continue without signature if signing fails
}
}
const response = await fetch(`/api/repos/${state.npub}/${state.repo}/file`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...buildApiHeaders()
},
body: JSON.stringify({
path: filePath,
message: commitMsg,
authorName: authorName,
authorEmail: authorEmail,
branch: state.git.currentBranch,
action: 'delete',
userPubkey: state.user.pubkey,
commitSignatureEvent: commitSignatureEvent // Send the signed event to server
})
}); });
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || 'Failed to delete file');
}
if (state.files.currentFile === filePath) {
state.files.currentFile = null;
}
await loadFiles(state.files.currentPath);
alert('File deleted successfully!');
} catch (err) {
state.error = err instanceof Error ? err.message : 'Failed to delete file';
} finally {
state.saving = false;
}
} }
async function createBranch() { async function createBranch() {
if (!state.forms.branch.name.trim()) { await createBranchService(state, repoAnnouncement, {
alert('Please enter a branch name'); loadBranches
return;
}
state.saving = true;
state.error = null;
try {
// If no state.git.branches exist, don't pass fromBranch (will use --orphan)
// Otherwise, use the selected branch or current branch
let fromBranch: string | undefined = state.forms.branch.from || state.git.currentBranch || undefined;
// Include announcement if available (for empty repos)
const requestBody: { branchName: string; fromBranch?: string; announcement?: NostrEvent } = {
branchName: state.forms.branch.name
};
if (state.git.branches.length > 0 && fromBranch) {
requestBody.fromBranch = fromBranch;
}
// Pass announcement if available (especially useful for empty repos)
if (repoAnnouncement) {
requestBody.announcement = repoAnnouncement;
}
const response = await fetch(`/api/repos/${state.npub}/${state.repo}/branches`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
...buildApiHeaders()
},
body: JSON.stringify(requestBody)
}); });
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || 'Failed to create branch');
}
state.openDialog = null;
state.forms.branch.name = '';
await loadBranches();
alert('Branch created successfully!');
} catch (err) {
state.error = err instanceof Error ? err.message : 'Failed to create branch';
} finally {
state.saving = false;
}
} }
async function deleteBranch(branchName: string) { async function deleteBranch(branchName: string) {
if (!confirm(`Are you sure you want to delete the branch "${branchName}"?\n\nThis will permanently delete the branch from the repository. This action CANNOT be undone.\n\nClick OK to delete, or Cancel to abort.`)) { await deleteBranchService(branchName, state, {
return; loadBranches
}
if (!state.user.pubkey) {
alert('Please connect your NIP-07 extension');
return;
}
// Prevent deleting the current branch
if (branchName === state.git.currentBranch) {
alert('Cannot delete the currently selected branch. Please switch to a different branch first.');
return;
}
state.saving = true;
state.error = null;
try {
const response = await fetch(`/api/repos/${state.npub}/${state.repo}/branches`, {
method: 'DELETE',
headers: {
'Content-Type': 'application/json',
...buildApiHeaders()
},
body: JSON.stringify({
branchName: branchName
})
}); });
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.message || 'Failed to delete branch');
}
await loadBranches();
alert('Branch deleted successfully!');
} catch (err) {
state.error = err instanceof Error ? err.message : 'Failed to delete branch';
alert(state.error);
} finally {
state.saving = false;
}
} }
async function loadCommitHistory() { async function loadCommitHistory() {

101
src/routes/repos/[npub]/[repo]/services/branch-operations.ts

@ -0,0 +1,101 @@
/**
* Branch operations service
* Handles branch creation and deletion
*/
import type { NostrEvent } from '$lib/types/nostr.js';
import type { RepoState } from '../stores/repo-state.js';
import { apiPost, apiRequest } from '../utils/api-client.js';
interface BranchOperationsCallbacks {
loadBranches: () => Promise<void>;
}
/**
* Create a new branch
*/
export async function createBranch(
state: RepoState,
repoAnnouncement: NostrEvent | null | undefined,
callbacks: BranchOperationsCallbacks
): Promise<void> {
if (!state.forms.branch.name.trim()) {
alert('Please enter a branch name');
return;
}
state.saving = true;
state.error = null;
try {
// If no branches exist, don't pass fromBranch (will use --orphan)
// Otherwise, use the selected branch or current branch
let fromBranch: string | undefined = state.forms.branch.from || state.git.currentBranch || undefined;
// Include announcement if available (for empty repos)
const requestBody: { branchName: string; fromBranch?: string; announcement?: NostrEvent } = {
branchName: state.forms.branch.name
};
if (state.git.branches.length > 0 && fromBranch) {
requestBody.fromBranch = fromBranch;
}
// Pass announcement if available (especially useful for empty repos)
if (repoAnnouncement) {
requestBody.announcement = repoAnnouncement;
}
await apiPost(`/api/repos/${state.npub}/${state.repo}/branches`, requestBody);
state.openDialog = null;
state.forms.branch.name = '';
await callbacks.loadBranches();
alert('Branch created successfully!');
} catch (err) {
state.error = err instanceof Error ? err.message : 'Failed to create branch';
} finally {
state.saving = false;
}
}
/**
* Delete a branch
*/
export async function deleteBranch(
branchName: string,
state: RepoState,
callbacks: BranchOperationsCallbacks
): Promise<void> {
if (!confirm(`Are you sure you want to delete the branch "${branchName}"?\n\nThis will permanently delete the branch from the repository. This action CANNOT be undone.\n\nClick OK to delete, or Cancel to abort.`)) {
return;
}
if (!state.user.pubkey) {
alert('Please connect your NIP-07 extension');
return;
}
// Prevent deleting the current branch
if (branchName === state.git.currentBranch) {
alert('Cannot delete the currently selected branch. Please switch to a different branch first.');
return;
}
state.saving = true;
state.error = null;
try {
// Note: DELETE endpoint expects branchName in body, not query string
await apiRequest(`/api/repos/${state.npub}/${state.repo}/branches`, {
method: 'DELETE',
body: JSON.stringify({ branchName })
});
await callbacks.loadBranches();
alert('Branch deleted successfully!');
} catch (err) {
state.error = err instanceof Error ? err.message : 'Failed to delete branch';
alert(state.error);
} finally {
state.saving = false;
}
}

255
src/routes/repos/[npub]/[repo]/services/file-operations.ts

@ -0,0 +1,255 @@
/**
* File operations service
* Handles file saving, creating, and deleting
* Note: loadFile and loadFiles remain in component due to complex state dependencies
*/
import type { NostrEvent } from '$lib/types/nostr.js';
import type { RepoState } from '../stores/repo-state.js';
import { isNIP07Available, signEventWithNIP07 } from '$lib/services/nostr/nip07-signer.js';
import { apiPost } from '../utils/api-client.js';
interface FileOperationsCallbacks {
getUserEmail: () => Promise<string>;
getUserName: () => Promise<string>;
loadFiles: (path: string) => Promise<void>;
loadFile?: (path: string) => Promise<void>;
}
/**
* Save a file to the repository
*/
export async function saveFile(
state: RepoState,
callbacks: FileOperationsCallbacks
): Promise<void> {
if (!state.files.currentFile || !state.forms.commit.message.trim()) {
alert('Please enter a commit message');
return;
}
if (!state.user.pubkey) {
alert('Please connect your NIP-07 extension to save files');
return;
}
if (!state.git.currentBranch || typeof state.git.currentBranch !== 'string') {
alert('Please select a branch before saving the file');
return;
}
state.saving = true;
state.error = null;
try {
const authorEmail = await callbacks.getUserEmail();
const authorName = await callbacks.getUserName();
// Sign commit with NIP-07 (client-side)
let commitSignatureEvent: NostrEvent | null = null;
if (isNIP07Available()) {
try {
const { KIND } = await import('$lib/types/nostr.js');
const timestamp = Math.floor(Date.now() / 1000);
const eventTemplate: Omit<NostrEvent, 'sig' | 'id'> = {
kind: KIND.COMMIT_SIGNATURE,
pubkey: '',
created_at: timestamp,
tags: [
['author', authorName, authorEmail],
['message', state.forms.commit.message.trim()]
],
content: `Signed commit: ${state.forms.commit.message.trim()}`
};
commitSignatureEvent = await signEventWithNIP07(eventTemplate);
} catch (err) {
console.warn('Failed to sign commit with NIP-07:', err);
}
}
await apiPost(`/api/repos/${state.npub}/${state.repo}/file`, {
path: state.files.currentFile,
content: state.files.editedContent,
message: state.forms.commit.message.trim(),
authorName: authorName,
authorEmail: authorEmail,
branch: state.git.currentBranch,
userPubkey: state.user.pubkey,
commitSignatureEvent: commitSignatureEvent
});
if (callbacks.loadFile) {
await callbacks.loadFile(state.files.currentFile);
}
state.forms.commit.message = '';
state.openDialog = null;
alert('File saved successfully!');
} catch (err) {
state.error = err instanceof Error ? err.message : 'Failed to save file';
console.error('Error saving file:', err);
} finally {
state.saving = false;
}
}
/**
* Create a new file in the repository
*/
export async function createFile(
state: RepoState,
callbacks: FileOperationsCallbacks
): Promise<void> {
if (!state.forms.file.fileName.trim()) {
alert('Please enter a file name');
return;
}
if (!state.user.pubkey) {
alert('Please connect your NIP-07 extension');
return;
}
if (!state.git.currentBranch || typeof state.git.currentBranch !== 'string') {
alert('Please select a branch before creating the file');
return;
}
state.saving = true;
state.error = null;
try {
const authorEmail = await callbacks.getUserEmail();
const authorName = await callbacks.getUserName();
const filePath = state.files.currentPath ? `${state.files.currentPath}/${state.forms.file.fileName}` : state.forms.file.fileName;
const commitMsg = `Create ${state.forms.file.fileName}`;
// Sign commit with NIP-07 (client-side)
let commitSignatureEvent: NostrEvent | null = null;
if (isNIP07Available()) {
try {
const { KIND } = await import('$lib/types/nostr.js');
const timestamp = Math.floor(Date.now() / 1000);
const eventTemplate: Omit<NostrEvent, 'sig' | 'id'> = {
kind: KIND.COMMIT_SIGNATURE,
pubkey: '',
created_at: timestamp,
tags: [
['author', authorName, authorEmail],
['message', commitMsg]
],
content: `Signed commit: ${commitMsg}`
};
commitSignatureEvent = await signEventWithNIP07(eventTemplate);
} catch (err) {
console.warn('Failed to sign commit with NIP-07:', err);
}
}
await apiPost(`/api/repos/${state.npub}/${state.repo}/file`, {
path: filePath,
content: state.forms.file.content,
message: commitMsg,
authorName: authorName,
authorEmail: authorEmail,
branch: state.git.currentBranch,
action: 'create',
userPubkey: state.user.pubkey,
commitSignatureEvent: commitSignatureEvent
});
// Clear form
state.forms.file.fileName = '';
state.forms.file.content = '';
state.openDialog = null;
// Reload file list
await callbacks.loadFiles(state.files.currentPath);
alert('File created successfully!');
} catch (err) {
state.error = err instanceof Error ? err.message : 'Failed to create file';
console.error('Error creating file:', err);
} finally {
state.saving = false;
}
}
/**
* Delete a file from the repository
*/
export async function deleteFile(
filePath: string,
state: RepoState,
callbacks: FileOperationsCallbacks
): Promise<void> {
if (!confirm(`Are you sure you want to delete "${filePath}"?\n\nThis will permanently delete the file from the repository. This action cannot be undone.\n\nClick OK to delete, or Cancel to abort.`)) {
return;
}
if (!state.user.pubkey) {
alert('Please connect your NIP-07 extension');
return;
}
if (!state.git.currentBranch || typeof state.git.currentBranch !== 'string') {
alert('Please select a branch before deleting the file');
return;
}
state.saving = true;
state.error = null;
try {
const authorEmail = await callbacks.getUserEmail();
const authorName = await callbacks.getUserName();
const commitMsg = `Delete ${filePath}`;
// Sign commit with NIP-07 (client-side)
let commitSignatureEvent: NostrEvent | null = null;
if (isNIP07Available()) {
try {
const { KIND } = await import('$lib/types/nostr.js');
const timestamp = Math.floor(Date.now() / 1000);
const eventTemplate: Omit<NostrEvent, 'sig' | 'id'> = {
kind: KIND.COMMIT_SIGNATURE,
pubkey: '',
created_at: timestamp,
tags: [
['author', authorName, authorEmail],
['message', commitMsg]
],
content: `Signed commit: ${commitMsg}`
};
commitSignatureEvent = await signEventWithNIP07(eventTemplate);
} catch (err) {
console.warn('Failed to sign commit with NIP-07:', err);
}
}
await apiPost(`/api/repos/${state.npub}/${state.repo}/file`, {
path: filePath,
message: commitMsg,
authorName: authorName,
authorEmail: authorEmail,
branch: state.git.currentBranch,
action: 'delete',
userPubkey: state.user.pubkey,
commitSignatureEvent: commitSignatureEvent
});
// Clear current file if it was deleted
if (state.files.currentFile === filePath) {
state.files.currentFile = null;
}
// Reload file list
await callbacks.loadFiles(state.files.currentPath);
alert('File deleted successfully!');
} catch (err) {
state.error = err instanceof Error ? err.message : 'Failed to delete file';
console.error('Error deleting file:', err);
} finally {
state.saving = false;
}
}
Loading…
Cancel
Save