An open API service indexing awesome lists of open source software.

https://github.com/pivanov/pivanov-utils


https://github.com/pivanov/pivanov-utils

Last synced: 20 days ago
JSON representation

Awesome Lists containing this project

README

        

# @pivanov/utils


A comprehensive collection of TypeScript utilities for modern web development




NPM Version
  
Bundle Size
  
CI Status
  
Coverage Status

## Features

- 🔄 **Type-Safe** - Full TypeScript support with strict type checking
- 🔄 **Immutable Operations** - Safe object and array manipulations
- 🎨 **String Transformations** - Comprehensive string formatting utilities
- 🛠️ **DOM Utilities** - Browser-safe DOM manipulation helpers
- ⚡ **Performance Focused** - Optimized for both speed and bundle size
- 📦 **Tree-Shakeable** - Import only what you need
- 📝 **Well Documented** - Detailed documentation and examples
- ✅ **Well Tested** - Comprehensive test coverage

## Installation

```bash
pnpm install @pivanov/utils
# or
yarn add @pivanov/utils
# or
npm install @pivanov/utils
```

## Documentation

### Module Overview

The package is organized into several modules:

- **assertion** - Type guards and runtime type checking
- **object** - Object manipulation utilities
- **promise** - Async utilities and promise helpers
- **string** - String transformation utilities
- **tools** - Various utilities including DOM, Event Bus, and more

### Assertion Module

Type-safe runtime type checking utilities.

```typescript
import {
isString,
isNumber,
isBoolean,
isObject,
isFunction,
isNull,
isUndefined
} from '@pivanov/utils/assertion';

// Type Guards with TypeScript type narrowing
isString('hello'); // type narrowed to string
isNumber(123); // type narrowed to number
isBoolean(true); // type narrowed to boolean
isObject({}); // type narrowed to object
isFunction(() => {}); // type narrowed to function
isNull(null); // type narrowed to null
isUndefined(void 0); // type narrowed to undefined

// Use in conditional checks
function processValue(value: unknown) {
if (isString(value)) {
return value.toUpperCase(); // TypeScript knows value is string
}
if (isNumber(value)) {
return value.toFixed(2); // TypeScript knows value is number
}
}
```

### Object Module

Type-safe object manipulation utilities.

```typescript
import { pick, omit, merge, deepMerge } from '@pivanov/utils/object';

// Pick specific properties
const user = { name: 'John', age: 30, email: '[email protected]' };
pick(user, ['name', 'email']);
// { name: 'John', email: '[email protected]' }

// Omit specific properties
omit(user, ['email']);
// { name: 'John', age: 30 }

// Shallow merge
merge({ a: 1 }, { b: 2 });
// { a: 1, b: 2 }

// Deep merge with nested structures
deepMerge(
{ user: { name: 'John', settings: { theme: 'dark' } } },
{ user: { settings: { fontSize: 14 } } }
);
// { user: { name: 'John', settings: { theme: 'dark', fontSize: 14 } } }
```

### Promise Module

Async utilities for better promise handling.

```typescript
import { sleep } from '@pivanov/utils/promise';

// Pause execution for specified duration
async function example() {
console.log('Start');
await sleep(1000); // Wait for 1 second
console.log('End');
}
```

### String Module

String manipulation utilities with TypeScript support.

```typescript
import {
camelCase,
pascalCase,
kebabCase,
slugify,
capitalize,
uncapitalize,
capitalizeFirstLetter
} from '@pivanov/utils/string';

// Case transformations
camelCase('foo-bar'); // 'fooBar'
pascalCase('foo_bar'); // 'FooBar'
kebabCase('fooBar'); // 'foo-bar'
slugify('Hello World!'); // 'hello-world'

// Capitalization with TypeScript support
capitalize('hello'); // 'Hello' (with type Capitalize<'hello'>)
uncapitalize('Hello'); // 'hello' (with type Uncapitalize<'Hello'>)
capitalizeFirstLetter('hello world'); // 'Hello world'
```

### Tools Module

Various utilities for DOM manipulation, event handling, and more.

#### DOM Utilities

```typescript
import { checkVisibility, setStyleProperties } from '@pivanov/utils/tools';

// Check element visibility
const isVisible = checkVisibility(element);

// Set CSS custom properties
setStyleProperties(element, {
'--background-color': '#fff',
'--text-color': '#000'
});
```

