Add prebuild script to fetch event kinds from nostr library

- Add scripts/fetch-kinds.js to fetch kinds.json from central source
- Add event-kinds.ts with TypeScript types and 184 event kinds
- Update package.json build scripts to fetch kinds before building
- Source: https://git.mleku.dev/mleku/nostr/raw/branch/main/encoders/kind/kinds.json

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
woikos
2025-12-21 05:08:00 +01:00
parent 8b6ead1f81
commit 7ff8e257dd
3 changed files with 1906 additions and 2 deletions

View File

@@ -15,10 +15,11 @@
"clean:firefox": "rimraf dist/firefox",
"start:chrome": "ng serve chrome",
"start:firefox": "ng serve firefox",
"fetch-kinds": "node scripts/fetch-kinds.js",
"prepare:chrome": "./chrome_prepare_manifest.sh",
"prepare:firefox": "./firefox_prepare_manifest.sh",
"build:chrome": "npm run prepare:chrome && ng build chrome",
"build:firefox": "npm run prepare:firefox && ng build firefox",
"build:chrome": "npm run fetch-kinds && npm run prepare:chrome && ng build chrome",
"build:firefox": "npm run fetch-kinds && npm run prepare:firefox && ng build firefox",
"watch:chrome": "npm run prepare:chrome && ng build chrome --watch --configuration development",
"watch:firefox": "npm run prepare:firefox && ng build firefox --watch --configuration development",
"test": "ng test",

File diff suppressed because it is too large Load Diff

147
scripts/fetch-kinds.js Normal file
View File

@@ -0,0 +1,147 @@
#!/usr/bin/env node
/**
* Fetches kinds.json from the nostr library and generates TypeScript definitions
* Run: node scripts/fetch-kinds.js
*/
import { writeFileSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const KINDS_URL = 'https://git.mleku.dev/mleku/nostr/raw/branch/main/encoders/kind/kinds.json';
async function fetchKinds() {
console.log(`Fetching kinds from ${KINDS_URL}...`);
const response = await fetch(KINDS_URL);
if (!response.ok) {
throw new Error(`Failed to fetch kinds.json: ${response.status} ${response.statusText}`);
}
const data = await response.json();
console.log(`Fetched ${Object.keys(data.kinds).length} kinds (version: ${data.version})`);
return data;
}
function generateTypeScript(data) {
const kinds = [];
for (const [kindNum, info] of Object.entries(data.kinds)) {
const k = parseInt(kindNum, 10);
// Determine classification
let classification = 'regular';
if (info.classification) {
classification = info.classification;
} else if (k === 0 || k === 3 || (k >= data.ranges.replaceable.start && k < data.ranges.replaceable.end)) {
classification = 'replaceable';
} else if (k >= data.ranges.parameterized.start && k <= data.ranges.parameterized.end) {
classification = 'parameterized';
} else if (k >= data.ranges.ephemeral.start && k < data.ranges.ephemeral.end) {
classification = 'ephemeral';
}
kinds.push({
kind: k,
name: info.name,
description: info.description,
nip: info.nip || null,
classification,
deprecated: info.deprecated || false,
spec: info.spec || null
});
}
// Sort by kind number
kinds.sort((a, b) => a.kind - b.kind);
return `/**
* Nostr Event Kinds Database
* Auto-generated from ${KINDS_URL}
* Version: ${data.version}
* Source: ${data.source}
*
* DO NOT EDIT - This file is auto-generated by scripts/fetch-kinds.js
*/
export interface KindInfo {
kind: number;
name: string;
description: string;
nip: string | null;
classification: 'regular' | 'replaceable' | 'ephemeral' | 'parameterized';
deprecated: boolean;
spec: string | null;
}
export interface KindRanges {
regular: { start: number; end: number; description: string };
replaceable: { start: number; end: number; description: string };
ephemeral: { start: number; end: number; description: string };
parameterized: { start: number; end: number; description: string };
}
export const EVENT_KINDS: KindInfo[] = ${JSON.stringify(kinds, null, 2)};
export const KIND_RANGES: KindRanges = ${JSON.stringify(data.ranges, null, 2)};
export const PRIVILEGED_KINDS: number[] = ${JSON.stringify(data.privileged)};
export const DIRECTORY_KINDS: number[] = ${JSON.stringify(data.directory)};
export const KIND_ALIASES: Record<string, number> = ${JSON.stringify(data.aliases, null, 2)};
// Lookup map for fast access
const kindMap = new Map<number, KindInfo>(EVENT_KINDS.map(k => [k.kind, k]));
export function getKindInfo(kind: number): KindInfo | undefined {
return kindMap.get(kind);
}
export function getKindName(kind: number): string {
const info = kindMap.get(kind);
return info ? info.name : \`Kind \${kind}\`;
}
export function isReplaceable(kind: number): boolean {
if (kind === 0 || kind === 3) return true;
return kind >= KIND_RANGES.replaceable.start && kind < KIND_RANGES.replaceable.end;
}
export function isEphemeral(kind: number): boolean {
return kind >= KIND_RANGES.ephemeral.start && kind < KIND_RANGES.ephemeral.end;
}
export function isParameterized(kind: number): boolean {
return kind >= KIND_RANGES.parameterized.start && kind <= KIND_RANGES.parameterized.end;
}
export function isPrivileged(kind: number): boolean {
return PRIVILEGED_KINDS.includes(kind);
}
export function isDirectoryKind(kind: number): boolean {
return DIRECTORY_KINDS.includes(kind);
}
`;
}
async function main() {
try {
const data = await fetchKinds();
const ts = generateTypeScript(data);
// Write to common library
const outPath = join(__dirname, '..', 'projects', 'common', 'src', 'lib', 'constants', 'event-kinds.ts');
writeFileSync(outPath, ts);
console.log(`Generated ${outPath} with ${Object.keys(data.kinds).length} kinds`);
} catch (error) {
console.error('Error:', error.message);
process.exit(1);
}
}
main();