@ffsm/serialize
Version:
Utilities for serialize
176 lines (175 loc) • 6.68 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import Nullish from '@ffsm/nullish';
import { get } from './get';
/**
* Asynchronously replaces variable placeholders in a string with corresponding values.
*
* This function takes a template string with variable placeholders in the format
* `{variableName}` and replaces them with values from the provided params object.
* It supports deep property access using dot notation and asynchronous formatting.
*
* @param text - The template string containing variables in the format `{variableName}`
* @param options - Configuration options including parameters and formatters
* @param options.params - An object containing values to replace variables
* @param options.format - An object mapping variable names to formatter functions (can be async)
* @returns A Promise resolving to the text with all variables replaced
*
* @example
* ```typescript
* // Basic usage
* await variableAsync('Hello, {name}!', {
* params: { name: 'John' }
* });
* // 'Hello, John!'
*
* // Deep property access
* await variableAsync('User: {user.profile.name}, Age: {user.profile.age}', {
* params: {
* user: {
* profile: {
* name: 'Alice',
* age: 30
* }
* }
* }
* });
* // 'User: Alice, Age: 30'
*
* // With async formatters
* await variableAsync('User status: {userId}', {
* params: { userId: 1234 },
* format: {
* userId: async (id) => {
* const response = await fetch(`/api/users/${id}`);
* const user = await response.json();
* return `${user.name} (${user.status})`;
* }
* }
* });
* // 'User status: John Doe (active)'
*
* // Parallel processing of multiple variables
* await variableAsync('Weather: {city1}, {city2}, {city3}', {
* params: { city1: 'New York', city2: 'London', city3: 'Tokyo' },
* format: {
* city1: async (city) => await getWeather(city),
* city2: async (city) => await getWeather(city),
* city3: async (city) => await getWeather(city)
* }
* });
* // Processes all weather requests in parallel
* ```
*
* @see variable - Synchronous version for simpler use cases
*/
export function variableAsync(text_1) {
return __awaiter(this, arguments, void 0, function* (text, options = {}) {
if (Nullish.isNullishOrEmpty(text)) {
return '';
}
const params = Nullish.nullish(options.params, {});
const matches = Array.from(Nullish.nullish(text.match(/{\s*[\w._-]+\s*}/g), []));
if (Nullish.isNullishOrEmpty(matches)) {
return Promise.resolve(text);
}
const serialized = yield Promise.all(matches.map((match) => __awaiter(this, void 0, void 0, function* () {
var _a;
const key = match.replace(/[{}]/g, '').trim();
let value = Nullish.nullish(get(params, key), '');
if (!Nullish.isNullishOrEmpty((_a = options.format) === null || _a === void 0 ? void 0 : _a[key])) {
value = yield options.format[key](value);
}
return {
key,
match,
value: Nullish.nullish(value === null || value === void 0 ? void 0 : value.toString(), ''),
};
})));
serialized.forEach((item) => (text = text.replace(new RegExp(`\\{\\s*${item.key}\\s*\\}`, 'g'), item.value)));
return text;
});
}
/**
* Replaces variable placeholders in a string with corresponding values.
*
* This function takes a template string with variable placeholders in the format
* `{variableName}` and replaces them with values from the provided params object.
* It supports deep property access using dot notation and synchronous formatting.
*
* @param text - The template string containing variables in the format `{variableName}`
* @param options - Configuration options including parameters and formatters
* @param options.params - An object containing values to replace variables
* @param options.format - An object mapping variable names to synchronous formatter functions
* @returns The text with all variables replaced
*
* @example
* ```typescript
* // Basic usage
* variable('Hello, {name}!', {
* params: { name: 'John' }
* });
* // 'Hello, John!'
*
* // Deep property access
* variable('User: {user.profile.name}, Age: {user.profile.age}', {
* params: {
* user: {
* profile: {
* name: 'Alice',
* age: 30
* }
* }
* }
* });
* // 'User: Alice, Age: 30'
*
* // With formatters
* variable('Created: {date}', {
* params: { date: '2023-04-15' },
* format: {
* date: (value) => new Date(value).toLocaleDateString()
* }
* });
* // 'Created: 4/15/2023' (format depends on locale)
*
* // Multiple occurrences of the same variable
* variable('Welcome, {username}! Your username is {username}.', {
* params: { username: 'user123' }
* });
* // 'Welcome, user123! Your username is user123.'
*
* // Missing variables are replaced with empty string
* variable('Hello, {name}!', { params: {} });
* // 'Hello, !'
* ```
*
* @see variableAsync - Asynchronous version that supports async formatters
*/
export function variable(text, options = {}) {
if (Nullish.isNullishOrEmpty(text)) {
return '';
}
const params = Nullish.nullish(options.params, {});
const matches = Array.from(Nullish.nullish(text.match(/{\s*[\w._-]+\s*}/g), []));
if (Nullish.isNullishOrEmpty(matches)) {
return text;
}
matches.forEach((match) => {
var _a, _b;
const key = match.replace(/[{}]/g, '').trim();
let value = Nullish.nullish(get(params, key), '');
if (!Nullish.isNullishOrEmpty((_a = options.format) === null || _a === void 0 ? void 0 : _a[key])) {
value = options.format[key](value);
}
text = text.replace(new RegExp(`\\{\\s*${key}\\s*\\}`, 'g'), (_b = value === null || value === void 0 ? void 0 : value.toString()) !== null && _b !== void 0 ? _b : '');
});
return text;
}