state-safe-x
v1.0.0
Published
Lightweight runtime state and object validation with human-friendly errors
Maintainers
Readme
🛡️ state-safe-x
Lightweight runtime state and object validation with human-friendly errors.
Why does state-safe-x exist?
Because JavaScript happily lets this happen:
const user = { age: "17" }…and your app finds out much later, usually in production.
state-safe-x exists to answer one simple question:
“Is this object actually safe to use right now?”
Not at compile time. Not in theory. At runtime.
What is state-safe-x?
state-safe-x is a tiny library that guards your objects and state by validating them against a schema.
- ✅ validates runtime data
- ✅ supports nested objects & arrays
- ✅ gives clear, human-friendly errors
- ✅ has a non-throwing
.safe()mode - ✅ works with ESM and CommonJS
- ✅ zero dependencies
No magic. No heavy abstractions. Just protection.
Installation
npm install state-safe-xBasic Usage
import { guard } from "state-safe-x"
const user = {
name: "Alex",
age: 17
}
guard(user, {
name: "string",
age: "number"
})
// If validation fails → throws StateGuardError
// If validation passes → returns the original objectNested Objects
state-safe-x handles deep structures naturally.
const user = {
profile: {
age: 17,
email: "[email protected]"
}
}
guard(user, {
profile: {
age: "number",
email: "string"
}
})Error paths are precise:
"profile.age" should be a numberArrays & Typed Arrays
guard(
{ tags: ["js", "node", "esm"] },
{ tags: "string[]" }
)If something goes wrong:
"tags[1]" should be a stringOptional Fields
Mark optional fields with ?.
guard(
{ name: "Alex" },
{ name: "string", email: "string?" }
).safe() — Non-Throwing Mode
Sometimes you don’t want exceptions. You just want the truth.
const result = guard.safe(
{ age: "17" },
{ age: "number" }
)
if (!result.success) {
console.log(result.errors)
}.safe() returns:
{
success: false,
data: { age: "17" },
errors: [
{
path: "age",
expected: "number",
received: "string",
message: "\"age\" should be a number"
}
]
}Perfect for:
- forms
- APIs
- logging
- batch validation
Error Handling
When using guard() (throwing mode), errors are instances of:
StateGuardErrortry {
guard(data, schema)
} catch (err) {
if (err.name === "StateGuardError") {
console.log(err.errors)
}
}Errors are structured and predictable — no guessing.
When should you use state-safe-x?
Use it when you want to:
- validate API responses
- guard application state
- protect config objects
- validate user input
- avoid silent runtime bugs
- fail fast, or fail safely
If you’ve ever written typeof x === "string" more than once — this is for you.
When not to use it?
- If you only need compile-time types
- If you want a massive, all-in-one validation framework
- If runtime validation doesn’t matter for your use case
state-safe-x is intentionally focused and small.
Design Philosophy
- Runtime first
- Explicit > magical
- Errors should be readable
- APIs should be SIMPLE
- Small surface area
This library is designed to grow without breaking users.
No rush. Stability first.
state-safe-xhelps you sleep better by making sure your data is actually what you think it is.
👨💻 About the Author
Hi cinfinit here 👋
Built state-safe-x after writing one too many typeof, Array.isArray, and “this should be a number” checks scattered across codebases.
Wanted something that:
- validates real runtime data
- stays small and readable
- doesn’t fight JavaScript’s nature
- doesn’t pretend TypeScript solves everything
- gives errors humans can actually understand
So instead of copy-pasting guards everywhere, got it centralized.
That’s all state-safe-x is:
a practical tool born out of real-world JavaScript pain.
No grand framework. No magic. Just safety where JavaScript needs it most.
If this library saves you from one production bug — it’s already done its job.
🧠 Final Note
If you find yourself thinking:
“I know this should be safe… but I wish I could be sure.”
That’s exactly why this exists.
