dbl-utils
Version:
Utilities for dbl, adba and others projects
508 lines (383 loc) โข 15.1 kB
Markdown
# dbl-utils
`dbl-utils` is a JavaScript/TypeScript utility library designed to simplify common application development tasks. This collection includes functions for event handling, queue processing, text manipulation, and date and currency formatting, among others.
[](https://joneldiablo.github.io/dbl-utils/modules.html)
[](https://deepwiki.com/joneldiablo/dbl-utils)
## Table of Contents
- [Installation](#installation)
- [Usage](#usage)
- [Main Modules](#main-modules)
- [Utilities](#utilities)
- [Documentation](#documentation)
- [License](#license)
## Installation
You can install `dbl-utils` via npm:
```bash
npm install dbl-utils
```
Or using yarn:
```bash
yarn add dbl-utils
```
## Usage
Import the modules and functions in your project as needed. Below is a basic example of how to use `dbl-utils`:
```javascript
// Import individual functions
import { formatCurrency, flatten, t } from 'dbl-utils';
// Use functions
console.log(formatCurrency(1234.56)); // Example of currency formatting
console.log(flatten({ a: { b: { c: 1 } } })); // Converts a nested object into a flat object
```
Minimal example of the CLI logic for CSS purging:
```ts
import purgeCss from 'dbl-utils/src/purge-css';
purgeCss('styles.css', 'index.html', 'clean.css');
```
Imports directly from any file to don't include all:
CommonJS use **/dist/cjs/\***
```javascript
// Import individual functions
const i18n = require('dbl-utils/dist/cjs/i18n');
// Use functions
console.log(i18n.formatCurrency(1234.56));
```
ESM use **/dist/esm/\***
```javascript
// Import individual functions
import t, { formatCurrency } from 'dbl-utils/dist/esm/i18n';
// Use functions
console.log(i18n.formatCurrency(1234.56));
```
TypeScript use **/src/\***
```javascript
// Import individual functions
import t, { formatCurrency } from 'dbl-utils/src/i18n';
// Use functions
console.log(i18n.formatCurrency(1234.56));
```
For a complete reference of all available functions, visit the [full documentation here](https://joneldiablo.github.io/dbl-utils/modules.html).
## Main Modules
Below are the main modules available in `dbl-utils`:
- [event-handler](https://github.com/joneldiablo/dbl-utils/blob/master/src/event-handler.ts)
- [fetch-queue](https://github.com/joneldiablo/dbl-utils/blob/master/src/fetch-queue.ts)
- [flat](https://github.com/joneldiablo/dbl-utils/blob/master/src/flat.ts)
- [format-value](https://github.com/joneldiablo/dbl-utils/blob/master/src/format-value.ts)
- [i18n](https://github.com/joneldiablo/dbl-utils/blob/master/src/i18n.ts)
- [object-mutation](https://github.com/joneldiablo/dbl-utils/blob/master/src/object-mutation.ts)
- [resolve-refs](https://github.com/joneldiablo/dbl-utils/blob/master/src/resolve-refs.ts)
- [utils](https://github.com/joneldiablo/dbl-utils/blob/master/src/utils.ts)
## Utilities
### event-handler
Decouple communication by subscribing to and dispatching custom events.
```ts
import { EventHandler } from 'dbl-utils';
const handler = new EventHandler();
handler.subscribe('ping', msg => console.log(msg), 'id'); // listen to events
await handler.dispatch('ping', 'pong'); // emit an event
handler.unsubscribe('ping', 'id'); // stop listening
```
### fetch-queue
Deduplicate concurrent HTTP calls so the same request is only made once.
```ts
import FetchQueue from 'dbl-utils/src/fetch-queue';
const queue = new FetchQueue(fetch);
const [a, b] = await Promise.all([
queue.addRequest('https://example.com'),
queue.addRequest('https://example.com')
]);
// a === b
```
### flat
Convert nested objects to and from dot notation.
```ts
import { flatten, unflatten } from 'dbl-utils';
flatten({ a: { b: 1 } }); // { 'a.b': 1 }
unflatten({ 'a.b': 1 }); // { a: { b: 1 } }
```
### format-value
Format numbers, dates, or dictionary entries using locale-aware helpers.
```ts
import formatValue from 'dbl-utils/src/format-value';
formatValue(1000, { format: 'currency', currency: 'USD' }); // "$1,000.00"
```
### i18n
Manage dictionaries and locale-aware formatting.
```ts
import t, { addDictionary, setLang, formatDate } from 'dbl-utils';
addDictionary({ es: { hello: 'Hola' } });
setLang('es');
t('hello'); // 'Hola'
formatDate(); // date formatted in Spanish
```
### object-mutation
Combine and transform objects without modifying the originals.
```ts
import { deepMerge, mergeWithMutation, transformJson } from 'dbl-utils';
deepMerge({}, { a: 1 }, { b: 2 }); // merge nested structures
await mergeWithMutation({ a: { b: 1 } }, { mutation: () => ({ c: 2 }) }); // async mutation
transformJson({ a: { b: 1 } }, { filter: 'a' }); // extract subset
```
### resolve-refs
Advanced reference resolution system for dynamic object composition and template inheritance. Perfect for configuration management, content templating, and complex data transformations.
#### Core Features
- **๐ Global References**: Access any value in your data schema
- **๐ Relative References**: Reference values within the current object context
- **๐ String Interpolation**: Embed references within strings seamlessly
- **๐จ Template Inheritance**: Create reusable object templates with property overrides
- **โ๏ธ Custom Rules & Tasks**: Define advanced transformation logic
- **๐ Recursive Resolution**: Handle complex nested reference chains
#### Reference Types
**1. Global References**
```ts
const config = { api: { url: "https://api.com", key: "secret" } };
const settings = {
endpoint: "$api/url", // Direct reference โ "https://api.com"
auth: "Bearer ${api/key}", // String interpolation โ "Bearer secret"
full: "${api/url}/v1/users" // Mixed interpolation โ "https://api.com/v1/users"
};
```
**2. Template Inheritance**
```ts
const data = {
// Base template
userTemplate: { name: "Guest", role: "viewer", active: false },
// Inherit and override properties
admin: { ref: "$userTemplate", name: "Admin", role: "admin", active: true },
john: { ref: "$userTemplate", name: "John Doe" }
};
const result = resolveRefs(data);
// result.admin = { name: "Admin", role: "admin", active: true }
// result.john = { name: "John Doe", role: "viewer", active: false }
```
**3. Relative References with Template System**
```ts
const data = {
user1: { ref: "$templates/user", firstName: "Alice", lastName: "Smith" },
user2: { ref: "$templates/user", firstName: "Bob", lastName: "Jones" },
templates: {
user: {
firstName: "",
lastName: "",
".": {
// These resolve AFTER template merging
fullName: "${./firstName} ${./lastName}", // Relative interpolation
email: "${./firstName}.${./lastName}@company.com", // Complex relative refs
profile: {
displayName: "$./fullName", // Reference to another relative ref
initials: "${./firstName/0}${./lastName/0}" // Access array/string indices
}
}
}
}
};
const result = resolveRefs(data);
// result.user1.fullName = "Alice Smith"
// result.user1.email = "Alice.Smith@company.com"
// result.user1.profile.displayName = "Alice Smith"
// result.user1.profile.initials = "AS"
```
#### Advanced Usage
**Configuration Management**
```ts
const config = {
// Environment settings
env: {
name: "production",
domain: "myapp.com",
apiVersion: "v2"
},
// Service definitions using templates
services: {
auth: { ref: "$templates/service", path: "/auth", timeout: 5000 },
users: { ref: "$templates/service", path: "/users", port: 8080 },
payments: { ref: "$templates/service", path: "/payments", ssl: true }
},
templates: {
service: {
path: "/",
port: 3000,
timeout: 30000,
ssl: false,
".": {
// Dynamic URL generation
baseUrl: "http${./ssl ? 's' : ''}://${env/domain}:${./port}",
fullUrl: "${./baseUrl}/${env/apiVersion}${./path}",
// Service configuration
config: {
endpoint: "$./fullUrl",
timeout: "$./timeout",
retries: 3,
headers: {
"X-Service-Name": "${env/name}",
"X-API-Version": "${env/apiVersion}"
}
}
}
}
}
};
const result = resolveRefs(config);
// result.services.auth.fullUrl = "http://myapp.com:3000/v2/auth"
// result.services.users.fullUrl = "http://myapp.com:8080/v2/users"
// result.services.payments.fullUrl = "https://myapp.com:3000/v2/payments"
```
**Custom Rules and Tasks**
```ts
const data = {
users: ["Alice", "Bob", "Charlie"],
products: [{ name: "Widget", price: 10 }, { name: "Gadget", price: 25 }]
};
const template = {
welcomeMessage: "$greetUsers",
productSummary: "$summarizeProducts",
totalValue: "$calculateTotal"
};
// Define custom processing rules
const rules = {
"$greetUsers": ["join", "$users", " and "],
"$summarizeProducts": ["iterate", "$products", "product"],
"$calculateTotal": ["sum", "$products", "price"]
};
// Custom task implementations
const extraTasks = {
sum: (array: any[], property: string) =>
array.reduce((total, item) => total + item[property], 0),
format: (template: string, ...values: any[]) =>
template.replace(/{(\d+)}/g, (_, i) => values[i]),
conditional: (condition: boolean, trueVal: any, falseVal: any) =>
condition ? trueVal : falseVal
};
const result = resolveRefs(template, data, rules, extraTasks);
// result.welcomeMessage = "Alice and Bob and Charlie"
// result.totalValue = 35
```
#### Built-in Tasks
- **`iterate(array, itemName)`** - Process array items with current schema context
- **`join(values, separator, ...extras)`** - Join arrays or concatenate values
- **`ignore(path, fallback)`** - Safe property access with fallback values
- **`if(condition, trueValue, falseValue)`** - Conditional value resolution
#### API Reference
```ts
resolveRefs<T>(
object: ResolvableValue, // Object/array with references to resolve
schema?: Record<string, any>, // Base schema for global references
rules?: ResolveRefsRules, // Custom rule definitions
extraTasks?: ResolveRefsTasks // Additional task implementations
): T
```
#### Best Practices
1. **๐๏ธ Structure**: Organize templates in dedicated sections (e.g., `templates/`, `definitions/`)
2. **๐ Naming**: Use descriptive paths like `config/database/url` over abbreviated versions
3. **๐ฏ Performance**: Avoid deep circular references and excessive nesting
4. **๐ Type Safety**: Define TypeScript interfaces for your schema structure
5. **๐งช Testing**: Test complex reference chains with various data combinations
#### Real-World Examples
For comprehensive examples and advanced use cases, see the [detailed examples documentation](./examples/resolve-refs-examples.md).
- **Multi-environment Configuration**: Different API endpoints per environment
- **Component Templates**: Reusable UI component configurations
- **Dynamic Content**: Blog posts with shared metadata and custom overrides
- **API Documentation**: Auto-generated endpoint documentation from templates
- **Feature Flags**: Conditional configuration based on environment/user settings
### utils
#### sliceIntoChunks
Split an array into smaller arrays for batching.
```ts
import { sliceIntoChunks } from 'dbl-utils';
sliceIntoChunks([1,2,3,4],2); // [[1,2],[3,4]]
```
#### splitAndFlat
Turn a list of strings into unique tokens.
```ts
import { splitAndFlat } from 'dbl-utils';
splitAndFlat(['a b','c']); // ['a','b','c']
```
#### generateRandomColors
Generate distinct colors for visualizations.
```ts
import { generateRandomColors } from 'dbl-utils';
generateRandomColors(2); // ['#aabbcc', '#ddeeff']
```
#### evaluateColorSimilarity
Check how close colors are to each other.
```ts
import { evaluateColorSimilarity } from 'dbl-utils';
evaluateColorSimilarity(['#fff','#ffe']); // value near 1
```
#### normalize
Remove accents and lowercase text.
```ts
import { normalize } from 'dbl-utils';
normalize('รก'); // 'a'
```
#### slugify
Create URL-friendly slugs.
```ts
import { slugify } from 'dbl-utils';
slugify('Hello World'); // 'hello-world'
```
#### randomS4
Produce a short hex segment.
```ts
import { randomS4 } from 'dbl-utils';
randomS4(); // '9f3b'
```
#### randomString
Generate a random alphanumeric string.
```ts
import { randomString } from 'dbl-utils';
randomString(5); // e.g., 'abcde'
```
#### timeChunks
Build time intervals between two dates.
```ts
import { timeChunks } from 'dbl-utils';
timeChunks({ from:'2020-01-01', to:'2020-01-02', step:3600 }); // [...]
```
#### delay
Pause execution for a given time.
```ts
import { delay } from 'dbl-utils';
await delay(10); // waits 10ms
```
#### hash
Generate a numeric hash.
```ts
import { hash } from 'dbl-utils';
hash('data'); // 123456789
```
#### LCG
Deterministic pseudo-random number generator.
```ts
import { LCG } from 'dbl-utils';
const gen = new LCG(123);
gen.random(); // 0.5967...
```
## Documentation
For a detailed description of each module and function, visit the [full documentation](https://joneldiablo.github.io/dbl-utils/modules.html) automatically generated with Typedoc. The documentation includes usage examples and in-depth explanations of each function.
For an in-depth analysis of the project architecture, codebase structure, and implementation details, check out the comprehensive [DeepWiki analysis](https://deepwiki.com/joneldiablo/dbl-utils).
## Testing
Run the test suite with:
```bash
npm test
```
This project uses Jest with ts-jest. New tests cover the `i18n` and `object-mutation` modules.
## Recent Changes
- **Comprehensive resolve-refs documentation**: Completely redesigned documentation with:
- Enhanced JSDoc comments with detailed examples and use cases
- Full TypeScript type definitions and interfaces
- Comprehensive README section with visual examples
- Real-world usage examples including configuration management, API documentation, and component systems
- Advanced examples covering feature flags, e-commerce catalogs, and multi-environment setups
- **Enhanced resolve-refs module**: Added support for relative references with `$./` and `${./}` syntax
- New template system using the `"."` key for relative references
- Ability to create reusable templates that can be extended with different values
- Support for references that point to other references (recursive resolution)
- Comprehensive unit tests covering all relative reference scenarios
- Fixed handling of numeric keys in `unflatten` so arrays are reconstructed correctly.
- Added unit tests for the `i18n` and `object-mutation` modules.
- Expanded coverage with additional tests for `utils`, `format-value`, and `i18n`.
## TODO
- Move number compact formatting to the i18n module.
## Development & Testing
When developing or debugging tests, use `yarn test -- <pattern>` to run only the relevant test cases.
## License
This project is under the ISC license. See the `LICENSE` file for more details.