Browse Source

fix build

master
Silberengel 1 week ago
parent
commit
e81570b9ba
  1. 1
      .npmrc
  2. 6
      esbuild.config.mjs
  3. 1379
      package-lock.json
  4. 10
      package.json
  5. 3
      src/eventManager.ts
  6. 4
      src/eventStorage.ts
  7. 2
      src/main.ts
  8. 99
      src/nostr/authHandler.ts
  9. 21
      src/nostr/eventBuilder.ts
  10. 98
      src/nostr/relayClient.ts
  11. 5
      src/relayManager.ts
  12. 6
      src/types/js-yaml.d.ts

1
.npmrc

@ -0,0 +1 @@ @@ -0,0 +1 @@
legacy-peer-deps=true

6
esbuild.config.mjs

@ -4,12 +4,10 @@ import builtins from "builtin-modules"; @@ -4,12 +4,10 @@ import builtins from "builtin-modules";
const isProduction = process.argv[2] === "production";
const banner =
"/*
const banner = `/*
THIS IS A GENERATED/BUNDLED FILE BY ESBUILD
if you want to view the source, please visit the github repository of this plugin
*/
";
*/`;
const prodConfig = {
banner: {

1379
package-lock.json generated

File diff suppressed because it is too large Load Diff

10
package.json

@ -9,20 +9,22 @@ @@ -9,20 +9,22 @@
"version": "node version-bump.mjs && git add manifest.json versions.json"
},
"keywords": [],
"author": "",
"author": "Silberengel",
"homepage": "https://gitcitadel.com",
"license": "MIT",
"devDependencies": {
"@types/node": "^16.11.6",
"@types/node": "^20.0.0",
"@typescript-eslint/eslint-plugin": "5.29.0",
"@typescript-eslint/parser": "5.29.0",
"@types/js-yaml": "^4.0.9",
"builtin-modules": "3.3.0",
"esbuild": "0.17.3",
"obsidian": "latest",
"tslib": "2.4.0",
"typescript": "4.7.4"
"typescript": "5.3.3"
},
"dependencies": {
"nostr-tools": "^2.4.0",
"nostr-tools": "^2.20.0",
"js-yaml": "^4.1.0"
}
}

3
src/eventManager.ts

