or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

bundles-queries.mdcore-payload-types.mdindex.mdstorage-metadata.mdtype-guards.mdutility-types.mdvalidation-errors.md

validation-errors.mddocs/

0

# Validation and Error Handling

1

2

Comprehensive validation framework with sync/async validation functions, structured error payload types, and Zod integration for runtime validation within the XYO Protocol 2.0 ecosystem.

3

4

## Capabilities

5

6

### Payload Validation Functions

7

8

Type definitions for synchronous and asynchronous payload validation functions with flexible validation patterns.

9

10

```typescript { .api }

11

/**

12

* Synchronous payload validation function

13

* @param payload - Payload to validate

14

* @returns Boolean indicating validation result

15

*/

16

type SyncPayloadValidationFunction<T extends Payload = Payload> = (payload: T) => boolean;

17

18

/**

19

* Asynchronous payload validation function

20

* @param payload - Payload to validate

21

* @returns Promise resolving to boolean validation result

22

*/

23

type AsyncPayloadValidationFunction<T extends Payload = Payload> = (payload: T) => Promise<boolean>;

24

25

/**

26

* Union type for both sync and async validation functions

27

*/

28

type PayloadValidationFunction<T extends Payload = Payload> =

29

SyncPayloadValidationFunction<T> | AsyncPayloadValidationFunction<T>;

30

```

31

32

### Zod Validation Schemas

33

34

Zod-based validation schemas for runtime payload validation and type checking with full TypeScript integration.

35

36

```typescript { .api }

37

/**

38

* Import Zod for schema validation

39

*/

40

import * as z from 'zod';

41

42

/**

43

* Storage metadata Zod schema

44

*/

45

const StorageMetaZod: z.ZodObject<{

46

_hash: z.ZodType<Hash>;

47

_dataHash: z.ZodType<Hash>;

48

_sequence: z.ZodType<string>;

49

}>;

50

51

/**

52

* Base payload Zod schema

53

*/

54

const PayloadZod: z.ZodObject<{

55

schema: z.ZodType<Schema>;

56

}>;

57

58

/**

59

* Payload with storage metadata Zod schema

60

*/

61

const PayloadWithStorageMetaZod: z.ZodIntersection<

62

typeof PayloadZod,

63

typeof StorageMetaZod

64

>;

65

66

/**

67

* Any payload with flexible additional properties

68

*/

69

const AnyPayloadZod: z.ZodObject<{

70

schema: z.ZodType<Schema>;

71

}> & z.ZodCatchall<z.ZodAny>;

72

73

/**

74

* Any payload with storage metadata

75

*/

76

const AnyPayloadWithStorageMetaZod: z.ZodIntersection<

77

typeof AnyPayloadZod,

78

typeof StorageMetaZod

79

>;

80

81

/**

82

* Inferred types from Zod schemas

83

*/

84

type PayloadWithStorageMeta = z.infer<typeof PayloadWithStorageMetaZod>;

85

type AnyPayload = z.infer<typeof AnyPayloadZod>;

86

type AnyPayloadWithStorageMeta = z.infer<typeof AnyPayloadWithStorageMetaZod>;

87

88

/**

89

* Helper function to create payload schema with storage metadata

90

*/

91

function WithStorageMetaZod<T extends typeof PayloadZod>(valueZod: T): z.ZodIntersection<typeof StorageMetaZod, T>;

92

```

93

94

**Usage Examples:**

95

96

```typescript

97

import {

98

PayloadValidationFunction,

99

SyncPayloadValidationFunction,

100

AsyncPayloadValidationFunction,

101

Payload

102

} from "@xyo-network/payload-model";

103

104

// Define custom payload type

105

interface UserPayload extends Payload {

106

schema: "network.example.user";

107

name: string;

108

email: string;

109

age: number;

110

}

111

112

// Synchronous validation function

113

const validateUserSync: SyncPayloadValidationFunction<UserPayload> = (payload) => {

114

if (!payload.name || payload.name.length < 2) return false;

115

if (!payload.email || !payload.email.includes('@')) return false;

116

if (!payload.age || payload.age < 0 || payload.age > 150) return false;

117

return true;

118

};

119

120

// Asynchronous validation function

121

const validateUserAsync: AsyncPayloadValidationFunction<UserPayload> = async (payload) => {

122

// Simulate async validation (e.g., database check)

123

const emailExists = await checkEmailExists(payload.email);

124

if (emailExists) return false;

125

126

const nameValid = await validateNameFormat(payload.name);

127

return nameValid && payload.age >= 18;

128

};

129

130

// Generic validation function

131

const validateUser: PayloadValidationFunction<UserPayload> = validateUserSync;

132

133

// Use validation functions

134

const userPayload: UserPayload = {

135

schema: "network.example.user",

136

name: "Alice",

137

email: "alice@example.com",

138

age: 25

139

};

140

141

// Sync validation

142

if (validateUserSync(userPayload)) {

143

console.log("User payload is valid");

144

}

145

146

// Async validation

147

const isValid = await validateUserAsync(userPayload);

148

if (isValid) {

149

console.log("User payload passed async validation");

150

}

151

152

// Helper functions (examples)

153

async function checkEmailExists(email: string): Promise<boolean> {

154

// Simulate database check

155

return Promise.resolve(false);

156

}

157

158

async function validateNameFormat(name: string): Promise<boolean> {

159

// Simulate external validation service

160

return Promise.resolve(name.length >= 2 && /^[a-zA-Z\s]+$/.test(name));

161

}

162

```