#### Event Bus

Type-safe event bus with React hooks support.

```typescript
import { busDispatch, busSubscribe, useEventBus } from '@pivanov/utils/tools/eventBus';

// Define your events interface
interface Events {
'user-logged-in': { id: number; name: string };
'data-updated': { timestamp: number };
}

// React hook usage
function Component() {
useEventBus('user-logged-in', (data) => {
console.log('User logged in:', data.name);
});
}

// Direct subscription
const unsubscribe = busSubscribe('data-updated', (data) => {
console.log('Data updated at:', data.timestamp);
});

// Dispatch events
busDispatch('user-logged-in', { id: 1, name: 'John' });
```

#### Deep Clone & Equality

```typescript
import { deepClone, isEqual } from '@pivanov/utils/tools';

// Deep clone with circular reference handling
const original = {
nested: { array: [1, 2, { value: 3 }] },
date: new Date(),
circular: {} as any
};
original.circular = original;
const cloned = deepClone(original);

// Deep equality comparison
isEqual({ a: [1, 2, 3] }, { a: [1, 2, 3] }); // true
isEqual(new Date('2024-01-01'), new Date('2024-01-01')); // true
isEqual([1, 2, [3, 4]], [1, 2, [3, 4]]); // true
```

#### Cache API

Browser-safe cache utilities with TypeScript support.

```typescript
import { CacheAPI } from '@pivanov/utils/tools/cache-api';

// Initialize cache
const cache = new CacheAPI('my-cache');

// Store data with expiration
await cache.set('user-data', { name: 'John' }, {
expireIn: '1h' // Supports: 's' (seconds), 'm' (minutes), 'h' (hours), 'd' (days)
});

// Retrieve data
const userData = await cache.get('user-data');

// Check if data exists and is not expired
const exists = await cache.has('user-data');

// Remove data
await cache.delete('user-data');

// Clear all cache
await cache.clear();
```

#### React to Web Components (r2wc)

A utility to convert React components into standalone Web Components that can be used in any application.

##### Creating a Widget

Create a single file for your widget (e.g., `sparkline-widget.ts`):
```typescript
import { registerWidget } from '@pivanov/utils';

// Your React component
const SparklineChart = ({ values, color }) => (


{/* Your chart implementation */}

);

// Register the widget with optional configuration
registerWidget({
name: 'sparkline',
component: SparklineChart,
styles: [
'https://cdn.example.com/styles/sparkline.css', // Optional: CSS files to load
],
svgSpritePath: 'https://cdn.example.com/icons/sprite.svg', // Optional: SVG sprite path
});
```

##### Using in React Applications

```typescript
import { importWidgets } from '@pivanov/utils';
import { createRoot } from 'react-dom/client';
import { App } from './app';

// Load widgets ... we need to do this once
void importWidgets([
'https://cdn.example.com/widgets/sparkline.js'
]);

const container = document.getElementById('root');
if (container) {
createRoot(container).render();
}

...

// Then use the widgets as React components

```

##### Using in Plain HTML

```html


import { importWidgets, renderWidget } from 'https://esm.sh/@pivanov/utils';

void importWidgets([
'https://cdn.example.com/widgets/sparkline.js'
]);

renderWidget({
name: 'sparkline',
mountTo: document.getElementById('sparkline'),
widgetProps: {
color: 'green',
values: [1, 2, 3, 4, 5]
}
});

```

Key Features:
- Single-file widget definition
- Automatic CSS and SVG sprite loading
- ESM support for browser and bundler usage
- TypeScript support with proper type inference
- Works in both React and plain HTML environments

### Tree Shaking

Import specific utilities to minimize bundle size:

```typescript
// Import only what you need
import { camelCase } from '@pivanov/utils/string';
import { deepClone } from '@pivanov/utils/tools';
import { isString } from '@pivanov/utils/assertion';
```

### TypeScript Integration

All utilities are written in TypeScript and provide excellent type inference:

```typescript
import { pick } from '@pivanov/utils/object';

// TypeScript will infer correct types
const user = { name: 'John', age: 30 } as const;
const picked = pick(user, ['name']); // Type: { name: "John" }
```

## Contributing

Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details.

## License

MIT © Pavel Ivanov