# convex-lite at https://convex.edifear.com

convex-lite is a small backend that speaks the public Convex contract. You write standard
Convex code (schema, queries, mutations, actions, `v.*` validators) and use the unmodified
`convex@1.46.0` npm client. This server hosts your functions and data; your frontend can run
anywhere, including localhost.

Read this whole file before writing code. Everything an agent needs is here.

## 1. Project setup

    npm install convex@1.46.0
    mkdir convex

Get the CLI (one-time, any machine):

    git clone https://github.com/Edifear/convex-lite ~/convex-lite
    cd ~/convex-lite && npm ci --ignore-scripts && npm run build
    export CONVEX_LITE=~/convex-lite/bin/convex-lite.js

You need the admin key for pushing code (ask the server owner). Set it once:

    export CONVEX_ADMIN_KEY=...

## 2. Write functions (standard Convex)

`convex/schema.ts`:

    import { defineSchema, defineTable } from "convex/server";
    import { v } from "convex/values";
    export default defineSchema({
      todos: defineTable({ text: v.string(), done: v.boolean() }).index("by_done", ["done"]),
    });

`convex/todos.ts`:

    import { v } from "convex/values";
    import { mutation, query } from "./_generated/server";
    export const list = query({
      args: {},
      handler: async (ctx) => ctx.db.query("todos").order("desc").collect(),
    });
    export const add = mutation({
      args: { text: v.string() },
      handler: async (ctx, { text }) => ctx.db.insert("todos", { text, done: false }),
    });

Rules:
- Every function must declare `args` validators; the server validates them.
- Queries are read-only and deterministic (`Date.now()` is frozen, `Math.random()` seeded, no fetch).
- Mutations are transactions: all writes commit or none. One mutation at a time per app.
- Actions may use `fetch` and call other functions with `ctx.runQuery` / `ctx.runMutation` / `ctx.runAction`.
- `internalQuery` / `internalMutation` / `internalAction` are not callable from clients.
- An action that references `api.<sameModule>.<fn>` needs an explicit return type annotation
  (TypeScript circular inference).

## 3. Push and develop

Watch `convex/` and push on every change (no local backend):

    node $CONVEX_LITE dev --url https://convex.edifear.com --dir convex

This also generates `convex/_generated/` and writes `.env.local` with
`CONVEX_URL` and `VITE_CONVEX_URL=https://convex.edifear.com`. One-off deploy:

    CONVEX_URL=https://convex.edifear.com node $CONVEX_LITE push --dir convex

## 4. Frontend

    import { ConvexProvider, ConvexReactClient } from "convex/react";
    const client = new ConvexReactClient(import.meta.env.VITE_CONVEX_URL);
    // useQuery(api.todos.list, {}), useMutation(api.todos.add), useAction, usePaginatedQuery

`convex/react` and `convex/browser` work unchanged: live queries over WebSocket, optimistic
updates, pagination, `ConvexHttpClient`. CORS is open, so localhost works.

## 5. Call functions without a client (curl)

    curl -s -X POST https://convex.edifear.com/api/query \
      -H 'Content-Type: application/json' \
      -d '{"path":"todos:list","args":[{}]}'

    curl -s -X POST https://convex.edifear.com/api/mutation \
      -H 'Content-Type: application/json' \
      -d '{"path":"todos:add","args":[{"text":"hello"}]}'

Also `/api/action`. `path` is `module:export` (`users/profile:get` for nested files).
Responses: `{"status":"success","value":...,"logLines":[...]}` or HTTP 560 with
`{"status":"error","errorMessage":"...","errorData":...}`.

## 6. Inspect (needs `Authorization: Bearer $CONVEX_ADMIN_KEY`)

    node $CONVEX_LITE tables      --url https://convex.edifear.com
    node $CONVEX_LITE data todos  --url https://convex.edifear.com --limit 20
    node $CONVEX_LITE logs        --url https://convex.edifear.com --limit 50
    node $CONVEX_LITE run todos:list --url https://convex.edifear.com

Raw: GET /api/inspect/functions, /api/inspect/tables, /api/inspect/data?table=todos&limit=100,
/api/inspect/logs?limit=100.

## 7. What works, what does not (v0)

Works: schema + indexes (`by_id`, `by_creation_time`, `.index()`), `db.get/insert/patch/replace/delete`,
`withIndex` ranges (`eq`, `gt`, `gte`, `lt`, `lte`), `order`, `filter`, `take/first/unique/collect`,
`paginate`, full nested documents, all Convex value types, `ConvexError`, `console.log` in logs,
live subscriptions with per-index-range invalidation, actions with `fetch`.

Not yet (each returns a clear `NotSupported` error):
- auth: `ctx.auth.getUserIdentity()` always returns `null`
- `ctx.scheduler` (runAfter/runAt) and cron jobs
- `ctx.storage` (file storage)
- HTTP actions (`httpRouter`)
- `ctx.runQuery` / `ctx.runMutation` inside queries/mutations (fine inside actions)
- full-text and vector search, components, Node.js runtime actions

## 8. Limits (per function call) and error codes

- 16 384 documents read, 8 MiB read, 8 192 writes, 1 MiB per document, 16 levels of nesting
- 10 s for queries/mutations, 60 s for actions, 64 MiB isolate memory
- Codes: ArgumentValidationError, SchemaValidation, FunctionNotFound, FunctionTypeMismatch,
  IndexNotFound, InvalidIndexRange, RowsReadLimit, BytesReadLimit, WritesLimit,
  DocumentTooLarge, DocumentNotFound, NotAllowedInQueryOrMutation, FunctionTimeout, NotSupported.
  Every message says what to change.

## 9. Important: one shared app

This server currently hosts a single app (`default`). Everyone who pushes replaces the same
function set and shares the same tables. Use unique table names or coordinate before pushing.
Per-project apps (`<name>.convex.edifear.com`) are planned.

Demo: https://convex.edifear.com/todo/  ·  Source: https://github.com/Edifear/convex-lite