163

164

### Module Error System

165

166

Structured error payload system for handling and communicating errors within XYO modules and operations.

167

168

```typescript { .api }

169

/**

170

* Schema constant for module errors

171

*/

172

const ModuleErrorSchema: "network.xyo.error.module";

173

174

/**

175

* Type alias for module error schema

176

*/

177

type ModuleErrorSchema = typeof ModuleErrorSchema;

178

179

/**

180

* Import JsonValue type from @xylabs/object

181

*/

182

import type { JsonValue } from '@xylabs/object';

183

184

/**

185

* Module error payload type with comprehensive error information

186

*/

187

type ModuleError = Payload<{

188

/** Additional error details as JSON value */

189

details?: JsonValue;

190

191

/** Human-readable error message */

192

message?: string;

193

194

/** Error name or type identifier */

195

name?: string;

196

197

/** Query hash or schema that caused the error */

198

query?: Hash | Schema;

199

200

/** Module error schema */

201

schema: ModuleErrorSchema;

202

}>;

203

204

/**

205

* Type guard for module error validation

206

*/

207

function isModuleError(value: unknown): value is ModuleError;

208

```

209

210

**Usage Examples:**

211

212

```typescript

213

import {

214

ModuleError,

215

ModuleErrorSchema,

216

isModuleError,

217

Payload,

218

Hash,

219

Schema

220

} from "@xyo-network/payload-model";

221

222

// Create basic module error

223

const basicError: ModuleError = {

224

schema: ModuleErrorSchema,

225

message: "Validation failed",

226

name: "ValidationError"

227

};

228

229

// Create detailed module error

230

const detailedError: ModuleError = {

231

schema: ModuleErrorSchema,

232

message: "User payload validation failed",

233

name: "UserValidationError",

234

details: {

235

field: "email",

236

reason: "Invalid email format",

237

value: "invalid-email",

238

code: "EMAIL_INVALID"

239

},

240

query: "network.example.user" as Schema

241

};

242

243

// Create error with query hash

244

const queryError: ModuleError = {

245

schema: ModuleErrorSchema,

246

message: "Query execution failed",

247

name: "QueryExecutionError",

248

details: {

249

timeout: true,

250

duration: 30000,

251

retries: 3

252

},

253

query: "0x1234567890abcdef..." as Hash

254

};

255

256

// Error handling utility

257

function createModuleError(

258

message: string,

259

name: string,

260

details?: any,

261

query?: Hash | Schema

262

): ModuleError {

263

return {

264

schema: ModuleErrorSchema,

265

message,

266

name,

267

details,

268

query

269

};

270

}

271

272

// Validate and handle errors

273

function processPayload(payload: unknown): Payload | ModuleError {

274

if (!payload || typeof payload !== 'object') {

275

return createModuleError(

276

"Invalid payload format",

277

"PayloadFormatError",

278

{ received: typeof payload }

279

);

280

}

281

282

if (isModuleError(payload)) {

283

console.error("Module error detected:", payload.message);

284

return payload;

285

}

286

287

// Process valid payload

288

return payload as Payload;

289

}

290

291

// Error result handling

292

function handleResult(result: Payload | ModuleError) {

293

if (isModuleError(result)) {

294

console.error(`Error: ${result.name} - ${result.message}`);

295

if (result.details) {

296

console.error("Details:", result.details);

297

}

298

if (result.query) {

299

console.error("Related query:", result.query);

300

}

301

return null;

302

}

303

304

return result;

305

}

306

307

// Use in validation pipeline

308

async function validateAndProcess<T extends Payload>(

309

payload: T,

310

validator: PayloadValidationFunction<T>

311

): Promise<T | ModuleError> {

312

try {

313

const isValid = await Promise.resolve(validator(payload));

314

315

if (!isValid) {

316

return createModuleError(

317

"Payload validation failed",

318

"ValidationError",

319

{ schema: payload.schema },

320

payload.schema

321

);

322

}

323

324

return payload;

325

} catch (error) {

326

return createModuleError(

327

"Validation process failed",

328

"ValidationProcessError",

329

{

330

originalError: error instanceof Error ? error.message : String(error),

331

schema: payload.schema

332

},

333

payload.schema

334

);

335

}

336

}

337

```

