From de867a9d589dee214d4d525dd6e3cb843e7fe9d0 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 5 Jun 2026 22:24:30 +0000 Subject: [PATCH] Rename defineFirestate to createFirestate Rename the registry API entry point across source, tests, the runnable example, and all documentation. The lower-level defineDocument / defineCollection escape hatch is unchanged. https://claude.ai/code/session_01VRSXNBSHMuJ7aFPx9GHWYx --- AGENTS.md | 6 +++--- CONTRIBUTING.md | 2 +- README.md | 12 ++++++------ docs/api-recipes.md | 6 +++--- docs/architecture.md | 4 ++-- examples/react-tasks/src/App.tsx | 2 +- examples/react-tasks/src/schemas.ts | 4 ++-- src/firestate.test.ts | 14 +++++++------- src/firestate.ts | 10 +++++----- src/index.ts | 2 +- src/schema.ts | 4 ++-- 11 files changed, 33 insertions(+), 33 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 292ba7c..44e8b64 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -13,7 +13,7 @@ The recommended application API is registry-based: ```ts import { z } from 'zod' -import { defineFirestate, doc, col } from '@hvakr/firestate' +import { createFirestate, doc, col } from '@hvakr/firestate' const TaskListSchema = z.object({ name: z.string(), createdAt: z.number() }) const TaskSchema = z.object({ @@ -21,7 +21,7 @@ const TaskSchema = z.object({ completed: z.boolean(), }) -export const { useTaskList, useTasks } = defineFirestate({ +export const { useTaskList, useTasks } = createFirestate({ taskList: doc({ path: 'taskLists/{listId}', schema: TaskListSchema }), tasks: col({ path: 'taskLists/{listId}/tasks', schema: TaskSchema }), }) @@ -47,7 +47,7 @@ CI runs `pnpm typecheck`, `pnpm build`, and `pnpm test` on Node 22. ## Source Map - `src/index.ts` - public exports. Update this when adding public API. -- `src/firestate.ts` - registry API: `defineFirestate`, `doc`, `col`, path +- `src/firestate.ts` - registry API: `createFirestate`, `doc`, `col`, path template validation, generated hook typing. - `src/schema.ts` - lower-level definition helpers. - `src/types.ts` - public state, handle, definition, undo, and config types. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6b86903..ed4813d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,7 +36,7 @@ pnpm test:coverage ## Change Guidelines -- Prefer the registry API (`defineFirestate`, `doc`, `col`) for examples and +- Prefer the registry API (`createFirestate`, `doc`, `col`) for examples and app-facing docs. - Keep the lower-level API (`defineDocument`, `defineCollection`, `useDocument`, `useCollection`) working as an escape hatch. diff --git a/README.md b/README.md index 921af23..e984a15 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Firestate provides a declarative, schema-first approach that eliminates boilerpl Firestate exposes two layers. Pick one based on what you're building: -- **`defineFirestate` + `doc` / `col`** (recommended for app code) — declare every Firestore thing in a single registry object; the library generates one typed React hook per entry. Each entry takes a `path` template and a Zod `schema`. In return you get: +- **`createFirestate` + `doc` / `col`** (recommended for app code) — declare every Firestore thing in a single registry object; the library generates one typed React hook per entry. Each entry takes a `path` template and a Zod `schema`. In return you get: - the data type (`TaskList`) inferred from the schema via `z.infer` - the param keys (`{ listId }`) inferred from the path template and enforced at call sites - runtime validation on `set` / `add` writes — bad data throws at the call site instead of after a Firestore round trip @@ -40,12 +40,12 @@ Firestate exposes two layers. Pick one based on what you're building: ```ts import { z } from 'zod' - import { defineFirestate, doc, col } from '@hvakr/firestate' + import { createFirestate, doc, col } from '@hvakr/firestate' const TaskListSchema = z.object({ name: z.string(), createdAt: z.number() }) const TaskSchema = z.object({ title: z.string(), completed: z.boolean() }) - export const { useTaskList, useTasks } = defineFirestate({ + export const { useTaskList, useTasks } = createFirestate({ taskList: doc({ path: 'taskLists/{listId}', schema: TaskListSchema }), tasks: col({ path: 'taskLists/{listId}/tasks', schema: TaskSchema }), }) @@ -370,14 +370,14 @@ awaiting writes is not feasible. ### Registry API -#### `defineFirestate(registry)` +#### `createFirestate(registry)` Creates typed React hooks from a registry object. Each key becomes a hook named `use{CapitalizedKey}`. ```typescript import { z } from 'zod' -import { defineFirestate, doc, col } from '@hvakr/firestate' +import { createFirestate, doc, col } from '@hvakr/firestate' const ProjectSchema = z.object({ name: z.string(), @@ -390,7 +390,7 @@ const SpaceSchema = z.object({ floor: z.number(), }) -export const { useProject, useSpaces } = defineFirestate({ +export const { useProject, useSpaces } = createFirestate({ project: doc({ path: 'projects/{projectId}', schema: ProjectSchema, diff --git a/docs/api-recipes.md b/docs/api-recipes.md index aa5f53c..24d3205 100644 --- a/docs/api-recipes.md +++ b/docs/api-recipes.md @@ -5,11 +5,11 @@ modifying Firestate. ## Recommended Registry API -Use `defineFirestate`, `doc`, and `col` for normal app code. +Use `createFirestate`, `doc`, and `col` for normal app code. ```ts import { z } from 'zod' -import { defineFirestate, doc, col } from '@hvakr/firestate' +import { createFirestate, doc, col } from '@hvakr/firestate' const ProjectSchema = z.object({ name: z.string(), @@ -22,7 +22,7 @@ const SpaceSchema = z.object({ floor: z.number(), }) -export const { useProject, useSpaces } = defineFirestate({ +export const { useProject, useSpaces } = createFirestate({ project: doc({ path: 'projects/{projectId}', schema: ProjectSchema, diff --git a/docs/architecture.md b/docs/architecture.md index 1e32556..e11854b 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -4,7 +4,7 @@ Firestate has two public API layers over the same core subscription system. The recommended layer is the registry API: -- `defineFirestate(registry)` creates named React hooks. +- `createFirestate(registry)` creates named React hooks. - `doc({ path, schema })` declares one document entry. - `col({ path, schema })` declares one collection entry. @@ -24,7 +24,7 @@ At runtime, a typical React app follows this flow: 1. The app renders `FirestateProvider` with a Firestore instance. 2. `FirestateProvider` creates a `FirestateStore`. -3. A generated hook from `defineFirestate`, or a direct call to `useDocument` +3. A generated hook from `createFirestate`, or a direct call to `useDocument` / `useCollection`, resolves the Firestore path from params. 4. The hook creates a document or collection subscription. 5. The subscription attaches an `onSnapshot` listener when loaded. diff --git a/examples/react-tasks/src/App.tsx b/examples/react-tasks/src/App.tsx index 7d5e0a7..371b551 100644 --- a/examples/react-tasks/src/App.tsx +++ b/examples/react-tasks/src/App.tsx @@ -15,7 +15,7 @@ const LIST_ID = 'demo-list' function TaskListEditor() { const params = { listId: LIST_ID } - // The two hooks below come straight from `defineFirestate(...)` in + // The two hooks below come straight from `createFirestate(...)` in // schemas.ts — one registry, generated `useTaskList` / `useTasks`. const taskList = useTaskList(params) const tasks = useTasks(params) diff --git a/examples/react-tasks/src/schemas.ts b/examples/react-tasks/src/schemas.ts index e701cdc..2484bcb 100644 --- a/examples/react-tasks/src/schemas.ts +++ b/examples/react-tasks/src/schemas.ts @@ -1,7 +1,7 @@ -import { defineFirestate, doc, col } from '@hvakr/firestate' +import { createFirestate, doc, col } from '@hvakr/firestate' import { TaskListSchema, TaskSchema } from './types' -export const { useTaskList, useTasks } = defineFirestate({ +export const { useTaskList, useTasks } = createFirestate({ taskList: doc({ path: 'taskLists/{listId}', schema: TaskListSchema, diff --git a/src/firestate.test.ts b/src/firestate.test.ts index bedd419..f52aa33 100644 --- a/src/firestate.test.ts +++ b/src/firestate.test.ts @@ -1,7 +1,7 @@ import { describe, it, expect } from 'vitest' import { z } from 'zod' import { - defineFirestate, + createFirestate, doc, col, interpolatePath, @@ -138,9 +138,9 @@ describe('splitDocPath', () => { }) }) -describe('defineFirestate', () => { +describe('createFirestate', () => { it('produces a hook per registry key', () => { - const api = defineFirestate({ + const api = createFirestate({ taskList: doc({ path: 'taskLists/{listId}', schema: tlSchema }), tasks: col({ path: 'taskLists/{listId}/tasks', @@ -153,7 +153,7 @@ describe('defineFirestate', () => { }) it('capitalizes the first character of each key', () => { - const api = defineFirestate({ + const api = createFirestate({ a: doc({ path: 'a/{id}', schema: tlSchema }), longerName: col({ path: 'a/{id}/sub', schema: taskSchema }), }) @@ -164,13 +164,13 @@ describe('defineFirestate', () => { it('rejects invalid keys', () => { expect(() => - defineFirestate({ + createFirestate({ '1bad': doc({ path: 'a/{id}', schema: tlSchema }), } as any) ).toThrow(/must start with a letter/) expect(() => - defineFirestate({ + createFirestate({ 'bad-key': doc({ path: 'a/{id}', schema: tlSchema }), } as any) ).toThrow(/must start with a letter/) @@ -215,7 +215,7 @@ describe('type-level params extraction', () => { // "is this call signature actually enforced?". it('requires the right param keys at call sites', () => { function _typeTest() { - const api = defineFirestate({ + const api = createFirestate({ taskList: doc({ path: 'taskLists/{listId}', schema: tlSchema, diff --git a/src/firestate.ts b/src/firestate.ts index d71e4a3..d622ccf 100644 --- a/src/firestate.ts +++ b/src/firestate.ts @@ -9,7 +9,7 @@ * interface TaskList { name: string; createdAt: number } * interface Task { title: string; completed: boolean } * - * export const { useTaskList, useTasks } = defineFirestate({ + * export const { useTaskList, useTasks } = createFirestate({ * taskList: doc('taskLists/{listId}'), * tasks: col('taskLists/{listId}/tasks'), * }) @@ -223,7 +223,7 @@ export function col< } // --------------------------------------------------------------------------- -// defineFirestate +// createFirestate // --------------------------------------------------------------------------- type HookName = `use${Capitalize}`; @@ -262,13 +262,13 @@ export type FirestateApi = { * `K` produces a hook named `use{Capitalize}`. * * ```ts - * export const { useTaskList, useTasks } = defineFirestate({ + * export const { useTaskList, useTasks } = createFirestate({ * taskList: doc('taskLists/{listId}'), * tasks: col('taskLists/{listId}/tasks'), * }) * ``` */ -export function defineFirestate( +export function createFirestate( registry: R ): FirestateApi { const api: Record = {}; @@ -303,7 +303,7 @@ export function defineFirestate( /** * Build the underlying {@link DocumentDefinition} for a registry doc entry. * Exported for unit testing — registry consumers should call - * {@link defineFirestate} instead. + * {@link createFirestate} instead. * * @internal */ diff --git a/src/index.ts b/src/index.ts index 4744260..28d2d77 100644 --- a/src/index.ts +++ b/src/index.ts @@ -38,7 +38,7 @@ export type { } from './schema' // Registry-driven API -export { defineFirestate, doc, col } from './firestate' +export { createFirestate, doc, col } from './firestate' export type { DocEntry, diff --git a/src/schema.ts b/src/schema.ts index fca43c7..a075fa9 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -8,7 +8,7 @@ import type { /** * Define a typed document. `TData` is the document's TypeScript shape. * - * **Most apps should reach for {@link defineFirestate} + {@link doc} instead** + * **Most apps should reach for {@link createFirestate} + {@link doc} instead** * — that builds a registry of every Firestore thing in one object and * generates typed hooks for you. `defineDocument` is the lower-level * escape hatch: use it when you need fully custom `collection` / `id` @@ -61,7 +61,7 @@ export function defineDocument( * Define a typed collection. `TData` is the shape of each document in the * collection. See {@link defineDocument} for the schema/plain-type tradeoff. * - * **Most apps should reach for {@link defineFirestate} + {@link col} instead.** + * **Most apps should reach for {@link createFirestate} + {@link col} instead.** * `defineCollection` is the escape hatch for fully custom path derivation * or non-React usage. *