@solid-primitives/utils
Advanced tools
+60
-0
@@ -127,1 +127,61 @@ import { onCleanup, createSignal, type Accessor, type AccessorArray, type EffectFunction, type NoInfer, type SignalOptions } from "solid-js"; | ||
| export declare function handleDiffArray<T>(current: readonly T[], prev: readonly T[], handleAdded: (item: T) => void, handleRemoved: (item: T) => void): void; | ||
| /** | ||
| * Parse a string as a single JSON value. | ||
| * | ||
| * ```ts | ||
| * const { data } = createSSE<{ status: string }>(url, { transform: json }); | ||
| * ``` | ||
| */ | ||
| export declare const json: <T>(raw: string) => T; | ||
| /** | ||
| * Parse a string as newline-delimited JSON (NDJSON / JSON Lines). | ||
| * | ||
| * Each non-empty line is parsed as a separate JSON value and returned as an array. | ||
| * | ||
| * ```ts | ||
| * const { data } = createSSE<TickEvent[]>(url, { transform: ndjson }); | ||
| * // data() === [{ id: 1, type: "tick" }, { id: 2, type: "tick" }] | ||
| * ``` | ||
| */ | ||
| export declare const ndjson: <T>(raw: string) => T[]; | ||
| /** | ||
| * Split a string into individual lines, returning a `string[]`. Empty lines are filtered out. | ||
| * | ||
| * ```ts | ||
| * const { data } = createSSE<string[]>(url, { transform: lines }); | ||
| * // data() === ["line one", "line two"] | ||
| * ``` | ||
| */ | ||
| export declare const lines: (raw: string) => string[]; | ||
| /** | ||
| * Parse a string as a number using `Number()` semantics. | ||
| * | ||
| * Note: `""` → `0`, non-numeric strings → `NaN`. | ||
| * | ||
| * ```ts | ||
| * const { data } = createSSE<number>(url, { transform: number }); | ||
| * // data() === 42 | ||
| * ``` | ||
| */ | ||
| export declare const number: (raw: string) => number; | ||
| /** | ||
| * Wrap any `(string) => T` transform in a `try/catch`. Returns `fallback` | ||
| * (default `undefined`) instead of throwing on malformed input. | ||
| * | ||
| * ```ts | ||
| * const { data } = createSSE<MyEvent>(url, { transform: safe(json) }); | ||
| * const { data } = createSSE<number>(url, { transform: safe(number, 0) }); | ||
| * ``` | ||
| */ | ||
| export declare function safe<T>(transform: (raw: string) => T): (raw: string) => T | undefined; | ||
| export declare function safe<T>(transform: (raw: string) => T, fallback: T): (raw: string) => T; | ||
| /** | ||
| * Compose two transforms into one: the output of `a` is passed as the input of `b`. | ||
| * | ||
| * ```ts | ||
| * const { data } = createSSE<RawEvent[]>(url, { | ||
| * transform: pipe(ndjson<RawEvent>, rows => rows.filter(r => r.type === "tick")), | ||
| * }); | ||
| * ``` | ||
| */ | ||
| export declare function pipe<A, B>(a: (raw: string) => A, b: (a: A) => B): (raw: string) => B; |
+65
-0
@@ -214,1 +214,66 @@ import { getOwner, onCleanup, createSignal, untrack, sharedConfig, onMount, DEV, equalFn, } from "solid-js"; | ||
| } | ||
| // ─── String transforms ──────────────────────────────────────────────────────── | ||
| /** | ||
| * Parse a string as a single JSON value. | ||
| * | ||
| * ```ts | ||
| * const { data } = createSSE<{ status: string }>(url, { transform: json }); | ||
| * ``` | ||
| */ | ||
| export const json = (raw) => JSON.parse(raw); | ||
| /** | ||
| * Parse a string as newline-delimited JSON (NDJSON / JSON Lines). | ||
| * | ||
| * Each non-empty line is parsed as a separate JSON value and returned as an array. | ||
| * | ||
| * ```ts | ||
| * const { data } = createSSE<TickEvent[]>(url, { transform: ndjson }); | ||
| * // data() === [{ id: 1, type: "tick" }, { id: 2, type: "tick" }] | ||
| * ``` | ||
| */ | ||
| export const ndjson = (raw) => raw | ||
| .split("\n") | ||
| .filter(line => line !== "") | ||
| .map(line => JSON.parse(line)); | ||
| /** | ||
| * Split a string into individual lines, returning a `string[]`. Empty lines are filtered out. | ||
| * | ||
| * ```ts | ||
| * const { data } = createSSE<string[]>(url, { transform: lines }); | ||
| * // data() === ["line one", "line two"] | ||
| * ``` | ||
| */ | ||
| export const lines = (raw) => raw.split("\n").filter(line => line !== ""); | ||
| /** | ||
| * Parse a string as a number using `Number()` semantics. | ||
| * | ||
| * Note: `""` → `0`, non-numeric strings → `NaN`. | ||
| * | ||
| * ```ts | ||
| * const { data } = createSSE<number>(url, { transform: number }); | ||
| * // data() === 42 | ||
| * ``` | ||
| */ | ||
| export const number = (raw) => Number(raw); | ||
| export function safe(transform, fallback) { | ||
| return (raw) => { | ||
| try { | ||
| return transform(raw); | ||
| } | ||
| catch { | ||
| return fallback; | ||
| } | ||
| }; | ||
| } | ||
| /** | ||
| * Compose two transforms into one: the output of `a` is passed as the input of `b`. | ||
| * | ||
| * ```ts | ||
| * const { data } = createSSE<RawEvent[]>(url, { | ||
| * transform: pipe(ndjson<RawEvent>, rows => rows.filter(r => r.type === "tick")), | ||
| * }); | ||
| * ``` | ||
| */ | ||
| export function pipe(a, b) { | ||
| return (raw) => b(a(raw)); | ||
| } |
+1
-1
| { | ||
| "name": "@solid-primitives/utils", | ||
| "version": "6.3.2", | ||
| "version": "6.4.0", | ||
| "description": "A bunch of reactive utility types and functions, for building primitives with Solid.js", | ||
@@ -5,0 +5,0 @@ "author": "Damian Tarnawski @thetarnav <gthetarnav@gmail.com>", |
+19
-0
@@ -99,4 +99,23 @@ <p> | ||
| ## String transforms | ||
| `(string) => T` transform functions for converting raw string data into typed values. Useful as the `transform` option for SSE, WebSocket, and similar streaming primitives. | ||
| ```ts | ||
| import { json, ndjson, safe } from "@solid-primitives/utils"; | ||
| const { data } = createSSE<Event>(url, { transform: json }); | ||
| const { data } = createSSE<Event[]>(url, { transform: ndjson }); | ||
| const { data } = createSSE<Event>(url, { transform: safe(json) }); | ||
| ``` | ||
| - **`json`** - Parse a string as a single JSON value | ||
| - **`ndjson`** - Parse newline-delimited JSON (NDJSON / JSON Lines) into an array | ||
| - **`lines`** - Split a string into a `string[]` by newline, filtering empty lines | ||
| - **`number`** - Parse a string as a number via `Number()` | ||
| - **`safe(transform, fallback?)`** - Wrap any transform in a `try/catch`; returns `fallback` instead of throwing | ||
| - **`pipe(a, b)`** - Compose two transforms into one | ||
| ## Changelog | ||
| See [CHANGELOG.md](./CHANGELOG.md) |
50577
10.54%1119
12.58%121
18.63%