Something went wrong. Try again.
WIP: A simple cli for daily tangled use cases and AI integration. This is for my personal use right now, but happy if others get mileage from it! :)
Something went wrong. Try again.
2.5 kB · 101 lines
TypeScript
at commit ac6cce98
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102/** * Git utilities for parsing and validating tangled.org remote URLs */
import { isValidHandle, isValidTangledDid } from './validation.js';
export interface ParsedTangledRemote { owner: string; ownerType: 'did' | 'handle'; name: string; protocol: 'ssh' | 'https';}
/** * Check if a Git remote URL is a tangled.org URL * @param url - Git remote URL * @returns true if URL points to tangled.org */export function isTangledRemote(url: string): boolean { // Match tangled.org in SSH or HTTPS URLs return ( url.includes('tangled.org') && (url.startsWith('git@tangled.org:') || url.startsWith('ssh://git@tangled.org') || url.startsWith('https://tangled.org')) );}
/** * Parse a tangled.org Git remote URL to extract owner and repo name * @param url - Git remote URL * @returns Parsed remote info or null if not a valid tangled URL */export function parseTangledRemote(url: string): ParsedTangledRemote | null { if (!isTangledRemote(url)) { return null; }
let path: string; let protocol: 'ssh' | 'https';
// Parse based on protocol if (url.startsWith('https://tangled.org')) { // HTTPS: https://tangled.org/owner/repo protocol = 'https'; path = url.replace(/^https:\/\/tangled\.org\//, ''); } else if (url.startsWith('ssh://git@tangled.org')) { // SSH with ssh:// prefix: ssh://git@tangled.org/owner/repo.git protocol = 'ssh'; path = url.replace(/^ssh:\/\/git@tangled\.org\//, ''); } else if (url.startsWith('git@tangled.org:')) { // SSH shorthand: git@tangled.org:owner/repo.git protocol = 'ssh'; path = url.replace(/^git@tangled\.org:/, ''); } else { return null; }
// Remove trailing slashes path = path.replace(/\/+$/, '');
// Remove .git extension if present path = path.replace(/\.git$/, '');
// Split path into owner and repo name const parts = path.split('/'); if (parts.length < 2) { return null; }
const owner = parts[0]; const name = parts[1];
// Validate that we have both parts if (!owner || !name) { return null; }
// Determine owner type based on format let ownerType: 'did' | 'handle'; if (owner.startsWith('did:plc:')) { ownerType = 'did'; // Validate DID format if (!isValidTangledDid(owner)) { return null; } } else { ownerType = 'handle'; // Validate handle format if (!isValidHandle(owner)) { return null; } }
return { owner, ownerType, name, protocol, };}