338

339

### Zod Integration

340

341

Runtime validation schemas using Zod for comprehensive payload structure validation and type safety.

342

343

```typescript { .api }

344

/**

345

* Base Zod schema for payload validation

346

*/

347

const PayloadZod: ZodType<{ schema: Schema }>;

348

349

/**

350

* Zod schema for storage metadata validation

351

*/

352

const StorageMetaZod: ZodType<{

353

_hash: Hash;

354

_dataHash: Hash;

355

_sequence: Sequence;

356

}>;

357

358

/**

359

* Zod schema for payload with storage metadata

360

*/

361

const PayloadWithStorageMetaZod: ZodType<PayloadWithStorageMeta>;

362

363

/**

364

* Catch-all Zod schema for any payload with additional properties

365

*/

366

const AnyPayloadZod: ZodType<AnyPayload>;

367

368

/**

369

* Catch-all Zod schema for any payload with storage metadata

370

*/

371

const AnyPayloadWithStorageMetaZod: ZodType<AnyPayloadWithStorageMeta>;

372

373

/**

374

* Helper function to add storage metadata validation to existing schema

375

*/

376

function WithStorageMetaZod<T extends typeof PayloadZod>(

377

valueZod: T

378

): ZodType<StorageMeta & z.infer<T>>;

379

380

/**

381

* Inferred types from Zod schemas

382

*/

383

type PayloadWithStorageMeta = z.infer<typeof PayloadWithStorageMetaZod>;

384

type AnyPayload = z.infer<typeof AnyPayloadZod>;

385

type AnyPayloadWithStorageMeta = z.infer<typeof AnyPayloadWithStorageMetaZod>;

386

```

387

388

**Usage Examples:**

389

390

```typescript

391

import {

392

PayloadZod,

393

AnyPayloadZod,

394

StorageMetaZod,

395

PayloadWithStorageMetaZod,

396

WithStorageMetaZod

397

} from "@xyo-network/payload-model";

398

import * as z from "zod";

399

400

// Create custom payload schema

401

const UserPayloadZod = z.object({

402

schema: z.literal("network.example.user"),

403

name: z.string().min(2).max(50),

404

email: z.string().email(),

405

age: z.number().int().min(0).max(150),

406

preferences: z.object({

407

theme: z.enum(["light", "dark"]).optional(),

408

notifications: z.boolean().optional()

409

}).optional()

410

});

411

412

type UserPayload = z.infer<typeof UserPayloadZod>;

413

414

// Validate user payload

415

const userData = {

416

schema: "network.example.user",

417

name: "Alice",

418

email: "alice@example.com",

419

age: 25,

420

preferences: {

421

theme: "dark",

422

notifications: true

423

}

424

};

425

426

try {

427

const validUser = UserPayloadZod.parse(userData);

428

console.log("Valid user:", validUser.name);

429

} catch (error) {

430

if (error instanceof z.ZodError) {

431

console.error("Validation errors:", error.errors);

432

}

433

}

434

435

// Validate any payload

436

const unknownPayload = {

437

schema: "network.example.unknown",

438

data: "some data",

439

timestamp: Date.now()

440

};

441

442

const validPayload = AnyPayloadZod.parse(unknownPayload);

443

console.log("Valid payload schema:", validPayload.schema);

444

445

// Add storage metadata to custom schema

446

const UserWithStorageZod = WithStorageMetaZod(UserPayloadZod);

447

448

const userWithStorageData = {

449

schema: "network.example.user",

450

name: "Bob",

451

email: "bob@example.com",

452

age: 30,

453

_hash: "0x123...",

454

_dataHash: "0x456...",

455

_sequence: "1234567890abcdef"

456

};

457

458

const validUserWithStorage = UserWithStorageZod.parse(userWithStorageData);

459

console.log("User with storage:", validUserWithStorage.name);

460

console.log("Storage hash:", validUserWithStorage._hash);

461

462

// Validation with error handling

463

function validatePayloadSafely<T>(

464

schema: z.ZodType<T>,

465

data: unknown

466

): { success: true; data: T } | { success: false; errors: z.ZodError } {

467

try {

468

const validated = schema.parse(data);

469

return { success: true, data: validated };

470

} catch (error) {

471

if (error instanceof z.ZodError) {

472

return { success: false, errors: error };

473

}

474

throw error;

475

}

476

}

477

478

// Use safe validation

479

const result = validatePayloadSafely(UserPayloadZod, userData);

480

if (result.success) {

481

console.log("Validated user:", result.data.name);

482

} else {

483

console.error("Validation failed:", result.errors.errors);

484

}

485

```

