8000 GitHub - AbianS/safetry: A TypeScript library for safe error handling with Result types
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

AbianS/safetry

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

5 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

@safetry/core

A TypeScript library for safe error handling using Result types, inspired by functional programming.

πŸš€ Features

  • Result Type: Explicit error handling without exceptions
  • TypeScript First: Fully typed with excellent type inference
  • Functional: API inspired by functional programming
  • Zero Dependencies: Lightweight library with no external dependencies
  • Async/Await: Full support for asynchronous operations

πŸ“¦ Installation

npm install @safetry/core

πŸ”§ Basic Usage

safetry Function

Converts operations that can fail into a Result type:

import { safetry } from '@safetry/core';

// Synchronous operation
const result = await safetry(() => {
  return JSON.parse('{"valid": "json"}');
});

if (result.ok) {
  console.log(result.value); // { valid: "json" }
} else {
  console.error(result.error); // Parsing error
}

// Asynchronous operation
const asyncResult = await safetry(async () => {
  const response = await fetch('/api/data');
  return await response.json();
});

Utility Functions

fallback - Default Values

import { safetry, fallback } from '@safetry/core';

const result = await safetry(() => riskyOperation());

// With static value
const value = fallback(result, 'default value');

// With function that receives the error
const valueWithError = fallback(result, (error) => {
  console.error('Operation failed:', error.message);
  return 'recovered value';
});

mapValue - Value Transformation

import { safetry, mapValue } from '@safetry/core';

const result = await safetry(() => getUserId());
const upperCased = mapValue(result, id => id.toUpperCase());

tapError - Error Logging

import { safetry, tapError } from '@safetry/core';

const result = await safetry(() => dangerousOperation());
const logged = tapError(result, (error) => {
  console.error('Error occurred:', error.message);
  // Send to logging service
});

unwrap - Extract Value or Throw Exception

import { safetry, unwrap } from '@safetry/core';

const result = await safetry(() => operation());

try {
  const value = unwrap(result); // Throws if result.ok === false
  console.log('Success:', value);
} catch (error) {
  console.error('Failed:', error.message);
}

πŸ”— Operation Chaining

import { safetry, mapValue, tapError, fallback } from '@safetry/core';

const processUser = async (userId: string) => {
  const result = await safetry(() => fetchUser(userId));
  
  return result
    |> tapError(#, error => logger.error('Fetch failed', error))
    |> mapValue(#, user => ({ ...user, processed: true }))
    |> fallback(#, { id: 'unknown', name: 'Anonymous', processed: false });
};

// Or without pipeline operator:
const processUserTraditional = async (userId: string) => {
  const result = await safetry(() => fetchUser(userId));
  const logged = tapError(result, error => logger.error('Fetch failed', error));
  const mapped = mapValue(logged, user => ({ ...user, processed: true }));
  return fallback(mapped, { id: 'unknown', name: 'Anonymous', processed: false });
};

πŸ”„ Asynchronous Operations

fallbackAsync

import { safetry, fallbackAsync } from '@safetry/core';

const result = safetry(async () => {
  const response = await fetch('/api/data');
  if (!response.ok) throw new Error('Network error');
  return await response.json();
});

// Asynchronous fallback
const data = await fallbackAsync(result, async (error) => {
  // Try local cache
  return await getCachedData();
});

// Synchronous fallback
const dataSync = await fallbackAsync(result, 'default data');

πŸ› οΈ Advanced Configuration

Error Transformation

import { safetry } from '@safetry/core';

const result = await safetry(
  () => riskyOperation(),
  {
    errorTransform: (raw) => {
      if (typeof raw === 'string') {
        return new ValidationError(raw);
      }
      return raw instanceof Error ? raw : new Error(String(raw));
    }
  }
);

Stack Trace Capture

import { safetry } from '@safetry/core';

const result = await safetry(
  () => operation(),
  { captureStack: true }
);

πŸ“š Advanced Examples

API with Error Handling

import { safetry, mapValue, tapError, fallback } from '@safetry/core';

class UserService {
  async getUser(id: string) {
    const result = await safetry(async () => {
      const response = await fetch(`/api/users/${id}`);
      if (!response.ok) {
        throw new Error(`HTTP ${response.status}: ${response.statusText}`);
      }
      return await response.json();
    });

    return result
      |> tapError(#, error => this.logger.error('User fetch failed', { id, error }))
      |> mapValue(#, user => new User(user))
      |> fallback(#, () => User.anonymous());
  }

  async updateUser(id: string, data: Partial<UserData>) {
    const fetchResult = await this.getUser(id);
    
    if (!fetchResult.ok) {
      return fetchResult; // Propagate the error
    }

    return await safetry(async () => {
      const response = await fetch(`/api/users/${id}`, {
        method: 'PUT',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(data)
      });
      
      if (!response.ok) {
        throw new Error(`Update failed: ${response.statusText}`);
      }
      
      return await response.json();
    });
  }
}

Form Validation

import { safetry, mapValue, fallback } from '@safetry/core';

interface FormData {
  email: string;
  age: number;
}

const validateForm = (data: unknown): FormData => {
  const emailResult = safetry(() => validateEmail(data.email));
  const ageResult = safetry(() => validateAge(data.age));

  const email = fallback(emailResult, '');
  const age = fallback(ageResult, 0);

  if (!emailResult.ok || !ageResult.ok) {
    throw new ValidationError('Form validation failed');
  }

  return { email, age };
};

const processForm = async (formData: unknown) => {
  const result = await safetry(() => validateForm(formData));
  
  return mapValue(result, validData => ({
    ...validData,
    timestamp: Date.now()
  }));
};

🀝 Contributing

Contributions are welcome! If you have ideas for improvements or have found a bug, please open an issue or submit a pull request.

  1. Fork the repository
  2. Create a new branch: git checkout -b feature/your-feature-name
  3. Make your changes and commit them: git commit -m 'Add some feature'
  4. Push to the branch: git push origin feature/your-feature-name
  5. Open a pull request

Please ensure your code follows the project's coding standards and includes appropriate tests.

πŸ“„ License

This project is licensed under the MIT License - see the LICENSE file for details.

πŸ’¬ Support

If you find this project useful, please consider giving it a ⭐ on GitHub. If you have any questions or need support, feel free to open an issue or contact me.


with πŸ’– by AbianS

0