@giftlion/typed-storage
v0.0.4
Published
A lightweight, type-safe localStorage wrapper with a SQL-like query API for TypeScript and React applications.
Downloads
18
Readme
@giftlion/typed-storage
A lightweight, type-safe localStorage wrapper with a SQL-like query API for TypeScript and React applications.
Features
- 🎯 Fully Type-Safe - Powered by Zod schemas with complete TypeScript inference
- 🔗 Chainable Query API - Intuitive
query().where().select()syntax - ⚡ Reactive React Hooks - Auto-sync your components with localStorage changes
- 🪶 Lightweight - Minimal bundle size with zero dependencies (except Zod)
- 🔄 Cross-Tab Sync - Automatically syncs data across browser tabs
- 🎨 Familiar API - Inspired by Drizzle ORM and tRPC
Installation
npm install @giftlion/typed-storage zodQuick Start
1. Define Your Schema
import { createClient } from "@giftlion/type-storage";
import { z } from "zod";
const schema = z.object({
users: z.object({
id: z.number(),
name: z.string(),
email: z.string(),
}),
posts: z.object({
id: z.number(),
title: z.string(),
authorId: z.number(),
}),
});
const db = createClient("my-app", { schema });2. Basic CRUD Operations
// Insert
db.users.insert({ id: 1, name: "Alice", email: "[email protected]" });
// Query all
const { data: users } = db.users.query();
// Query with filter
const { data: activeUsers } = db.users
.query()
.where((user) => user.id > 10);
// Query with select
const { data: emails } = db.users
.query()
.select({ email: true });
// Chain where and select
const { data: filtered } = db.users
.query()
.where((user) => user.name.includes("Alice"))
.select({ name: true, email: true });
// Update
db.users.update().where((user) => user.id === 1, { name: "Alice Updated" });
// Delete
db.users.delete().where((user) => user.id === 1);React Integration
Real-time Data Sync
Use the useLiveStorage hook to automatically re-render components when data changes:
import { useLiveStorage } from "@giftlion/typed-storage/react";
import { db } from "./db";
function UserList() {
const { data: users } = useLiveStorage(() => db.users.query());
return (
<ul>
{users?.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
function AddUser() {
const handleAdd = () => {
db.users.insert({
id: Date.now(),
name: "New User",
email: "[email protected]",
});
// UserList component automatically updates!
};
return <button onClick={handleAdd}>Add User</button>;
}API Reference
Query Methods
query()
Start a new query on a table.
db.users.query().where(predicate)
Filter results based on a condition.
db.users.query().where((user) => user.age > 18).select(fields)
Select specific fields from results.
db.users.query().select({ name: true, email: true })Mutation Methods
insert(item)
Insert a single item.
const { data, error } = db.users.insert({ id: 1, name: "Alice", email: "[email protected]" });insertMany(items)
Insert multiple items.
db.users.insertMany([
{ id: 1, name: "Alice", email: "[email protected]" },
{ id: 2, name: "Bob", email: "[email protected]" },
]);update().where(predicate, updates)
Update items matching a condition.
db.users.update().where(
(user) => user.id === 1,
{ name: "Updated Name" }
);delete().where(predicate)
Delete items matching a condition.
db.users.delete().where((user) => user.id === 1);deleteMany().where(predicate)
Delete multiple items.
db.users.deleteMany().where((user) => user.age < 18);Helper Functions
import { equal, contains, notEqual } from "@giftlion/typed-storage";
// Exact match
db.users.query().where(equal({ id: 1 }))
// Contains substring
db.users.query().where(contains({ name: "Alice" }))
// Not equal
db.users.query().where(notEqual({ status: "inactive" }))Advanced Usage
Chaining Queries
const { data } = db.users
.query()
.where((u) => u.age > 18)
.select({ name: true, email: true })
.where((u) => u.email.includes("@gmail.com"));Working with Nested Data
const schema = z.object({
users: z.object({
id: z.number(),
name: z.string(),
profile: z.object({
bio: z.string(),
avatar: z.string(),
}),
}),
});
const db = createClient("app", { schema });
db.users.insert({
id: 1,
name: "Alice",
profile: { bio: "Developer", avatar: "avatar.jpg" },
});
const { data } = db.users
.query()
.where((u) => u.profile.bio.includes("Developer"));TypeScript Tips
The library provides full type inference:
const { data } = db.users.query().select({ name: true, email: true });
// data is typed as: { name: string; email: string }[]
const { data: user } = db.users.insert({ id: 1, name: "Alice", email: "..." });
// user is typed as: { id: number; name: string; email: string }License
MIT
Contributing
Contributions are welcome! Please open an issue or PR on GitHub.
Built with ❤️ using TypeScript and Zod
