Browse Source

Sync from gitrepublic-web monorepo - 2026-02-20 22:54:41

master
Silberengel 3 weeks ago
parent
commit
6b8888638b
  1. BIN
      gitrepublic-cli-1.0.0.tgz
  2. 10
      package.json
  3. 4
      scripts/commands/publish/index.js
  4. 32
      scripts/config.js
  5. 32
      scripts/git-commit-msg-hook.js
  6. 63
      scripts/relay/profile-fetcher.js
  7. 4
      scripts/relay/relay-fetcher.js

BIN
gitrepublic-cli-1.0.0.tgz

Binary file not shown.

10
package.json

@ -39,19 +39,9 @@ @@ -39,19 +39,9 @@
"author": "GitCitadel LLC",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://git.imwald.eu/silberengel/gitrepublic-cli.git"
},
"repositories": [
{
"type": "git",
"url": "https://github.com/silberengel/gitrepublic-cli.git"
},
{
"type": "git",
"url": "https://git.imwald.eu/silberengel/gitrepublic-cli.git"
}
],
"dependencies": {
"nostr-tools": "^2.22.1"
},

4
scripts/commands/publish/index.js

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
import { getPrivateKeyFromEnv, getPrivateKeyBytes } from '../../utils/keys.js';
import { getPublicKey } from 'nostr-tools';
import { DEFAULT_RELAYS } from '../../config.js';
import { DEFAULT_NOSTR_RELAYS } from '../../config.js';
import { publishToRelays } from '../../relay/publisher.js';
import { enhanceRelayList } from '../../relay/relay-fetcher.js';
import { storeEventInJsonl } from '../../utils/event-storage.js';
@ -35,7 +35,7 @@ export async function publish(args, server, json) { @@ -35,7 +35,7 @@ export async function publish(args, server, json) {
// Get relays from environment or use defaults
const relaysEnv = process.env.NOSTR_RELAYS;
const baseRelays = relaysEnv ? relaysEnv.split(',').map(r => r.trim()).filter(r => r.length > 0) : DEFAULT_RELAYS;
const baseRelays = relaysEnv ? relaysEnv.split(',').map(r => r.trim()).filter(r => r.length > 0) : DEFAULT_NOSTR_RELAYS;
// Enhance relay list with user's relay preferences (outboxes, local relays, blocked relays)
const relays = await enhanceRelayList(baseRelays, pubkey, baseRelays);

32
scripts/config.js

@ -8,15 +8,33 @@ export const KIND_NIP98_AUTH = 27235; @@ -8,15 +8,33 @@ export const KIND_NIP98_AUTH = 27235;
// Default server URL
export const DEFAULT_SERVER = process.env.GITREPUBLIC_SERVER || 'http://localhost:5173';
// Default relays
export const DEFAULT_RELAYS = [
/**
* Default Nostr relays to use for operations (publishing, fetching)
* Can be overridden by NOSTR_RELAYS env var (comma-separated list)
*
*/
export const DEFAULT_NOSTR_RELAYS =
typeof process !== 'undefined' && process.env?.NOSTR_RELAYS
? process.env.NOSTR_RELAYS.split(',').map(r => r.trim()).filter(r => r.length > 0)
: [
'wss://theforest.nostr1.com',
'wss://nostr.land',
];
/**
* Nostr relays to use for searching for repositories, profiles, or other events
* Can be overridden by NOSTR_SEARCH_RELAYS env var (comma-separated list)
*
*/
export const DEFAULT_NOSTR_SEARCH_RELAYS =
typeof process !== 'undefined' && process.env?.NOSTR_SEARCH_RELAYS
? process.env.NOSTR_SEARCH_RELAYS.split(',').map(r => r.trim()).filter(r => r.length > 0)
: [
'wss://theforest.nostr1.com',
'wss://nostr.land',
'wss://relay.damus.io',
'wss://thecitadel.nostr1.com',
'wss://nostr21.com',
'wss://theforest.nostr1.com',
'wss://freelay.sovbit.host',
'wss://nostr.sovbit.host',
'wss://bevos.nostr1.com',
'wss://relay.primal.net',
];
];

32
scripts/git-commit-msg-hook.js

@ -245,11 +245,40 @@ async function signCommitMessage(commitMessageFile) { @@ -245,11 +245,40 @@ async function signCommitMessage(commitMessageFile) {
const keyBytes = decodeNostrKey(secretKey);
const pubkey = getPublicKey(keyBytes);
// Get author info from git config, fallback to shortened npub
// Get author info from git config, then try to fetch from kind 0 event, fallback to shortened npub
let authorName = getGitConfig('user.name');
let authorEmail = getGitConfig('user.email');
// If not set in git config, try to fetch from kind 0 event
if (!authorName || !authorEmail) {
try {
const { fetchProfileFromRelays } = await import('./relay/profile-fetcher.js');
const profile = await fetchProfileFromRelays(pubkey);
if (!authorName) {
// Try display_name -> name -> shortened npub (20 chars)
if (profile?.displayName) {
authorName = profile.displayName;
} else if (profile?.name) {
authorName = profile.name;
} else {
const npub = nip19.npubEncode(pubkey);
authorName = npub.substring(0, 20);
}
}
if (!authorEmail) {
// Try NIP-05 -> shortenednpub@gitrepublic.web
if (profile?.nip05) {
authorEmail = profile.nip05;
} else {
const npub = nip19.npubEncode(pubkey);
authorEmail = `${npub.substring(0, 20)}@gitrepublic.web`;
}
}
} catch (profileError) {
// Fallback to shortened npub if profile fetch fails
console.warn(' ⚠ Failed to fetch profile from relays, using fallback:', profileError instanceof Error ? profileError.message : 'Unknown error');
const shortenedNpub = getShortenedNpub(pubkey);
if (!authorName) {
@ -260,6 +289,7 @@ async function signCommitMessage(commitMessageFile) { @@ -260,6 +289,7 @@ async function signCommitMessage(commitMessageFile) {
authorEmail = `${shortenedNpub}@gitrepublic.web`;
}
}
}
// Create timestamp
const timestamp = Math.floor(Date.now() / 1000);

63
scripts/relay/profile-fetcher.js

@ -0,0 +1,63 @@ @@ -0,0 +1,63 @@
/**
* Fetch user profile (kind 0) from Nostr relays
*/
import { SimplePool } from 'nostr-tools';
import { DEFAULT_NOSTR_RELAYS } from '../config.js';
/**
* Fetch kind 0 profile event from relays
*/
export async function fetchProfileFromRelays(pubkey, relays = null) {
try {
const pool = new SimplePool();
const relayList = relays || DEFAULT_NOSTR_RELAYS;
// Ensure pubkey is in hex format (getPublicKey returns hex string)
const pubkeyHex = typeof pubkey === 'string' && pubkey.length === 64
? pubkey.toLowerCase()
: pubkey;
const events = await pool.querySync(relayList, [
{
kinds: [0], // Kind 0 = profile metadata
authors: [pubkeyHex],
limit: 1
}
]);
pool.close(relayList);
if (events.length === 0) {
return null;
}
const event = events[0];
const profile = {};
// Try to parse JSON content
try {
const content = JSON.parse(event.content);
profile.displayName = content.display_name || content.displayName;
profile.name = content.name;
profile.nip05 = content.nip05;
} catch {
// Invalid JSON, try tags
}
// Check tags for nip05 (newer format)
if (!profile.nip05) {
const nip05Tag = event.tags.find((tag) =>
(tag[0] === 'nip05' || tag[0] === 'l') && tag[1]
);
if (nip05Tag && nip05Tag[1]) {
profile.nip05 = nip05Tag[1];
}
}
return profile;
} catch (error) {
console.warn('Failed to fetch profile from relays:', error);
return null;
}
}

4
scripts/relay/relay-fetcher.js

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
import { SimplePool } from 'nostr-tools';
import { DEFAULT_RELAYS } from '../config.js';
import { DEFAULT_NOSTR_RELAYS } from '../config.js';
/**
* Normalize a relay URL (similar to nostr-tools normalizeURL but simpler)
@ -75,7 +75,7 @@ function extractRelayUrls(event) { @@ -75,7 +75,7 @@ function extractRelayUrls(event) {
*/
export async function fetchRelayLists(pubkey, queryRelays = null) {
const pool = new SimplePool();
const relays = queryRelays || DEFAULT_RELAYS;
const relays = queryRelays || DEFAULT_NOSTR_RELAYS;
const outboxes = [];
const localRelays = [];

Loading…
Cancel
Save