### Install @mongez/reinforcements Source: https://github.com/hassanzohdy/reinforcements/blob/main/skills/overview.md Install the package using either Yarn or npm. ```sh yarn add @mongez/reinforcements # or npm i @mongez/reinforcements ``` -------------------------------- ### TypeScript path autocompletion with get Source: https://github.com/hassanzohdy/reinforcements/blob/main/skills/overview.md Demonstrates how the `get` function provides type-safe autocompletion for object paths. ```ts type User = { profile: { email: string } }; const u: User = { profile: { email: "x@y.z" } }; get(u, "profile.email"); // typed as string ``` -------------------------------- ### Debounce and Memoize Function Examples Source: https://github.com/hassanzohdy/reinforcements/blob/main/README.md Demonstrates the usage of debounce for rate-limiting function calls and memoize for caching function results with an optional time-to-live. ```ts const onSearch = debounce(query => fetch(query), 300); onSearch("ad"); onSearch("ada"); // 300ms later: fetches "ada" const slow = memoize((id: string) => fetchUser(id), { ttl: 60_000 }); ``` -------------------------------- ### Currying and Partial Application Examples Source: https://github.com/hassanzohdy/reinforcements/blob/main/llms-full.txt Demonstrates how to use `curry` to create functions that accept arguments one at a time, and `partial` and `partialRight` to create functions with pre-filled arguments. ```typescript const add = curry((a: number, b: number, c: number) => a + b + c); add(1)(2)(3); // 6 add(1, 2)(3); // 6 add(1, 2, 3); // 6 const greet = (greeting: string, name: string) => `${greeting}, ${name}`; const hello = partial(greet, "Hello"); hello("Ada"); // "Hello, Ada" const divide = (a: number, b: number) => a / b; const halve = partialRight(divide, 2); halve(10); // 5 ``` -------------------------------- ### Import and Use Reinforcements Utilities Source: https://github.com/hassanzohdy/reinforcements/blob/main/README.md Import various utilities from the library for tasks like object manipulation, string formatting, and asynchronous operations. This example demonstrates typed dot-notation, casing functions, slugify, truncate, number formatting, concurrency control, retries, templated strings, and randomness. ```ts import { clone, get, set, has, pick, omit, merge, slugify, truncate, toCamelCase, toSnakeCase, formatBytes, clamp, debounce, retry, pMap, Random, lazy, template, } from "@mongez/reinforcements"; // Typed dot-notation paths const user = { id: 1, profile: { email: "ada@example.com" } }; get(user, "profile.email"); // "ada@example.com" (typed!) has(user, "profile.email"); // true set(user, "profile.country", "EG"); // Casing — acronym-aware toSnakeCase("AIAgent"); // "ai_agent" toCamelCase("XMLHttpRequest"); // "xmlHttpRequest" // Slug & truncate slugify("Hello, café & croissant!"); // "hello-cafe-croissant" truncate("hello world there", 14, { byWord: true }); // "hello world..." // Numbers formatBytes(1_500_000); // "1.50 MB" clamp(150, 0, 100); // 100 // Async with bounded concurrency const docs = await pMap(urls, fetch, { concurrency: 5 }); // Resilient fetch const data = await retry(() => fetchUser(id), { attempts: 5, delay: 200, backoff: "exponential", }); // Templated strings with dot-notation vars template("Hi {user.name}, you have {count} items.", { user: { name: "Ada" }, count: 3, }); // "Hi Ada, you have 3 items." // Reproducible randomness for tests Random.seed(42); Random.uuid(); // Lazy / deferred references const config = lazy(() => loadConfig()); config.resolve(); // computes once, cached thereafter ``` -------------------------------- ### String Padding Utilities Source: https://github.com/hassanzohdy/reinforcements/blob/main/skills/strings.md Pad strings to a specific length from the start, end, or both sides using `padStart`, `padEnd`, and `pad`. A custom character can be specified. ```typescript pad("hi", 6); // " hi " pad("hi", 7, "*"); // "**hi***" padStart("7", 3, "0"); // "007" padEnd("7", 3, "0"); // "700" ``` -------------------------------- ### String Padding Utilities Source: https://github.com/hassanzohdy/reinforcements/blob/main/llms-full.txt Provides functions to pad strings to a specified length from the start, end, or both sides, using a specified character. ```typescript pad(str, length, char?): string // pad both sides; extra char goes to end ``` ```typescript padStart(str, length, char?): string // typed wrapper around String#padStart ``` ```typescript padEnd(str, length, char?): string // typed wrapper around String#padEnd ``` ```typescript pad("hi", 6); // " hi " ``` ```typescript pad("hi", 7, "*"); // "**hi***" ``` ```typescript padStart("7", 3, "0"); // "007" ``` ```typescript padEnd("7", 3, "0"); // "700" ``` -------------------------------- ### Object Manipulation with Get, Set, Pick, and Merge Source: https://github.com/hassanzohdy/reinforcements/blob/main/README.md Utilize `get`, `set`, `pick`, and `merge` for robust object manipulation. `get` safely retrieves values using dot-notation, `set` updates or creates properties, `pick` selects specific properties, and `merge` performs deep merging with array handling options. ```typescript import { get, set, pick, merge } from "@mongez/reinforcements"; const settings = merge({ theme: "dark" }, { features: { beta: true } }); const slim = pick(settings, ["theme"]); const value = get(settings, "features.beta", false); set(settings, "features.experimental", true); ``` -------------------------------- ### Path access — get / set / has / unset Source: https://github.com/hassanzohdy/reinforcements/blob/main/skills/objects.md Utilities for reading and writing nested object properties using dot-notation paths. ```APIDOC ## get ### Description Reads a value from an object by a specified dot-notation path. Handles falsy values correctly and allows for a default value. ### Signature ```ts get>(obj: T, path: P, default?: T): PathValue get(obj: any, path: string, default?: T): T ``` ### Example ```ts get({ user: { email: "ada@x.com" } }, "user.email"); // "ada@x.com" get({ user: {} }, "user.email", "n/a"); // "n/a" get(arr, "0.name"); // numeric segments index arrays ``` ## set ### Description Mutates an object by setting a value at a specified dot-notation path. Automatically creates arrays if the next segment is a numeric index. ### Signature ```ts set(obj: T, path: string, value: unknown): T ``` ### Example ```ts set({}, "users.0.name", "Ada"); // { users: [{ name: "Ada" }] } set(obj, "a.b.c", 1); // creates a.b.c chain ``` ## has ### Description Checks if a path exists within an object, returning `true` even if the value at the path is `undefined`. Useful for distinguishing between a missing path and a present `undefined` value. ### Signature ```ts has(obj: any, path: string): boolean ``` ### Example ```ts has({ a: { b: 1 } }, "a.b"); // true has({ a: { b: undefined } }, "a.b"); // true has({ a: {} }, "a.b"); // false ``` ## unset ### Description Mutates an object by removing properties at the specified dot-notation paths. Returns the same object reference. ### Signature ```ts unset(obj: T, paths: readonly string[]): T ``` ### Example ```ts unset({ a: 1, b: 2 }, ["a"]); // { b: 2 } unset({ a: { b: 1, c: 2 } }, ["a.b"]); // { a: { c: 2 } } ``` ``` -------------------------------- ### Array Chunking and Range Generation Source: https://github.com/hassanzohdy/reinforcements/blob/main/llms-full.txt Examples of using the `chunk` function to split an array or string into smaller arrays of a specified size, and the `range` function to generate an array of numbers within a given range. ```typescript chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]] chunk("abcdef", 2); // [["a","b"], ["c","d"], ["e","f"]] range(1, 5); // [1, 2, 3, 4, 5] ``` -------------------------------- ### Memoize Function with TTL and Custom Resolver Source: https://github.com/hassanzohdy/reinforcements/blob/main/llms-full.txt The `memoize` utility caches the results of a function. This example demonstrates setting a Time-To-Live (TTL) for cache entries and providing a custom `resolver` function to generate cache keys based on specific arguments. ```typescript memoize(fn: T, options?: { resolver?: (...args: Parameters) => string; ttl?: number; }): Memoized type Memoized = T & { clear(): void; forget(key: string): void }; ``` ```typescript const lookup = memoize((id: string) => db.users.find(id), { ttl: 60_000 }); lookup("u1"); // hits DB lookup("u1"); // cached lookup.forget("u1"); // surgical invalidation lookup.clear(); // nuke everything ``` ```typescript const cached = memoize( (a: User, b: User) => similarity(a, b), { resolver: (a, b) => `${a.id}-${b.id}` }, ); ``` -------------------------------- ### Array Statistical Calculations Source: https://github.com/hassanzohdy/reinforcements/blob/main/llms-full.txt Provides examples for statistical functions like `sum`, `average` (aliased as `avg`), `median`, `min`, and `max`. These functions can operate on arrays of numbers or arrays of objects using a specified key. ```typescript sum([1, 2, 3]); // 6 sum(orders, "total.price"); // sum of total.price across orders average([2, 4, 6]); // 4 median([1, 2, 3, 4]); // 2.5 min(users, "age"); // smallest age max(users, "age"); // largest age ``` -------------------------------- ### Typed Dot-Notation Reads and Writes Source: https://github.com/hassanzohdy/reinforcements/blob/main/skills/recipes.md Use `get`, `set`, and `has` for type-safe access to nested object properties. Provides default values for `get` if the property is not found. ```typescript import { get, set, has } from "@mongez/reinforcements"; type User = { id: number; profile: { email: string } }; const u: User = { id: 1, profile: { email: "ada@x.com" } }; get(u, "profile.email"); // typed string get(u, "profile.email", "n/a"); // typed string has(u, "profile.email"); // true set(u, "profile.country", "EG"); ``` -------------------------------- ### Import all utilities from @mongez/reinforcements Source: https://github.com/hassanzohdy/reinforcements/blob/main/skills/overview.md Import all available functions and types directly from the package root. ```ts import { get, set, has, pick, omit, merge, clone, areEqual, toCamelCase, slugify, truncate, template, clamp, formatBytes, percentage, debounce, throttle, memoize, pipe, sleep, retry, pMap, defer, Random, lazy, type Path, type PathValue, type DeepPartial, } from "@mongez/reinforcements"; ``` -------------------------------- ### Typed Dot-Notation Read with `get` Source: https://context7.com/hassanzohdy/reinforcements/llms.txt Use `get` to safely read nested object properties by dot-notation path. It supports typed access, default values, and correctly handles falsy values. ```ts import { get } from "@mongez/reinforcements"; type User = { id: number; profile: { email: string; addresses: { city: string }[] } }; const user: User = { id: 1, profile: { email: "ada@example.com", addresses: [{ city: "Cairo" }] } }; get(user, "profile.email"); // "ada@example.com" — typed as string get(user, "profile.addresses.0.city"); // "Cairo" — typed as string get(user, "profile.email", "n/a"); // "ada@example.com" (default unused) get({ score: 0 }, "score", 99); // 0 (falsy value passes through, no default substitution) get({}, "missing.path", "fallback"); // "fallback" ``` -------------------------------- ### Get nested object property by path Source: https://github.com/hassanzohdy/reinforcements/blob/main/llms-full.txt Use `get` to read properties using dot-notation paths. Falsy values like `0`, `""`, or `false` are returned correctly without substituting defaults. ```typescript get({ user: { email: "ada@x.com" } }, "user.email"); // "ada@x.com" get({ user: {} }, "user.email", "n/a"); // "n/a" get(arr, "0.name"); // numeric segments index arrays ``` -------------------------------- ### Currying and Partial Application Source: https://github.com/hassanzohdy/reinforcements/blob/main/skills/functions.md Transform functions for easier partial application and currying with `curry`, `partial`, and `partialRight`. These utilities help in creating more flexible and reusable function compositions. ```APIDOC ## Currying & partial application ### Description Utilities for transforming functions to support currying and partial application, enabling more flexible function composition. ### Signature ```ts curry(fn: (...args) => R): any partial(fn: T, ...preset): (...rest) => ReturnType partialRight(fn: T, ...preset): (...rest) => ReturnType ``` ### Example ```ts const add = curry((a: number, b: number, c: number) => a + b + c); add(1)(2)(3); // 6 add(1, 2)(3); // 6 add(1, 2, 3); // 6 const greet = (greeting: string, name: string) => `${greeting}, ${name}`; const hello = partial(greet, "Hello"); hello("Ada"); // "Hello, Ada" const divide = (a: number, b: number) => a / b; const halve = partialRight(divide, 2); halve(10); // 5 ``` ``` -------------------------------- ### startsWithArabic Source: https://github.com/hassanzohdy/reinforcements/blob/main/skills/strings.md Checks if a string starts with an Arabic character. ```APIDOC ## startsWithArabic ### Description Checks if a string begins with an Arabic character. Optionally trims whitespace before checking. ### Parameters #### Parameters - **str** (string) - Required - The input string. - **trimmed** (boolean) - Optional - Whether to trim whitespace from the beginning of the string before checking. Defaults to true. ### Returns (boolean) - True if the string starts with an Arabic character, false otherwise. ### Examples ```ts startsWithArabic("مرحبا"); // true startsWithArabic(" مرحبا"); // true (trimmed) ``` ``` -------------------------------- ### Import Async Utilities Source: https://github.com/hassanzohdy/reinforcements/blob/main/skills/async.md Import necessary asynchronous control flow functions from the @mongez/reinforcements library. ```typescript import { sleep, retry, timeout, pAll, pAllSettled, pMap, pSeries, pFilter, defer, debounceAsync, } from "@mongez/reinforcements"; ``` -------------------------------- ### Typed Dot-Notation Paths with get, set, has Source: https://github.com/hassanzohdy/reinforcements/blob/main/README.md Utilize `get`, `set`, and `has` for type-safe access and modification of nested object properties. These functions provide autocompletion for valid paths and infer the exact type of the resolved value. `has` can distinguish between a key being absent and its value being `undefined`. ```ts import { get, set, has } from "@mongez/reinforcements"; type User = { id: number; profile: { email: string; addresses: { city: string }[] } }; const user: User = { id: 1, profile: { email: "ada@example.com", addresses: [{ city: "Cairo" }] }, }; const email = get(user, "profile.email"); // typed as string const city = get(user, "profile.addresses.0.city"); // typed as string const missing = get(user, "profile.email", "n/a"); // typed string, falls back has(user, "profile.email"); // true — distinguishes "key absent" from "value undefined" set(user, "profile.country", "EG"); ``` -------------------------------- ### Testing with Vitest Source: https://github.com/hassanzohdy/reinforcements/blob/main/MIGRATION.md Provides commands for running tests using Vitest, including single run, watch mode, coverage, and UI. ```sh yarn test ``` ```sh yarn test:watch ``` ```sh yarn test:coverage ``` ```sh yarn test:ui ``` -------------------------------- ### Running Tests with Yarn Source: https://github.com/hassanzohdy/reinforcements/blob/main/README.md Provides commands for running tests using Yarn, including single runs, watch mode, coverage reports, and an interactive UI. ```sh yarn test # single run yarn test:watch # watch mode yarn test:coverage # v8 coverage yarn test:ui # interactive UI ``` -------------------------------- ### mask Source: https://github.com/hassanzohdy/reinforcements/blob/main/skills/strings.md Masks a string with a specified character, revealing a portion from the start and end. ```APIDOC ## mask ### Description Masks a string, showing a specified number of characters from the start and end. ### Parameters #### Parameters - **str** (string) - Required - The input string to mask. - **options** (object) - Optional - Configuration options. - **start** (number) - Optional - Number of visible characters from the start. Defaults to 0. - **end** (number) - Optional - Number of visible characters from the end. Defaults to 0. - **char** (string) - Optional - The character to use for masking. Defaults to "*". ### Returns (string) - The masked string. ### Examples ```ts mask("4242424242424242", { start: 0, end: 4 }); // "************4242" mask("hassan@gmail.com", { start: 2, end: 4 }); // "ha**********.com" ``` ``` -------------------------------- ### Arabic String Detection Source: https://context7.com/hassanzohdy/reinforcements/llms.txt Check if a string starts with or contains Arabic characters. The `startsWithArabic` function trims whitespace by default. ```typescript import { startsWithArabic, containsArabic, ARABIC_REGEX } from "@mongez/reinforcements"; startsWithArabic("مرحبا"); // true startsWithArabic(" مرحبا"); // true (trimmed by default) containsArabic("hello مرحبا"); // true ARABIC_REGEX.test("abc"); // false ``` -------------------------------- ### String Utilities - URL Slugs and Truncation Source: https://github.com/hassanzohdy/reinforcements/blob/main/llms-full.txt Utilities for creating URL-friendly slugs from strings and truncating strings with options. ```APIDOC ## URL slugs & truncation ### `slugify` #### Description Converts a string into a URL-friendly slug. #### Signature ```ts slugify(str, options?: { separator?: string; // default "-" lower?: boolean; // default true strict?: boolean; // default true — strip non-alphanumeric per token }): string ``` #### Example ```ts slugify("Hello, World!"); // "hello-world" slugify("café crème"); // "cafe-creme" slugify("Hello World", { separator: "_" }); // "hello_world" ``` ### `truncate` #### Description Truncates a string to a specified length, with options for suffix, word boundary cutting, and position. #### Signature ```ts truncate(str, length, options?: { suffix?: string; // default "..." byWord?: boolean; // default false — cut at word boundary position?: "end" | "middle"; // default "end" }): string ``` #### Example ```ts truncate("hello world", 8); // "hello..." truncate("hello world there", 14, { byWord: true }); // "hello world..." truncate("abcdefghij", 7, { position: "middle" }); // "ab...ij" ``` ``` -------------------------------- ### Check for Arabic Characters Source: https://github.com/hassanzohdy/reinforcements/blob/main/skills/strings.md Determines if a string starts with or contains Arabic characters. The `startsWithArabic` function can optionally trim whitespace before checking. ```typescript startsWithArabic("مرحبا"); // true startsWithArabic(" مرحبا"); // true (trimmed) containsArabic("hello مرحبا"); // true ``` -------------------------------- ### Composition Utilities Source: https://github.com/hassanzohdy/reinforcements/blob/main/skills/functions.md Combine multiple functions into a single, more complex function using `pipe`, `compose`, and `tap`. These utilities are essential for building elegant and readable functional pipelines. ```APIDOC #### `pipe` / `compose` ##### Description `pipe` creates a function that accepts a value and applies functions from left to right. `compose` creates a function that accepts a value and applies functions from right to left. ##### Signature ```ts pipe(value: A): A pipe(value: A, fn1: (a: A) => B): B pipe(value: A, fn1: (a: A) => B, fn2: (b: B) => C): C // …up to 4 typed steps; variadic fallback after that compose(fn2: (b: B) => C, fn1: (a: A) => B): (a: A) => C // right-to-left ``` ##### Example ```ts pipe(2, n => n + 1, n => n * 10); // 30 const shout = compose( (s: string) => s + "!", (s: string) => s.toUpperCase(), ); shout("hi"); // "HI!" ``` #### `tap` / `tap.with` ##### Description `tap` is a utility for performing side effects on a value within a pipeline without altering the value itself. `tap.with` returns a pipeline-friendly identity function that also performs a side effect. ##### Signature ```ts tap(value: T, sideEffect: (value: T) => void): T tap.with(sideEffect: (value: T) => void): (value: T) => T ``` ##### Example ```ts pipe(value, trim, tap.with(console.log), toSnakeCase); ``` ``` -------------------------------- ### Currying and Partial Application Source: https://github.com/hassanzohdy/reinforcements/blob/main/llms-full.txt Functions for currying and partial application to create more specialized functions from general ones. ```APIDOC ## Currying & partial application ```ts curry(fn: (...args) => R): any partial(fn: T, ...preset): (...rest) => ReturnType partialRight(fn: T, ...preset): (...rest) => ReturnType ``` ### Example Usage ```ts const add = curry((a: number, b: number, c: number) => a + b + c); add(1)(2)(3); // 6 add(1, 2)(3); // 6 add(1, 2, 3); // 6 const greet = (greeting: string, name: string) => `${greeting}, ${name}`; const hello = partial(greet, "Hello"); hello("Ada"); // "Hello, Ada" const divide = (a: number, b: number) => a / b; const halve = partialRight(divide, 2); halve(10); // 5 ``` ``` -------------------------------- ### HTML & Masking: mask Source: https://github.com/hassanzohdy/reinforcements/blob/main/llms-full.txt Masks a portion of a string with a specified character. You can control the number of visible characters from the start and end, and the masking character itself. ```APIDOC ## `mask` ### Description Masks a string with a specified character, allowing control over visible characters from the start and end. ### Signature ```ts mask(str: string, options?: { start?: number; // visible chars from start, default 0 end?: number; // visible chars from end, default 0 char?: string; // mask char, default "*" }): string ``` ### Examples ```ts mask("4242424242424242", { start: 0, end: 4 }); // "************4242" mask("hassan@gmail.com", { start: 2, end: 4 }); // "ha**********.com" ``` ``` -------------------------------- ### PII Masking Source: https://context7.com/hassanzohdy/reinforcements/llms.txt Masks the central part of a string, retaining a specified number of characters at the start and end. A custom masking character can be provided. ```typescript import { mask } from "@mongez/reinforcements"; mask("4242424242424242", { start: 0, end: 4 }); // "************4242" mask("hassan@gmail.com", { start: 2, end: 4 }); // "ha**********.com" mask("+201234567890", { start: 4, end: 2, char: "•" }); // "+201•••••••90" ``` -------------------------------- ### Lazy Initialization Source: https://github.com/hassanzohdy/reinforcements/blob/main/llms-full.txt Memoize deferred values using `lazy` for efficient computation and managing circular dependencies. ```APIDOC ## Lazy Initialization ### Description Memoize deferred values using `lazy` for efficient computation and managing circular dependencies. The producer is not invoked until the first `resolve()` call, and the result is cached. ### Import ```ts import { lazy, isLazy, type Lazy, type LazyAsync } from "@mongez/reinforcements"; ``` ### `lazy(producer)` ```ts lazy(producer: () => T): Lazy type Lazy = { resolve(): T; // compute (once) and return the cached value reset(): void; // drop the cache; next resolve() recomputes isResolved(): boolean; // has resolve() been called? peek(): T | undefined; // cached value without forcing computation }; ``` ### Example ```ts const config = lazy(() => loadHeavyConfig()); config.resolve(); // computes config.resolve(); // cached, no recomputation config.reset(); // forget cached value config.resolve(); // recomputes config.peek(); // returns cached value or undefined config.isResolved(); // true / false ``` ### Circular Imports `lazy()` defers reference resolution to call time, effectively breaking circular dependencies between modules. ```ts // In a module that creates a circular dep: const service = lazy(() => Service); // Service is undefined right now — fine export function handler() { return service.resolve().run(); // Service is guaranteed to exist by this point } ``` ``` -------------------------------- ### URL Summaries with Slugification and Truncation Source: https://github.com/hassanzohdy/reinforcements/blob/main/skills/recipes.md Creates SEO-friendly URL summaries by truncating text and converting it to a slug using `pipe`, `truncate`, and `slugify`. Ensures summaries are concise and URL-safe. ```typescript import { slugify, truncate, pipe } from "@mongez/reinforcements"; const urlSummary = (title: string) => pipe(title, t => truncate(t, 60, { byWord: true }), t => slugify(t)); urlSummary("How to break circular ES module imports without crying!"); // "how-to-break-circular-es-module-imports-without" ``` -------------------------------- ### Get File Extension Source: https://github.com/hassanzohdy/reinforcements/blob/main/skills/strings.md Extracts the file extension from a filename. Returns an empty string if no extension is present (i.e., no dot or dot is the first character). ```typescript extension("foo.txt"); // "txt" extension("archive.tar.gz"); // "gz" extension("README"); // "" ``` -------------------------------- ### Merge Behavior Change Source: https://github.com/hassanzohdy/reinforcements/blob/main/MIGRATION.md Demonstrates the change in `merge` behavior for null inputs and configurable array merging strategies. ```diff - merge(null, { a: 1 }); // returned null + merge(null, { a: 1 }); // returns { a: 1 } ``` ```ts ```ts merge({ list: [1, 2] }, { list: [3, 4] }); // { list: [3, 4] } replace (default) merge({ list: [1, 2] }, { list: [3, 4] }, { arrays: "concat" }); // { list: [1, 2, 3, 4] } merge({ list: [1, 2] }, { list: [2, 3] }, { arrays: "union" }); // { list: [1, 2, 3] } ``` ``` -------------------------------- ### Get object property by path Source: https://github.com/hassanzohdy/reinforcements/blob/main/skills/objects.md Read nested object properties using dot-notation. Handles falsy values correctly and supports array indexing. ```typescript get>(obj: T, path: P, default?): PathValue get(obj: any, path: string, default?: T): T ``` ```javascript get({ user: { email: "ada@x.com" } }, "user.email"); // "ada@x.com" get({ user: {} }, "user.email", "n/a"); // "n/a" get(arr, "0.name"); // numeric segments index arrays ``` -------------------------------- ### Key Selection with `pick` Source: https://context7.com/hassanzohdy/reinforcements/llms.txt Create a new object containing only the specified keys, dot-notation paths, or entries that match a predicate function. ```ts import { pick } from "@mongez/reinforcements"; pick({ a: 1, b: 2, c: 3 }, ["a", "c"]); // { a: 1, c: 3 } pick({ a: { b: 1, c: 2 } }, ["a.b"]); // { a: { b: 1 } } pick({ a: 1, b: 5, c: 3 }, v => v > 2); // { b: 5, c: 3 } ``` -------------------------------- ### Async Lazy Initialization Source: https://github.com/hassanzohdy/reinforcements/blob/main/llms-full.txt Memoize asynchronous deferred values using `lazy.async` for managing promises and circular dependencies. ```APIDOC ## Async Lazy Initialization ### Description Memoize asynchronous deferred values using `lazy.async` for managing promises and circular dependencies. The producer is not invoked until the first `resolve()` call, and the result (a Promise) is cached. ### `lazy.async(producer)` ```ts lazy.async(producer: () => Promise): LazyAsync type LazyAsync = { resolve(): Promise; reset(): void; isResolved(): boolean; peek(): Promise | undefined; }; ``` ### Example ```ts const user = lazy.async(() => fetch("/api/me").then(r => r.json())); await user.resolve(); // fetches await user.resolve(); // returns the same cached promise — no refetch user.reset(); await user.resolve(); // refetches ``` ``` -------------------------------- ### Extract File Extension Source: https://github.com/hassanzohdy/reinforcements/blob/main/llms-full.txt Get the file extension using the `extension` function. It returns the part of the filename after the last dot, or an empty string if no dot is present. ```typescript extension(filename: string): string ``` ```typescript extension("foo.txt"); // "txt" extension("archive.tar.gz"); // "gz" extension("README"); // "" ``` -------------------------------- ### Mask Sensitive String Portions Source: https://github.com/hassanzohdy/reinforcements/blob/main/llms-full.txt Use the `mask` function to obscure parts of a string with a specified character. Control the number of visible characters from the start and end. ```typescript mask(str, options?: { start?: number; // visible chars from start, default 0 end?: number; // visible chars from end, default 0 char?: string; // mask char, default "*" }): string ``` ```typescript mask("4242424242424242", { start: 0, end: 4 }); // "************4242" mask("hassan@gmail.com", { start: 2, end: 4 }); // "ha**********.com" ``` -------------------------------- ### Create Data Processing Pipelines with `pipe` and `tap` Source: https://github.com/hassanzohdy/reinforcements/blob/main/README.md Construct data processing pipelines using `pipe` for sequential transformation and `tap` for adding observability (e.g., logging) without altering the data flow. `tap.with` allows passing context to the tap function. ```typescript import { pipe, tap } from "@mongez/reinforcements"; const result = pipe( rawInput, trim, tap.with(s => console.log("after trim:", s)), // side-effect, passes value through toSnakeCase, s => s + "_v3", ); ``` -------------------------------- ### Path and PathValue Type Usage Source: https://github.com/hassanzohdy/reinforcements/blob/main/README.md Illustrates how to use the Path and PathValue utility types to derive string literal types representing object paths and the types of values at those paths. ```ts type User = { id: number; profile: { email: string } }; type UserPath = Path; // "id" | "profile" | "profile.email" type EmailType = PathValue; // string ``` -------------------------------- ### Detect Arabic Characters in Strings Source: https://github.com/hassanzohdy/reinforcements/blob/main/llms-full.txt Check if a string starts with Arabic characters using `startsWithArabic` (optionally trimmed) or contains Arabic characters with `containsArabic`. Includes `ARABIC_REGEX`. ```typescript startsWithArabic(str: string, trimmed?: boolean): boolean // default trimmed = true containsArabic(str: string): boolean ARABIC_REGEX: RegExp // /[؀-ۿ]/ ARABIC_PATTERN: RegExp // @deprecated — same as ARABIC_REGEX ``` ```typescript startsWithArabic("مرحبا"); // true startsWithArabic(" مرحبا"); // true (trimmed) containsArabic("hello مرحبا"); // true ``` -------------------------------- ### pick — key selection Source: https://context7.com/hassanzohdy/reinforcements/llms.txt Creates a new object containing only the specified keys, dot-notation paths, or entries that match a given predicate function. ```APIDOC ## pick — key selection ### Description Returns a new object with only the requested keys, dot-notation paths, or entries matching a predicate. ### Usage ```ts import { pick } from "@mongez/reinforcements"; pick({ a: 1, b: 2, c: 3 }, ["a", "c"]); // { a: 1, c: 3 } pick({ a: { b: 1, c: 2 } }, ["a.b"]); // { a: { b: 1 } } pick({ a: 1, b: 5, c: 3 }, v => v > 2); // { b: 5, c: 3 } ``` ``` -------------------------------- ### Currying and Partial Application Source: https://github.com/hassanzohdy/reinforcements/blob/main/skills/functions.md Utilities for creating functions that accept arguments one at a time (`curry`) or pre-filling some arguments (`partial`, `partialRight`). Simplifies function usage and enables functional composition. ```typescript const add = curry((a: number, b: number, c: number) => a + b + c); add(1)(2)(3); // 6 add(1, 2)(3); // 6 add(1, 2, 3); // 6 ``` ```typescript const greet = (greeting: string, name: string) => `${greeting}, ${name}`; const hello = partial(greet, "Hello"); hello("Ada"); // "Hello, Ada" ``` ```typescript const divide = (a: number, b: number) => a / b; const halve = partialRight(divide, 2); halve(10); // 5 ``` -------------------------------- ### Object Path Access - get Source: https://github.com/hassanzohdy/reinforcements/blob/main/llms-full.txt Reads a value from an object using a typed dot-notation path. Handles falsy values correctly and supports numeric segments for array indexing. ```APIDOC ## get ### Description Reads a value from an object using a typed dot-notation path. Falsy values pass through correctly (no spurious default-substitution on `0` / `""` / `false`). Supports numeric segments for array indexing. ### Method Signature ```ts get>(obj: T, path: P, default?): PathValue get(obj: any, path: string, default?: T): T ``` ### Parameters - **obj** (any) - The object to read from. - **path** (string | Path) - The dot-notation path to the desired value. - **default** (any, optional) - The default value to return if the path is not found. ### Examples ```ts get({ user: { email: "ada@x.com" } }, "user.email"); // "ada@x.com" get({ user: {} }, "user.email", "n/a"); // "n/a" get(arr, "0.name"); // numeric segments index arrays ``` ``` -------------------------------- ### Mask PII for logs / display Source: https://github.com/hassanzohdy/reinforcements/blob/main/README.md The `mask` function allows you to mask sensitive information in strings, such as credit card numbers or email addresses, by specifying start and end positions and an optional masking character. ```APIDOC ## mask ### Description Masks sensitive information in a string by replacing characters within a specified range. ### Parameters - **text** (string) - The input string to mask. - **options** (object) - An object containing masking options: - **start** (number) - The starting index for masking (inclusive). - **end** (number) - The ending index for masking (inclusive). - **char** (string, optional) - The character to use for masking. Defaults to '*'. ### Example ```ts import { mask } from "@mongez/reinforcements"; mask("4242424242424242", { start: 0, end: 4 }); // Returns "************4242" mask("hassanzohdy@gmail.com", { start: 2, end: 10 }); // Returns "ha*********gmail.com" mask("+201234567890", { start: 4, end: 2, char: "•" }); // Returns "+201•••••••90" ``` ``` -------------------------------- ### Tiny FP Primitives Source: https://github.com/hassanzohdy/reinforcements/blob/main/skills/functions.md A set of small, fundamental functional programming utilities including `noop`, `identity`, `constant`, and `negate` for common functional patterns. ```APIDOC ## Tiny FP primitives ### Description Essential small functions for functional programming. ### Signature ```ts noop(): void // does nothing identity(value: T): T // returns argument constant(value: T): () => T // returns a function that always yields value negate(predicate: T): (...args) => boolean // inverts a predicate ``` ### Example ```ts items.filter(identity); // drop falsy values events.on("data", noop); // explicitly ignore const always42 = constant(42); const isOdd = negate((n: number) => n % 2 === 0); ``` ``` -------------------------------- ### Currying and Partial Application Source: https://context7.com/hassanzohdy/reinforcements/llms.txt Utilize `curry` to create functions that accept arguments one at a time. `partial` and `partialRight` create new functions with some arguments pre-filled. ```typescript import { curry, partial, partialRight } from "@mongez/reinforcements"; const add = curry((a: number, b: number, c: number) => a + b + c); add(1)(2)(3); // 6 add(1, 2)(3); // 6 const greet = (greeting: string, name: string) => `${greeting}, ${name}!`; const hello = partial(greet, "Hello"); hello("Ada"); // "Hello, Ada!" hello("Bob"); // "Hello, Bob!" const divide = (a: number, b: number) => a / b; const halve = partialRight(divide, 2); halve(10); // 5 ``` -------------------------------- ### Import Reinforcements Function Utilities Source: https://github.com/hassanzohdy/reinforcements/blob/main/llms-full.txt Imports various function utilities from the `@mongez/reinforcements` package, including rate-limiting, memoization, composition, currying, and basic FP primitives. ```typescript import { debounce, throttle, memoize, once, after, before, pipe, compose, tap, curry, partial, partialRight, noop, identity, constant, negate, escapeRegex, } from "@mongez/reinforcements"; ``` -------------------------------- ### String Utilities - Words and Casing Source: https://github.com/hassanzohdy/reinforcements/blob/main/llms-full.txt Functions for tokenizing strings into words and converting strings between various casing formats. ```APIDOC ## `words` ### Description Tokenizes a string into an array of words, correctly handling acronyms. ### Signature ```ts words(input: string): string[] ``` ### Example ```ts words("XMLHttpRequest"); // ["XML", "Http", "Request"] words("AIAgent"); // ["AI", "Agent"] words("hello-world"); // ["hello", "world"] ``` ## Casing Family All casing functions share a single tokenizer that handles acronyms correctly. | Function | Signature | Example | |---|---|---| | `toCamelCase` | `(str) => string` | `toCamelCase("XMLHttpRequest")` → `"xmlHttpRequest"` | | `toStudlyCase` | `(str) => string` | `toStudlyCase("hello-world")` → `"HelloWorld"` | | `toPascalCase` | `(str) => string` | Alias of `toStudlyCase` | | `toSnakeCase` | `(str, separator?, lowerAll?) => string` | `toSnakeCase("AIAgent")` → `"ai_agent"` | | `toKebabCase` | `(str, lowerAll?) => string` | `toKebabCase("getUserID")` → `"get-user-id"` | | `toConstantCase` | `(str) => string` | `toConstantCase("apiBaseUrl")` → `"API_BASE_URL"` | | `toDotCase` | `(str, lowerAll?) => string` | `toDotCase("helloWorld")` → `"hello.world"` | | `toPathCase` | `(str, lowerAll?) => string` | `toPathCase("helloWorld")` → `"hello/world"` | | `toTitleCase` | `(str, options?: { stopWords? }) => string` | `toTitleCase("the lord of rings")` → `"The Lord of Rings"` | ``` -------------------------------- ### get — typed dot-notation read Source: https://context7.com/hassanzohdy/reinforcements/llms.txt Reads a value from a nested object using dot-notation path. Handles falsy values correctly and supports numeric segments for array indexing. An optional default value can be provided. ```APIDOC ## get — typed dot-notation read ### Description Reads a value from a nested object by dot-notation path. Falsy values (`0`, `""`, `false`) pass through correctly and do not trigger the default. Numeric segments index into arrays automatically. ### Usage ```ts import { get } from "@mongez/reinforcements"; type User = { id: number; profile: { email: string; addresses: { city: string }[] } }; const user: User = { id: 1, profile: { email: "ada@example.com", addresses: [{ city: "Cairo" }] } }; get(user, "profile.email"); // "ada@example.com" — typed as string get(user, "profile.addresses.0.city"); // "Cairo" — typed as string get(user, "profile.email", "n/a"); // "ada@example.com" (default unused) get({ score: 0 }, "score", 99); // 0 (falsy value passes through, no default substitution) get({}, "missing.path", "fallback"); // "fallback" ``` ``` -------------------------------- ### Importing Reinforcements Types Source: https://github.com/hassanzohdy/reinforcements/blob/main/skills/types.md Import various utility types from the @mongez/reinforcements library. These types are zero-runtime cost and only available in TypeScript. ```typescript import type { Path, PathValue, DeepPartial, DeepRequired, DeepReadonly, DeepMutable, Prettify, UnionToIntersection, Branded, Nullable, Maybe, Awaitable, NonEmptyArray, GenericObject, AlphaNumeric, Primitive, } from "@mongez/reinforcements"; ``` -------------------------------- ### String Utilities - Padding Source: https://github.com/hassanzohdy/reinforcements/blob/main/llms-full.txt Functions for adding characters to the beginning or end of a string to reach a specified length. ```APIDOC ## Padding ### `pad` #### Description Pads a string on both sides to reach a specified length. If the padding character count is odd, the extra character is added to the end. #### Signature ```ts pad(str, length, char?): string ``` ### `padStart` #### Description Pads the start of a string with a specified character until it reaches a given length. This is a typed wrapper around `String#padStart`. #### Signature ```ts padStart(str, length, char?): string ``` ### `padEnd` #### Description Pads the end of a string with a specified character until it reaches a given length. This is a typed wrapper around `String#padEnd`. #### Signature ```ts padEnd(str, length, char?): string ``` ### Example ```ts pad("hi", 6); // " hi " pad("hi", 7, "*"); // "**hi***" padStart("7", 3, "0"); // "007" padEnd("7", 3, "0"); // "700" ``` ```