Something went wrong. Try again.
[READ-ONLY] Mirror of https://github.com/just-cameron/tangled-cli. Automation-first CLI for Tangled.org
Something went wrong. Try again.
5.2 kB · 188 lines
TypeScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189import { z } from 'zod';
/** * Validation schema for AT Protocol handle * Supports standard Bluesky handles (user.bsky.social) and custom domains (example.com) */export const handleSchema: z.ZodString = z .string() .min(1, 'Handle cannot be empty') .regex( /^([a-zA-Z0-9]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?\.)+[a-zA-Z]([a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?$/, 'Invalid handle format. Must be a valid domain (e.g., user.bsky.social or example.com)' );
/** * Validation schema for AT Protocol DID */export const didSchema: z.ZodString = z .string() .min(1, 'DID cannot be empty') .regex( /^did:[a-z]+:[a-zA-Z0-9._:%-]*[a-zA-Z0-9._-]$/, 'Invalid DID format. Must start with "did:" followed by method and identifier' );
/** * Validation schema for app password * AT Protocol app passwords are typically 19 characters with dashes */export const appPasswordSchema: z.ZodString = z .string() .min(1, 'Password cannot be empty') .max(1000, 'Password is too long');
/** * Validation schema for identifier (handle or DID) */export const identifierSchema: z.ZodUnion<[typeof handleSchema, typeof didSchema]> = z.union([ handleSchema, didSchema,]);
/** * Validate a handle * @throws {z.ZodError} if validation fails */export function validateHandle(handle: string): string { return handleSchema.parse(handle);}
/** * Validate a DID * @throws {z.ZodError} if validation fails */export function validateDid(did: string): string { return didSchema.parse(did);}
/** * Validate an identifier (handle or DID) * @throws {z.ZodError} if validation fails */export function validateIdentifier(identifier: string): string { return identifierSchema.parse(identifier);}
/** * Validate an app password * @throws {z.ZodError} if validation fails */export function validateAppPassword(password: string): string { return appPasswordSchema.parse(password);}
/** * Safe validation that returns success/error instead of throwing */export function safeValidateHandle( handle: string): { success: true; data: string } | { success: false; error: string } { const result = handleSchema.safeParse(handle); if (result.success) { return { success: true, data: result.data }; } return { success: false, error: result.error.issues[0]?.message ?? 'Validation failed' };}
/** * Safe validation that returns success/error instead of throwing */export function safeValidateDid( did: string): { success: true; data: string } | { success: false; error: string } { const result = didSchema.safeParse(did); if (result.success) { return { success: true, data: result.data }; } return { success: false, error: result.error.issues[0]?.message ?? 'Validation failed' };}
/** * Safe validation that returns success/error instead of throwing */export function safeValidateIdentifier( identifier: string): { success: true; data: string } | { success: false; error: string } { const result = identifierSchema.safeParse(identifier); if (result.success) { return { success: true, data: result.data }; } return { success: false, error: result.error.issues[0]?.message ?? 'Validation failed' };}
/** * Validation schema for Tangled-specific DID (did:plc: format only) */export const tangledDidSchema: z.ZodString = z .string() .regex(/^did:plc:[a-z0-9]+$/, 'Invalid Tangled DID format. Expected: did:plc:...');
/** * Check if a string is a valid AT Protocol handle * Returns true/false without throwing */export function isValidHandle(handle: string): boolean { return handleSchema.safeParse(handle).success;}
/** * Check if a string is a valid Tangled DID (did:plc: format) * Returns true/false without throwing */export function isValidTangledDid(did: string): boolean { return tangledDidSchema.safeParse(did).success;}
/** * Validation schema for issue title * Titles must be 1-256 characters */export const issueTitleSchema: z.ZodString = z .string() .min(1, 'Issue title cannot be empty') .max(256, 'Issue title must be 256 characters or less');
/** * Validation schema for issue body * Body is optional but limited to 50,000 characters */export const issueBodySchema: z.ZodOptional<z.ZodString> = z .string() .max(50000, 'Issue body must be 50,000 characters or less') .optional();
/** * Validation schema for AT-URI * Format: at://did:method:identifier/collection[/rkey] */export const atUriSchema: z.ZodString = z .string() .regex( /^at:\/\/did:[a-z]+:[a-zA-Z0-9._:%-]+\/[a-zA-Z0-9._-]+(?:\.[a-zA-Z0-9._-]+)*(?:\/[a-zA-Z0-9._-]+)?$/, 'Invalid AT-URI format. Expected: at://did:method:id/collection[/rkey]' );
/** * Validate an issue title * @throws {z.ZodError} if validation fails */export function validateIssueTitle(title: string): string { return issueTitleSchema.parse(title);}
/** * Validate an issue body * @throws {z.ZodError} if validation fails */export function validateIssueBody(body: string): string { return issueBodySchema.parse(body) ?? '';}
/** * Check if a string is a valid AT-URI * Returns true/false without throwing */export function isValidAtUri(uri: string): boolean { return atUriSchema.safeParse(uri).success;}