# eval-safe _(no submodules)_ ## Purpose Provides `serializeEvalSafe` and `deserializeEvalSafe` as an explicit opt-in adapter for scenarios where the standard tagged JSON or MessagePack codecs cannot be used — for example, when the payload must include JavaScript `Function` values, `RegExp` literals with complex syntax, or other types that cannot be expressed in a JSON-safe intermediate. The adapter wraps the `serialize-javascript` library, which is purpose-built for this use case (e.g. server-side Redux initial state injection into HTML). This module lives under the `./unsafe` subpath export and must **never** appear in the main `@suaveplan/serialize` bundle. Importing it is an explicit acknowledgment of the security trade-off. ## Features - `serializeEvalSafe` — produces a JavaScript expression string via `serialize-javascript` that, when eval'd, reconstructs the original value including Functions and RegExps - `deserializeEvalSafe` — evaluates the produced string via `(0, eval)(...)` (indirect eval) to reconstruct the value - Security warning emitted on every call unless `{ ignoreSecurityWarning: true }` is passed - `EvalSafeOptions` interface for suppressing warnings in controlled environments ## Usage: Basic Example ```typescript import { serializeEvalSafe, deserializeEvalSafe } from "@suaveplan/serialize/unsafe"; // Suppress warnings in a trusted server-side context const str = serializeEvalSafe({ fn: () => 42 }, { ignoreSecurityWarning: true }); const restored = deserializeEvalSafe(str, { ignoreSecurityWarning: true }); // (restored as any).fn() === 42 ``` ## Usage: Advanced Example ```typescript import { serializeEvalSafe } from "@suaveplan/serialize/unsafe"; // Inject Redux initial state into an HTML page server-side. // This is the canonical use case for serialize-javascript. const html = ` `; ``` ## API Reference ### `serializeEvalSafe(value: unknown, opts?: EvalSafeOptions): string` Serialize `value` using `serialize-javascript`. The output is a JavaScript expression string, not JSON. **Parameters:** - `value` — any JavaScript value, including Functions and RegExps - `opts.ignoreSecurityWarning` — pass `true` to suppress the `console.warn` **Returns:** a JavaScript expression string. ### `deserializeEvalSafe(json: string, opts?: EvalSafeOptions): unknown` Evaluate `json` as a JavaScript expression and return the result. **Parameters:** - `json` — a string produced by `serializeEvalSafe`; MUST be from a trusted source - `opts.ignoreSecurityWarning` — pass `true` to suppress the `console.warn` **Returns:** the reconstructed value. **Security:** Uses indirect `eval` (`(0, eval)(...)`), which runs in the global scope rather than the local closure scope, slightly reducing the attack surface compared to direct `eval`. ### `EvalSafeOptions` ```typescript interface EvalSafeOptions { ignoreSecurityWarning?: boolean; } ``` ## Implementation Notes - The `(0, eval)(...)` pattern (indirect eval) is used intentionally: it evaluates in the global scope rather than capturing local variables, which slightly reduces the blast radius if a malicious string is accidentally evaluated. - `serialize-javascript` is listed as a regular dependency (not a dev dependency) because it is shipped as part of the `/unsafe` subpath. The main bundle's Rollup config marks it as `external`, so it is never bundled into `dist/index.js`. - The biome `lint/security/noEval` rule is suppressed with a comment at the call site to document that the eval usage is intentional, reviewed, and isolated to this specific adapter.