congeal
v0.1.0
Published
Best-effort parse of an incomplete/streaming JSON prefix — closes open strings, arrays, and objects so you get a usable value at every step. Never throws on truncation.
Maintainers
Readme
congeal
Best-effort parse of an incomplete/streaming JSON prefix — closes open strings, arrays, and objects so you get a usable value at every step. Never throws on truncation.
The problem
When streaming JSON from APIs or LLMs, you receive partial chunks truncated mid-string, mid-object, or mid-array. Standard JSON.parse() throws on incomplete input, forcing you to buffer and wait. congeal solves this by intelligently closing open structures to produce usable values at every step, enabling progressive parsing without buffering.
Install
npm install congeal
# or
pnpm add congeal
# or
yarn add congealUse
import congeal, { isComplete } from "congeal";
// Parse incomplete JSON without throwing
const partial = '{"name":"Alice","age":30,"cit';
const result = congeal(partial); // { name: 'Alice', age: 30 }
isComplete(partial); // false// LLM tool-call streaming scenario
const chunks = [
'{"function_name":"get_w',
'{"function_name":"get_weather","param',
'{"function_name":"get_weather","parameters":{"location":"NYC"}}',
];
chunks.forEach(chunk => {
const parsed = congeal(chunk);
console.log(parsed);
// Progressive results: { function_name: 'get_w' }, { function_name: 'get_weather' }, ...
});// Control partial string behavior
congeal('{"msg":"Hello', { partialStrings: true }); // { msg: 'Hello' }
congeal('{"msg":"Hello', { partialStrings: false }); // {}API
congeal(input, options?)
Best-effort parse of an incomplete/streaming JSON prefix.
Parameters:
input(string): The JSON prefix to parseoptions?(CongealOptions): Optional configurationpartialStrings?(boolean): Include partial string content (default: true)
Returns: T | undefined — The parsed value, or undefined if nothing parseable
Behavior: Closes open strings, arrays, and objects to produce valid JSON. Drops incomplete tokens (keywords, numbers, dangling separators). Never throws — returns undefined for unparseable input. Handles escape sequences correctly.
isComplete(input)
Check if the input is already complete, valid JSON.
Parameters:
input(string): The JSON string to check
Returns: boolean — True if input is valid JSON, false otherwise
Behavior: Uses JSON.parse() internally. Returns false for incomplete or invalid JSON. Throws are caught and converted to false return.
CongealOptions
Options for controlling congeal behavior.
Properties:
partialStrings?(boolean): When true (default), keeps partial string content. When false, drops open strings entirely.
Non-goals
JSON schema validation: Does not validate types or schemas. Use zod or ajv for validation.
const result = congeal('{"age":"thirty"}'); // { age: 'thirty' } - no type checkingMalformed JSON fixing: Only handles truncation, not malformed JSON like trailing commas.
congeal('{"name": "Alice", }'); // undefined - can't fix trailing commaCross-chunk state: Each call is independent — no buffering or state across calls.
congeal('{"name": "Alice", "ag'); // { name: 'Alice' }
congeal('e": 30}'); // undefined - no cross-chunk memoryNon-standard JSON: Does not handle comments, trailing commas, or unquoted keys.
TypeScript
import congeal, { isComplete } from "congeal";
// Type parameter for result
const result: Record<string, unknown> | undefined = congeal(input);
// With known structure
interface User { name: string; age: number; }
const user: User | undefined = congeal<User>('{"name":"Alice","age":30}');Related Packages
- @azghr/filterkit — Type-safe filtering for TypeScript
- @azghr/shorn — Truncate strings by byte budget
- @azghr/singlet — Deduplicate concurrent async calls
- forbear — Read server rate-limit instructions
- quiesce — Graceful shutdown for Node
- sortition — Deterministic percentage rollouts
- staleness — Stale-while-revalidate caching
License
MIT
