@tourik/yeet 0.1.0-rc.1 → 0.1.0-rc.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +144 -0
  2. package/package.json +5 -5
package/README.md ADDED
@@ -0,0 +1,144 @@
1
+ # yeet
2
+
3
+ yeet hosts small apps that AI agents build, deploy and check on their own. An app is one folder
4
+ of TypeScript: a server with a database, sign-in and live queries, and a React page. This package
5
+ holds the `yeet` command and the SDK that apps import.
6
+
7
+ ## Start an app
8
+
9
+ ```sh
10
+ npx @tourik/yeet init notes
11
+ cd notes
12
+ npx yeet dev
13
+ ```
14
+
15
+ - `yeet init notes` creates the folder `notes` with a small todo app in it: a table, a search, a
16
+ query, two mutations and a React page. It installs the app's npm packages and starts a git
17
+ repository. `notes` is also the app's id, which names it on the server.
18
+ - The app's `package.json` holds this package under the name `yeet`. So the app imports
19
+ `yeet/server` and `yeet/react`, and `npx yeet` runs the command.
20
+ - `yeet dev` serves the app at the address it prints, and reloads on every save. It starts on an
21
+ empty database and deletes it when it stops.
22
+
23
+ Then open your coding agent in the folder and describe the app you want. `yeet init` wrote
24
+ `AGENTS.md`, which tells the agent how to write, run, check and deploy a yeet app, and a
25
+ `CLAUDE.md` that points Claude Code at it. `npx yeet agents-md` rewrites yeet's part of
26
+ `AGENTS.md` after an update.
27
+
28
+ Without a name, `yeet init` starts the app in the current folder, under the folder's name. It
29
+ keeps every file that is already there. If it kept a `package.json`, it prints the `npm install`
30
+ command for the packages that file lacks.
31
+
32
+ ## What an app looks like
33
+
34
+ ```
35
+ server/index.ts the tables, and the functions that clients call
36
+ client/ the web page: index.html, index.tsx, index.css, public/
37
+ shared/ TypeScript that both import
38
+ yeet.json the app's id
39
+ ```
40
+
41
+ The server, in `server/index.ts`:
42
+
43
+ ```ts
44
+ import { defineSchema, defineTable, mutation, query, v } from "yeet/server";
45
+
46
+ export default defineSchema({
47
+ todos: defineTable({ owner: v.union(v.string(), v.null()), text: v.string() })
48
+ .index("by_owner", ["owner"]),
49
+ });
50
+
51
+ export const todos = query({
52
+ handler: (ctx) =>
53
+ ctx.db.query("todos").withIndex("by_owner", (q) => q.eq("owner", ctx.auth.userId)).collect(),
54
+ });
55
+
56
+ export const addTodo = mutation({
57
+ args: { text: v.string() },
58
+ handler: (ctx, { text }) => ctx.db.insert("todos", { owner: ctx.auth.userId, text }),
59
+ });
60
+ ```
61
+
62
+ The page, in `client/index.tsx`:
63
+
64
+ ```tsx
65
+ import { createRoot } from "react-dom/client";
66
+ import { useMutation, useQuery, YeetProvider } from "yeet/react";
67
+
68
+ declare module "yeet/react" {
69
+ interface Register {
70
+ server: typeof import("../server/index");
71
+ }
72
+ }
73
+
74
+ function Todos() {
75
+ const todos = useQuery("todos");
76
+ const addTodo = useMutation("addTodo");
77
+ if (todos === undefined) return <p>Loading…</p>;
78
+ return (
79
+ <>
80
+ <button onClick={() => addTodo({ text: "Buy milk" })}>Add</button>
81
+ <ul>
82
+ {todos.map((todo) => (
83
+ <li key={todo._id}>{String(todo.text)}</li>
84
+ ))}
85
+ </ul>
86
+ </>
87
+ );
88
+ }
89
+
90
+ createRoot(document.getElementById("root")!).render(
91
+ <YeetProvider>
92
+ <Todos />
93
+ </YeetProvider>,
94
+ );
95
+ ```
96
+
97
+ `useQuery` keeps its result up to date: when a mutation changes what a query read, every open
98
+ page gets the new result.
99
+
100
+ ## The server API
101
+
102
+ The API resembles Convex's, but it is its own. `server.d.ts` in this package declares all of it.
103
+
104
+ - A `query` only reads. A `mutation` reads and writes in one transaction. An `action` can `fetch`
105
+ and wait, and reaches the data through `ctx.runQuery` and `ctx.runMutation`.
106
+ - `ctx.auth.userId` is the signed-in user's id, or `null`.
107
+ - Tables can have indexes and text search. Functions can run later (`ctx.scheduler`) or on a
108
+ timetable (`cronJobs()`). An app can answer plain HTTP under `/api/` (`httpRouter()`).
109
+ - Server code imports only `yeet/server` and its own files: no npm package. It runs in neither
110
+ Node nor a browser, so `crypto`, `TextEncoder`, `btoa` and `Buffer` do not exist. Client code
111
+ can import npm packages.
112
+ - There is no `v.any()`, `.filter()`, `.paginate()` or `ctx.auth.getUserIdentity()`: `yeet check`
113
+ reports each use with its line.
114
+
115
+ ## Commands
116
+
117
+ Every command takes `--json`, and `npx yeet --help` lists them all.
118
+
119
+ | Command | What it does |
120
+ |---|---|
121
+ | `yeet init [name]` | Starts a new app, in the new folder `<name>` or in the current one |
122
+ | `yeet dev` | Serves the app locally, on an empty database |
123
+ | `yeet run <name> '<json args>' --port <port>` | Calls a function on a running `yeet dev` |
124
+ | `yeet logs --port <port> --errors` | Shows the calls that failed, with their arguments |
125
+ | `yeet check` | Checks the types, the build, and the new code on a copy of the live data |
126
+ | `yeet deploy` | Builds the app and makes it live |
127
+ | `yeet deploy --preview <name>` | Serves the code at its own address, on a copy of the live data |
128
+ | `yeet status`, `yeet logs` | Show the deployed app |
129
+ | `yeet rollback` | Brings back the previous deploy |
130
+ | `yeet login` | Logs in through the browser |
131
+ | `yeet mcp` | Serves the main commands to an agent as MCP tools |
132
+
133
+ ## Deploying
134
+
135
+ - Without a login, `npx yeet deploy` creates an unclaimed app at a random address under
136
+ `yeet.tourik.dev`. It expires 7 days after its last deploy, and it cannot `fetch` or keep
137
+ secrets.
138
+ - With an account, `npx yeet login` and then `npx yeet deploy` serve the app at
139
+ `https://<id>.yeet.tourik.dev`. `npx yeet claim` gives an unclaimed app to your account.
140
+ - Each deployed app has its own database. `npx yeet access` shows and sets who may sign in to it.
141
+
142
+ ## License
143
+
144
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tourik/yeet",
3
- "version": "0.1.0-rc.1",
3
+ "version": "0.1.0-rc.2",
4
4
  "description": "Small apps with a database, sign-in and live updates: the yeet command and its SDK",
5
5
  "license": "MIT",
6
6
  "exports": {
@@ -20,9 +20,9 @@
20
20
  "yeet": "bin/yeet.js"
21
21
  },
22
22
  "optionalDependencies": {
23
- "@tourik/yeet-linux-x64": "0.1.0-rc.1",
24
- "@tourik/yeet-linux-arm64": "0.1.0-rc.1",
25
- "@tourik/yeet-darwin-arm64": "0.1.0-rc.1",
26
- "@tourik/yeet-darwin-x64": "0.1.0-rc.1"
23
+ "@tourik/yeet-linux-x64": "0.1.0-rc.2",
24
+ "@tourik/yeet-linux-arm64": "0.1.0-rc.2",
25
+ "@tourik/yeet-darwin-arm64": "0.1.0-rc.2",
26
+ "@tourik/yeet-darwin-x64": "0.1.0-rc.2"
27
27
  }
28
28
  }