486

487

### Advanced Validation Patterns

488

489

Complex validation scenarios and patterns for robust payload processing.

490

491

```typescript { .api }

492

/**

493

* Schema validation with regex pattern

494

*/

495

const SchemaZod: ZodType<Schema>;

496

497

/**

498

* Schema validation functions

499

*/

500

function isSchema(value: unknown): value is Schema;

501

function asSchema(value: unknown): Schema;

502

```

503

504

**Usage Examples:**

505

506

```typescript

507

import {

508

PayloadValidationFunction,

509

ModuleError,

510

ModuleErrorSchema,

511

createModuleError,

512

SchemaZod,

513

AnyPayloadZod

514

} from "@xyo-network/payload-model";

515

import * as z from "zod";

516

517

// Complex validation pipeline

518

class PayloadValidator {

519

private validators: Map<string, PayloadValidationFunction> = new Map();

520

private schemas: Map<string, z.ZodType<any>> = new Map();

521

522

// Register schema validator

523

registerSchema<T extends Payload>(

524

schema: string,

525

zodSchema: z.ZodType<T>,

526

customValidator?: PayloadValidationFunction<T>

527

) {

528

this.schemas.set(schema, zodSchema);

529

if (customValidator) {

530

this.validators.set(schema, customValidator);

531

}

532

}

533

534

// Validate payload with comprehensive error reporting

535

async validatePayload(payload: unknown): Promise<{

536

valid: boolean;

537

payload?: Payload;

538

errors: ModuleError[];

539

}> {

540

const errors: ModuleError[] = [];

541

542

// Basic structure validation

543

try {

544

const basicPayload = AnyPayloadZod.parse(payload);

545

546

// Schema format validation

547

if (!SchemaZod.safeParse(basicPayload.schema).success) {

548

errors.push({

549

schema: ModuleErrorSchema,

550

message: "Invalid schema format",

551

name: "SchemaFormatError",

552

details: { schema: basicPayload.schema }

553

});

554

return { valid: false, errors };

555

}

556

557

// Schema-specific validation

558

const zodSchema = this.schemas.get(basicPayload.schema);

559

if (zodSchema) {

560

const zodResult = zodSchema.safeParse(payload);

561

if (!zodResult.success) {

562

errors.push({

563

schema: ModuleErrorSchema,

564

message: "Schema validation failed",

565

name: "ZodValidationError",

566

details: {

567

errors: zodResult.error.errors,

568

schema: basicPayload.schema

569

},

570

query: basicPayload.schema

571

});

572

}

573

}

574

575

// Custom validation

576

const customValidator = this.validators.get(basicPayload.schema);

577

if (customValidator) {

578

try {

579

const isValid = await Promise.resolve(customValidator(basicPayload));

580

if (!isValid) {

581

errors.push({

582

schema: ModuleErrorSchema,

583

message: "Custom validation failed",

584

name: "CustomValidationError",

585

details: { schema: basicPayload.schema },

586

query: basicPayload.schema

587

});

588

}

589

} catch (error) {

590

errors.push({

591

schema: ModuleErrorSchema,

592

message: "Custom validation error",

593

name: "CustomValidationException",

594

details: {

595

error: error instanceof Error ? error.message : String(error),

596

schema: basicPayload.schema

597

},

598

query: basicPayload.schema

599

});

600

}

601

}

602

603

return {

604

valid: errors.length === 0,

605

payload: errors.length === 0 ? basicPayload : undefined,

606

errors

607

};

608

609

} catch (error) {

610

errors.push({

611

schema: ModuleErrorSchema,

612

message: "Payload structure validation failed",

613

name: "StructureValidationError",

614

details: {

615

error: error instanceof Error ? error.message : String(error)

616

}

617

});

618

619

return { valid: false, errors };

620

}

621

}

622

623

// Batch validation

624

async validateBatch(payloads: unknown[]): Promise<{

625

valid: Payload[];

626

invalid: { payload: unknown; errors: ModuleError[] }[];

627

}> {

628

const valid: Payload[] = [];

629

const invalid: { payload: unknown; errors: ModuleError[] }[] = [];

630

631

for (const payload of payloads) {

632

const result = await this.validatePayload(payload);

633

if (result.valid && result.payload) {

634

valid.push(result.payload);

635

} else {

636

invalid.push({ payload, errors: result.errors });

637

}

638

}

639

640

return { valid, invalid };

641

}

642

}

643

644

// Usage example

645

const validator = new PayloadValidator();

646

647

// Register user schema

648

const UserSchema = z.object({

649

schema: z.literal("network.example.user"),

650

name: z.string().min(2),

651

email: z.string().email(),

652

age: z.number().int().min(0)

653

});

654

655

const userCustomValidator: PayloadValidationFunction = async (payload) => {

656

// Custom business logic validation

657

return payload.name !== "admin"; // Example: no admin users allowed

658

};

659

660

validator.registerSchema("network.example.user", UserSchema, userCustomValidator);

661

662

// Validate payloads

663

const testPayloads = [

664

{ schema: "network.example.user", name: "Alice", email: "alice@example.com", age: 25 },

665

{ schema: "network.example.user", name: "admin", email: "admin@example.com", age: 35 },

666

{ schema: "invalid.schema.format", data: "test" },

667

"invalid payload"

668

];

669

670

const batchResult = await validator.validateBatch(testPayloads);

671

console.log(`Valid: ${batchResult.valid.length}, Invalid: ${batchResult.invalid.length}`);

672

673

batchResult.invalid.forEach(({ payload, errors }) => {

674

console.error("Invalid payload:", errors.map(e => e.message));

675

});

676

```

