db/cell_item_queries.ts

Raw queries against the cell_item table.

Ordered-child membership: each row is (parent_id, position) → child_id. position is opaque text (fractional-indexing key) — lex ordering is the contract. The PK on (parent_id, position) enforces one cell per slot but allows the same child_id to appear at multiple positions (the primitive is JSON-array-shaped — ordered multiset, not set; domain dedup rules ride on top).

Reads filter both endpoints by cell.deleted_at IS NULL so items dangling off a soft-deleted cell don't surface.

query_cell_item_insert returns the inserted row OR throws the underlying 23505 (Postgres unique violation) on a `(parent_id, position)` collision. Handlers convert this into the cell_item_position_taken JSON-RPC error so the client retries with a refreshed bracket.

view source

Declarations
#

8 declarations

CellItemInsertQueryInput
#

CellItemRow
#

db/cell_item_queries.ts view source

CellItemRow import type {CellItemRow} from '@fuzdev/fuz_app/db/cell_item_queries.js';

Row shape returned by cell_item SELECTs.

parent_id

type Uuid

position

type string

child_id

type Uuid

created_at

type Date

query_cell_item_delete
#

db/cell_item_queries.ts view source

(deps: QueryDeps, parent_id: string & $brand<"Uuid">, position: string): Promise<CellItemRow | null> import {query_cell_item_delete} from '@fuzdev/fuz_app/db/cell_item_queries.js';

Delete one item row by (parent_id, position). Returns the deleted row so callers can audit child_id after the delete without a pre-fetch.

deps

parent_id

type string & $brand<"Uuid">

position

type string

returns

Promise<CellItemRow | null>

the deleted row, or null when nothing matched

query_cell_item_get
#

db/cell_item_queries.ts view source

(deps: QueryDeps, parent_id: string & $brand<"Uuid">, position: string): Promise<CellItemRow | null> import {query_cell_item_get} from '@fuzdev/fuz_app/db/cell_item_queries.js';

Fetch one item row by (parent_id, position). Used by move + delete handlers to confirm the row exists before issuing the mutation.

deps

parent_id

type string & $brand<"Uuid">

position

type string

returns

Promise<CellItemRow | null>

the row or null when not found

query_cell_item_insert
#

db/cell_item_queries.ts view source

(deps: QueryDeps, input: CellItemInsertQueryInput): Promise<CellItemRow> import {query_cell_item_insert} from '@fuzdev/fuz_app/db/cell_item_queries.js';

Insert one item row at the caller-supplied position.

Throws on (parent_id, position) collision (Postgres 23505); handler callers detect via is_pg_unique_violation and surface as cell_item_position_taken. Helper-side jitter (fractional_index) makes the collision rate negligible at realistic UX concurrency, so the throw is the cold-path safety net, not the hot path.

deps

input

returns

Promise<CellItemRow>

query_cell_item_list_for_child
#

db/cell_item_queries.ts view source

(deps: QueryDeps, child_id: string & $brand<"Uuid">, options?: { limit?: number | undefined; } | undefined): Promise<CellItemRow[]> import {query_cell_item_list_for_child} from '@fuzdev/fuz_app/db/cell_item_queries.js';

Reverse items list (child.lists[]).

Returns rows whose child_id = $1, joined to cell on parent_id so items from tombstoned parents don't surface. The caller-side authz filter (per-parent can_view_cell) runs after the SQL fetch — see the 2-layer authz contract on cell_item_list({child_id}).

Bounded by limit (the wire cell_item_list cap) so a heavily inbound-linked child can't force an unbounded fetch + per-parent authz pass on the public, IP-rate-limited reverse endpoint.

deps

child_id

type string & $brand<"Uuid">

options?

type { limit?: number | undefined; } | undefined
optional

returns

Promise<CellItemRow[]>

query_cell_item_list_for_parent
#

db/cell_item_queries.ts view source

(deps: QueryDeps, parent_id: string & $brand<"Uuid">, options?: { limit?: number | undefined; position_after?: string | undefined; } | undefined): Promise<CellItemRow[]> import {query_cell_item_list_for_parent} from '@fuzdev/fuz_app/db/cell_item_queries.js';

Forward items list (parent.items[]), ordered by lex position.

Filters child by deleted_at IS NULL so items pointing at tombstoned cells don't surface; the parent filter is the caller's responsibility (gated upstream by can_view_cell(parent)).

deps

parent_id

type string & $brand<"Uuid">

options?

type { limit?: number | undefined; position_after?: string | undefined; } | undefined
optional

returns

Promise<CellItemRow[]>

query_cell_item_move
#

db/cell_item_queries.ts view source

(deps: QueryDeps, parent_id: string & $brand<"Uuid">, position_old: string, position_new: string): Promise<CellItemRow | null> import {query_cell_item_move} from '@fuzdev/fuz_app/db/cell_item_queries.js';

Move an item row from position_old to position_new (same parent).

Implemented as an UPDATE on the PK; throws 23505 on collision with an existing row at position_new so handlers can surface cell_item_position_taken. The caller-supplied position_new is what fractional-indexing produced for the new slot — collisions are rare but the error path keeps the client truthful.

deps

parent_id

type string & $brand<"Uuid">

position_old

type string

position_new

type string

returns

Promise<CellItemRow | null>

the updated row, or null when the source row was missing (raced with a deleter)

Depends on
#

Imported by
#