@ -102,10 +102,11 @@ export async function buildAsciiDocEvents( @@ -102,10 +102,11 @@ export async function buildAsciiDocEvents(
}
// Now build this index event with references to children
const baseMetadata = node.metadata as Kind30040Metadata;
const indexMetadata: Kind30040Metadata = {
...baseMetadata,
kind: 30040,
title: node.title,
...(node.metadata as Kind30040Metadata),
};
const tags = buildTagsFromMetadata(indexMetadata, pubkey, childEvents);

4
src/eventStorage.ts

@ -39,8 +39,8 @@ export async function loadEvents( @@ -39,8 +39,8 @@ export async function loadEvents(
return [];
}
const content = await app.vault.read(eventsFile);
const lines = content.split("\n").filter((line) => line.trim().length > 0);
return lines.map((line) => JSON.parse(line) as SignedEvent);
const lines = content.split("\n").filter((line: string) => line.trim().length > 0);
return lines.map((line: string) => JSON.parse(line) as SignedEvent);
} catch (error) {
console.error("Error loading events:", error);
return [];

2
src/main.ts

@ -12,7 +12,7 @@ import { parseAsciiDocStructure, isAsciiDocDocument } from "./asciidocParser"; @@ -12,7 +12,7 @@ import { parseAsciiDocStructure, isAsciiDocDocument } from "./asciidocParser";
import { normalizeSecretKey, getPubkeyFromPrivkey } from "./nostr/eventBuilder";
export default class ScriptoriumPlugin extends Plugin {
settings: ScriptoriumSettings;
settings!: ScriptoriumSettings;
async onload() {
await this.loadSettings();

99
src/nostr/authHandler.ts

@ -12,49 +12,14 @@ export async function handleAuthChallenge( @@ -12,49 +12,14 @@ export async function handleAuthChallenge(
): Promise<boolean> {
try {
const normalizedKey = normalizeSecretKey(privkey);
const pubkey = getPublicKey(normalizedKey);
// Create kind 22242 AUTH event
const authEvent = finalizeEvent(
{
kind: 22242,
pubkey,
created_at: Math.floor(Date.now() / 1000),
tags: [
["relay", relayUrl],
["challenge", challenge],
],
content: "",
},
normalizedKey
);
// Send AUTH event
return new Promise((resolve) => {
const timeout = setTimeout(() => {
resolve(false);
}, 10000);
relay.on("ok", (ok) => {
if (ok.id === authEvent.id && ok.ok) {
clearTimeout(timeout);
resolve(true);
}
});
relay.on("error", () => {
clearTimeout(timeout);
resolve(false);
});
relay.send(["AUTH", authEvent]);
// Also listen for OK message directly
setTimeout(() => {
clearTimeout(timeout);
resolve(false);
}, 5000);
// Use relay.auth() method which handles the AUTH flow
// auth() returns a promise that resolves with a string (challenge response)
// We consider it successful if it doesn't throw
await relay.auth(async (eventTemplate) => {
return finalizeEvent(eventTemplate, normalizedKey);
});
return true;
} catch (error) {
console.error("Error handling AUTH challenge:", error);
return false;
@ -69,34 +34,21 @@ export async function ensureAuthenticated( @@ -69,34 +34,21 @@ export async function ensureAuthenticated(
privkey: string,
relayUrl: string
): Promise<boolean> {
return new Promise((resolve) => {
let challengeReceived = false;
let authHandled = false;
const timeout = setTimeout(() => {
if (!authHandled) {
resolve(true); // Assume no AUTH required if no challenge received
}
}, 2000);
try {
const normalizedKey = normalizeSecretKey(privkey);
// Listen for AUTH challenge
relay.on("auth", async (challenge: string) => {
challengeReceived = true;
clearTimeout(timeout);
const success = await handleAuthChallenge(relay, challenge, privkey, relayUrl);
authHandled = true;
resolve(success);
});
// Set up auth handler if relay sends challenge
relay.onauth = async (eventTemplate) => {
return finalizeEvent(eventTemplate, normalizedKey);
};
// If no challenge received within timeout, assume no AUTH required
setTimeout(() => {
if (!challengeReceived) {
clearTimeout(timeout);
authHandled = true;
resolve(true);
// Try to authenticate - this will only run if relay requires it
// The relay will call onauth if it needs authentication
return true;
} catch (error) {
console.error("Error ensuring authentication:", error);
return false;
}
}, 2000);
});
}
/**
@ -108,12 +60,17 @@ export async function handleAuthRequiredError( @@ -108,12 +60,17 @@ export async function handleAuthRequiredError(
relayUrl: string,
originalOperation: () => Promise<any>
): Promise<any> {
// Try to authenticate
const authenticated = await ensureAuthenticated(relay, privkey, relayUrl);
if (!authenticated) {
throw new Error("Failed to authenticate with relay");
}
try {
const normalizedKey = normalizeSecretKey(privkey);
// Authenticate using relay.auth()
await relay.auth(async (eventTemplate) => {
return finalizeEvent(eventTemplate, normalizedKey);
});
// Retry original operation
return originalOperation();
} catch (error: any) {
throw new Error(`Failed to authenticate with relay: ${error.message}`);
}
}

21
src/nostr/eventBuilder.ts

@ -4,7 +4,7 @@ import { EventKind, EventMetadata, SignedEvent } from "../types"; @@ -4,7 +4,7 @@ import { EventKind, EventMetadata, SignedEvent } from "../types";
/**
* Normalize secret key from bech32 nsec or hex format to hex
*/
export function normalizeSecretKey(key: string): string {
export function normalizeSecretKey(key: string): Uint8Array {
if (key.startsWith("nsec")) {
try {
const decoded = nip19.decode(key);
@ -17,7 +17,12 @@ export function normalizeSecretKey(key: string): string { @@ -17,7 +17,12 @@ export function normalizeSecretKey(key: string): string {
}
// Assume hex format (64 chars)
if (key.length === 64) {
return key.toLowerCase();
const hex = key.toLowerCase();
const bytes = new Uint8Array(32);
for (let i = 0; i < 32; i++) {
bytes[i] = parseInt(hex.substr(i * 2, 2), 16);
}
return bytes;
}
throw new Error("Invalid key format. Expected nsec bech32 or 64-char hex string.");
}
@ -30,6 +35,13 @@ export function getPubkeyFromPrivkey(privkey: string): string { @@ -30,6 +35,13 @@ export function getPubkeyFromPrivkey(privkey: string): string {
return getPublicKey(normalized);
}
/**
* Get public key from private key (Uint8Array version)
*/
export function getPubkeyFromPrivkeyBytes(privkey: Uint8Array): string {
return getPublicKey(privkey);
}
/**
* Build tags array from metadata
*/
@ -185,15 +197,14 @@ export function createSignedEvent( @@ -185,15 +197,14 @@ export function createSignedEvent(
const pubkey = getPublicKey(normalizedKey);
const created_at = createdAt || Math.floor(Date.now() / 1000);
const unsignedEvent = {
const eventTemplate = {
kind,
pubkey,
created_at,
tags,
content,
};
const signedEvent = finalizeEvent(unsignedEvent, normalizedKey);
const signedEvent = finalizeEvent(eventTemplate, normalizedKey);
return {
...signedEvent,

98
src/nostr/relayClient.ts

@ -1,4 +1,4 @@ @@ -1,4 +1,4 @@
import { Relay, relayInit } from "nostr-tools";
import { Relay } from "nostr-tools";
import { SignedEvent, PublishingResult } from "../types";
import { ensureAuthenticated, handleAuthRequiredError } from "./authHandler";
@ -14,73 +14,63 @@ export async function publishEventToRelay( @@ -14,73 +14,63 @@ export async function publishEventToRelay(
let relay: Relay | null = null;
try {
relay = relayInit(relayUrl);
relay = new Relay(relayUrl);
await relay.connect();
// Ensure authenticated if needed
await ensureAuthenticated(relay, privkey, relayUrl);
return new Promise((resolve) => {
const timer = setTimeout(() => {
if (relay) {
relay.close();
}
resolve({
eventId: event.id,
relay: relayUrl,
success: false,
message: "Timeout waiting for relay response",
});
}, timeout);
const publishPromise = new Promise<PublishingResult>((innerResolve) => {
relay!.on("ok", (ok) => {
if (ok.id === event.id) {
clearTimeout(timer);
relay?.close();
innerResolve({
eventId: event.id,
relay: relayUrl,
success: ok.ok,
message: ok.message || undefined,
// Set up notice handler for auth-required messages
const originalOnNotice = relay.onnotice;
relay.onnotice = (notice: string) => {
if (notice.includes("auth-required")) {
handleAuthRequiredError(relay!, privkey, relayUrl, async () => {
return await relay!.publish(event);
}).catch((error) => {
console.error("Auth failed:", error);
});
}
});
if (originalOnNotice) {
originalOnNotice(notice);
}
};
// Publish event - returns a promise that resolves with the reason string
// The reason indicates success (e.g., "seen", "duplicate") or failure
try {
const reason = await Promise.race([
relay.publish(event),
new Promise<string>((resolve) => {
setTimeout(() => resolve("timeout"), timeout);
}),
]);
relay.close();
// Check if publish was successful
// Reasons like "seen", "duplicate", "broadcast" indicate success
// "blocked", "invalid", etc. indicate failure
const success = reason !== "timeout" &&
!reason.toLowerCase().includes("error") &&
!reason.toLowerCase().includes("blocked") &&
!reason.toLowerCase().includes("invalid") &&
!reason.toLowerCase().includes("restricted");
relay!.on("error", (error) => {
clearTimeout(timer);
relay?.close();
innerResolve({
return {
eventId: event.id,
relay: relayUrl,
success: false,
message: error.message || "Relay error",
});
});
// Handle auth-required errors
relay!.on("notice", (notice) => {
if (notice.includes("auth-required")) {
handleAuthRequiredError(relay!, privkey, relayUrl, async () => {
relay!.publish(event);
}).catch((error) => {
clearTimeout(timer);
relay?.close();
innerResolve({
success,
message: success ? undefined : reason,
};
} catch (error: any) {
relay.close();
return {
eventId: event.id,
relay: relayUrl,
success: false,
message: `Auth failed: ${error.message}`,
});
});
message: error.message || "Publish failed",
};
}
});
relay!.publish(event);
});
publishPromise.then(resolve);
});
} catch (error: any) {
if (relay) {
relay.close();

5
src/relayManager.ts

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
import { Relay, relayInit, getPublicKey } from "nostr-tools";
import { Relay, getPublicKey } from "nostr-tools";
import { RelayInfo } from "./types";
import { normalizeSecretKey } from "./nostr/eventBuilder";
/**
* Default relay URLs to query for kind 10002
@ -60,7 +61,7 @@ export async function fetchRelayListFromRelay( @@ -60,7 +61,7 @@ export async function fetchRelayListFromRelay(
}, timeout);
try {
relay = relayInit(relayUrl);
relay = new Relay(relayUrl);
await relay.connect();
const sub = relay.subscribe(

6
src/types/js-yaml.d.ts vendored

@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
declare module "js-yaml" {
export function load(str: string, options?: any): any;
export function dump(obj: any, options?: any): string;
export function safeLoad(str: string, options?: any): any;
export function safeDump(obj: any, options?: any): string;
}
Loading…
Cancel
Save