677

678

## Advanced Error Handling Patterns

679

680

### Error Recovery and Transformation

681

682

```typescript

683

import { ModuleError, ModuleErrorSchema, Payload } from "@xyo-network/payload-model";

684

685

// Error recovery utilities

686

class ErrorRecovery {

687

// Attempt to recover from validation errors

688

static tryRecover(error: ModuleError, originalPayload: unknown): Payload | null {

689

if (error.name === "SchemaFormatError" && error.details?.schema) {

690

// Try to fix common schema format issues

691

const fixedSchema = this.fixSchemaFormat(error.details.schema);

692

if (fixedSchema && typeof originalPayload === 'object' && originalPayload) {

693

return { ...(originalPayload as object), schema: fixedSchema };

694

}

695

}

696

697

return null;

698

}

699

700

private static fixSchemaFormat(schema: string): string | null {

701

// Example: fix common schema format issues

702

if (schema.includes("_")) {

703

return schema.replace(/_/g, ".");

704

}

705

if (schema.toUpperCase() === schema) {

706

return schema.toLowerCase();

707

}

708

return null;

709

}

710

711

// Transform errors for external reporting

712

static transformError(error: ModuleError): {

713

code: string;

714

message: string;

715

details?: any;

716

} {

717

return {

718

code: error.name || "UNKNOWN_ERROR",

719

message: error.message || "An unknown error occurred",

720

details: error.details

721

};

722

}

723

}

724

```

725

726

## Types Reference

727

728

### Validation Function Types

729

730

- **`SyncPayloadValidationFunction<T>`**: Synchronous validation function type

731

- **`AsyncPayloadValidationFunction<T>`**: Asynchronous validation function type

732

- **`PayloadValidationFunction<T>`**: Union of sync/async validation functions

733

734

### Error Types

735

736

- **`ModuleError`**: Structured error payload type

737

- **`ModuleErrorSchema`**: Module error schema constant

738

739

### Zod Integration Types

740

741

- **`PayloadWithStorageMeta`**: Payload with storage metadata (inferred from Zod)

742

- **`AnyPayload`**: Any payload type (inferred from Zod)

743

- **`AnyPayloadWithStorageMeta`**: Any payload with storage metadata (inferred from Zod)

744

745

### Validation Schema Types

746

747

- **`PayloadZod`**: Base payload Zod schema

748

- **`StorageMetaZod`**: Storage metadata Zod schema

749

- **`PayloadWithStorageMetaZod`**: Payload with storage metadata Zod schema

750

- **`AnyPayloadZod`**: Catch-all payload Zod schema

751

- **`AnyPayloadWithStorageMetaZod`**: Catch-all payload with storage metadata Zod schema

752

753

### Constants

754

755

- **`ModuleErrorSchema`**: "network.xyo.error.module"

756

757

### Functions

758

759

- **`isModuleError(value)`**: Type guard for module errors

760

- **`WithStorageMetaZod<T>(schema)`**: Add storage metadata validation to Zod schema