@pylonsync/create-pylon 0.3.238 → 0.3.240
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.
- package/package.json +1 -1
- package/templates/_root/AGENTS.md +53 -0
- package/templates/ssr/AGENTS.md +53 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pylonsync/create-pylon",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.240",
|
|
4
4
|
"description": "Scaffold a new Pylon app — realtime backend + web/mobile/expo frontends in one command. Run via `npm create @pylonsync/pylon@latest`.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# AGENTS.md — working in a Pylon project
|
|
2
|
+
|
|
3
|
+
Operating rules for a coding agent in this Pylon app. Pylon is a Rails-like framework for realtime apps: you declare entities, policies, and server functions in TypeScript, and a single Rust binary (`pylon`) serves the API, auth, sync, WebSocket, SSE, and native React 19 SSR — one process, one port. The full API reference is at **/llms-full.txt** (served at `/llms-full.txt`; in the repo at `apps/web/public/llms-full.txt`). Read it before guessing an API name.
|
|
4
|
+
|
|
5
|
+
## Directory conventions
|
|
6
|
+
|
|
7
|
+
**Unified SSR app:**
|
|
8
|
+
- `app.ts` — data model + manifest (`entity()` + `field.*`, queries/actions/policies, `routes: await discoverAppRoutes()`). Ends with `console.log(JSON.stringify(manifest))`.
|
|
9
|
+
- `app/` — file-based SSR routes. `app/page.tsx` → `/`, `app/about/page.tsx` → `/about`, `app/blog/[slug]/page.tsx` → `/blog/:slug`. `app/layout.tsx` is the shell; `app/error.tsx` / `app/not-found.tsx` are boundaries.
|
|
10
|
+
- `app/globals.css` — Tailwind v4 entrypoint (auto-compiled and injected).
|
|
11
|
+
- `functions/` — server functions, one per file, `default`-exported.
|
|
12
|
+
- `.pylon/` — local dev state (sqlite, jobs, sessions, uploads). Created by `pylon dev`. Do not commit.
|
|
13
|
+
|
|
14
|
+
**Monorepo app:** backend is `apps/api/` (entry `apps/api/schema.ts`, handlers in `apps/api/functions/`); frontend in `apps/web/`. `pylon.manifest.json` / `pylon.client.ts` are generated — do not hand-edit.
|
|
15
|
+
|
|
16
|
+
## The core authoring loop
|
|
17
|
+
|
|
18
|
+
1. **Define an entity** — `entity("Thing", { name: field.string(), done: field.boolean().default(false) })`. Modifiers: `.optional()`, `.unique()`, `.readonly()` (settable on insert, rejected on client update — use for `authorId`/`orgId`), `.serverOnly()` (never in HTTP responses), `.encrypted()` (AEAD at rest, needs `PYLON_ENCRYPTION_KEY`), `.crdt("text")` (collaborative).
|
|
19
|
+
2. **Write a policy** — `policy({ entity: "Thing", allowRead, allowInsert, allowUpdate, allowDelete })` with CEL-like expressions over `auth.*` / `data.*` (e.g. `"auth.userId == data.authorId"`). **Omitted actions DENY by default.** Wide-open dev policies (`allow*: "true"`) are flagged by `pylon lint` — tighten before shipping.
|
|
20
|
+
3. **Author a function** in `functions/<name>.ts` — `query` (read-only), `mutation` (transactional read+write), or `action` (external I/O, no direct `ctx.db`). Import `{ query, mutation, action, v }` from `@pylonsync/functions`. `auth` defaults to `"user"` (secure-by-default); set `"public"` explicitly for unauthenticated access. Use `ctx.db.*`, `ctx.auth.userId`, `ctx.error(code, msg)`.
|
|
21
|
+
4. **Read it on the client** — `db.useQuery("Thing")` (live, re-renders on any write) or `db.useQueryOne("Thing", id)`. Call functions with `db.fn(name, args)` / `callFn`. On SSR pages, read via `use(serverData.list("Thing"))` inside `<Suspense>`.
|
|
22
|
+
|
|
23
|
+
## Key gotchas
|
|
24
|
+
|
|
25
|
+
- **Policies deny by default; server functions BYPASS them.** Direct client CRUD (`/api/entities/*`) and sync are policy-checked. Functions run with full DB access — enforce trust with `ctx.auth` checks inside the handler, not policies.
|
|
26
|
+
- **`serverData` (SSR) is READ-ONLY.** No write methods; the runtime rejects write frames (`SSR_WRITE_FORBIDDEN`). Mutations belong in actions/functions, never in a page render.
|
|
27
|
+
- **`response.*` / `response.redirect()` / `response.notFound()` must fire in the synchronous shell render**, before any `await` / `<Suspense>`. The HTTP head commits when the shell is ready — status/headers/cookies set from a suspended subtree are lost, and `redirect`/`notFound` thrown below a Suspense boundary are swallowed.
|
|
28
|
+
- **`ctx.llm` and `ctx.connections` are on mutation + action only, NOT query** (reactive purity). `action` has no direct `ctx.db` — use `ctx.runQuery` / `ctx.runMutation`.
|
|
29
|
+
- **It's `db.useQueryOne`, not `useOne`.** Validators and field types have aliases: `v.bool`/`v.boolean`, `v.float`/`v.number`.
|
|
30
|
+
- **There is no `ctx.files` or `defineWorkflow`/`defineJob`.** Files go through `<FileUpload>` + `/api/files/*`; deferred execution is `ctx.scheduler.runAfter/runAt/cancel`.
|
|
31
|
+
|
|
32
|
+
## Use the CLI — don't guess
|
|
33
|
+
|
|
34
|
+
| Need | Command |
|
|
35
|
+
|---|---|
|
|
36
|
+
| Run the app (SSR + API, hot reload, one port `:4321`) | `pylon dev` (or `npm run dev`) |
|
|
37
|
+
| Regenerate manifest + typed client | `pylon codegen` (Swift client: `pylon codegen client --target swift`) |
|
|
38
|
+
| Validate / diff / push schema | `pylon schema check` \| `diff` \| `push` |
|
|
39
|
+
| Migrations | `pylon migrate create <name>` \| `plan` \| `apply` |
|
|
40
|
+
| Lint policies (PYL001–PYL004) | `pylon lint --strict` |
|
|
41
|
+
| Tests | `pylon test` |
|
|
42
|
+
| Adversarial security probe | `pylon test:security` |
|
|
43
|
+
| Inspect cloud request logs (agent-safe) | `pylon logs --json --limit 50` |
|
|
44
|
+
| Inspect data / entities | `pylon data entities` \| `pylon data list <Entity>` |
|
|
45
|
+
| Call a function | `pylon fn <name> key=value` |
|
|
46
|
+
| Health snapshot | `pylon status` |
|
|
47
|
+
| Build for prod | `pylon build` |
|
|
48
|
+
| Deploy (Pylon Cloud by default) | `pylon deploy` |
|
|
49
|
+
| Look up an error code | `pylon explain <CODE>` |
|
|
50
|
+
|
|
51
|
+
`--json` works on every command for machine-readable output. Prefer one-shot/agent-safe flags (`pylon logs --limit N`, not a blocking `--follow`).
|
|
52
|
+
|
|
53
|
+
For full signatures, env vars, the complete CLI, and SSR/client/server-primitive details: **/llms-full.txt**.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# AGENTS.md — working in a Pylon project
|
|
2
|
+
|
|
3
|
+
Operating rules for a coding agent in this Pylon app. Pylon is a Rails-like framework for realtime apps: you declare entities, policies, and server functions in TypeScript, and a single Rust binary (`pylon`) serves the API, auth, sync, WebSocket, SSE, and native React 19 SSR — one process, one port. The full API reference is at **/llms-full.txt** (served at `/llms-full.txt`; in the repo at `apps/web/public/llms-full.txt`). Read it before guessing an API name.
|
|
4
|
+
|
|
5
|
+
## Directory conventions
|
|
6
|
+
|
|
7
|
+
**Unified SSR app:**
|
|
8
|
+
- `app.ts` — data model + manifest (`entity()` + `field.*`, queries/actions/policies, `routes: await discoverAppRoutes()`). Ends with `console.log(JSON.stringify(manifest))`.
|
|
9
|
+
- `app/` — file-based SSR routes. `app/page.tsx` → `/`, `app/about/page.tsx` → `/about`, `app/blog/[slug]/page.tsx` → `/blog/:slug`. `app/layout.tsx` is the shell; `app/error.tsx` / `app/not-found.tsx` are boundaries.
|
|
10
|
+
- `app/globals.css` — Tailwind v4 entrypoint (auto-compiled and injected).
|
|
11
|
+
- `functions/` — server functions, one per file, `default`-exported.
|
|
12
|
+
- `.pylon/` — local dev state (sqlite, jobs, sessions, uploads). Created by `pylon dev`. Do not commit.
|
|
13
|
+
|
|
14
|
+
**Monorepo app:** backend is `apps/api/` (entry `apps/api/schema.ts`, handlers in `apps/api/functions/`); frontend in `apps/web/`. `pylon.manifest.json` / `pylon.client.ts` are generated — do not hand-edit.
|
|
15
|
+
|
|
16
|
+
## The core authoring loop
|
|
17
|
+
|
|
18
|
+
1. **Define an entity** — `entity("Thing", { name: field.string(), done: field.boolean().default(false) })`. Modifiers: `.optional()`, `.unique()`, `.readonly()` (settable on insert, rejected on client update — use for `authorId`/`orgId`), `.serverOnly()` (never in HTTP responses), `.encrypted()` (AEAD at rest, needs `PYLON_ENCRYPTION_KEY`), `.crdt("text")` (collaborative).
|
|
19
|
+
2. **Write a policy** — `policy({ entity: "Thing", allowRead, allowInsert, allowUpdate, allowDelete })` with CEL-like expressions over `auth.*` / `data.*` (e.g. `"auth.userId == data.authorId"`). **Omitted actions DENY by default.** Wide-open dev policies (`allow*: "true"`) are flagged by `pylon lint` — tighten before shipping.
|
|
20
|
+
3. **Author a function** in `functions/<name>.ts` — `query` (read-only), `mutation` (transactional read+write), or `action` (external I/O, no direct `ctx.db`). Import `{ query, mutation, action, v }` from `@pylonsync/functions`. `auth` defaults to `"user"` (secure-by-default); set `"public"` explicitly for unauthenticated access. Use `ctx.db.*`, `ctx.auth.userId`, `ctx.error(code, msg)`.
|
|
21
|
+
4. **Read it on the client** — `db.useQuery("Thing")` (live, re-renders on any write) or `db.useQueryOne("Thing", id)`. Call functions with `db.fn(name, args)` / `callFn`. On SSR pages, read via `use(serverData.list("Thing"))` inside `<Suspense>`.
|
|
22
|
+
|
|
23
|
+
## Key gotchas
|
|
24
|
+
|
|
25
|
+
- **Policies deny by default; server functions BYPASS them.** Direct client CRUD (`/api/entities/*`) and sync are policy-checked. Functions run with full DB access — enforce trust with `ctx.auth` checks inside the handler, not policies.
|
|
26
|
+
- **`serverData` (SSR) is READ-ONLY.** No write methods; the runtime rejects write frames (`SSR_WRITE_FORBIDDEN`). Mutations belong in actions/functions, never in a page render.
|
|
27
|
+
- **`response.*` / `response.redirect()` / `response.notFound()` must fire in the synchronous shell render**, before any `await` / `<Suspense>`. The HTTP head commits when the shell is ready — status/headers/cookies set from a suspended subtree are lost, and `redirect`/`notFound` thrown below a Suspense boundary are swallowed.
|
|
28
|
+
- **`ctx.llm` and `ctx.connections` are on mutation + action only, NOT query** (reactive purity). `action` has no direct `ctx.db` — use `ctx.runQuery` / `ctx.runMutation`.
|
|
29
|
+
- **It's `db.useQueryOne`, not `useOne`.** Validators and field types have aliases: `v.bool`/`v.boolean`, `v.float`/`v.number`.
|
|
30
|
+
- **There is no `ctx.files` or `defineWorkflow`/`defineJob`.** Files go through `<FileUpload>` + `/api/files/*`; deferred execution is `ctx.scheduler.runAfter/runAt/cancel`.
|
|
31
|
+
|
|
32
|
+
## Use the CLI — don't guess
|
|
33
|
+
|
|
34
|
+
| Need | Command |
|
|
35
|
+
|---|---|
|
|
36
|
+
| Run the app (SSR + API, hot reload, one port `:4321`) | `pylon dev` (or `npm run dev`) |
|
|
37
|
+
| Regenerate manifest + typed client | `pylon codegen` (Swift client: `pylon codegen client --target swift`) |
|
|
38
|
+
| Validate / diff / push schema | `pylon schema check` \| `diff` \| `push` |
|
|
39
|
+
| Migrations | `pylon migrate create <name>` \| `plan` \| `apply` |
|
|
40
|
+
| Lint policies (PYL001–PYL004) | `pylon lint --strict` |
|
|
41
|
+
| Tests | `pylon test` |
|
|
42
|
+
| Adversarial security probe | `pylon test:security` |
|
|
43
|
+
| Inspect cloud request logs (agent-safe) | `pylon logs --json --limit 50` |
|
|
44
|
+
| Inspect data / entities | `pylon data entities` \| `pylon data list <Entity>` |
|
|
45
|
+
| Call a function | `pylon fn <name> key=value` |
|
|
46
|
+
| Health snapshot | `pylon status` |
|
|
47
|
+
| Build for prod | `pylon build` |
|
|
48
|
+
| Deploy (Pylon Cloud by default) | `pylon deploy` |
|
|
49
|
+
| Look up an error code | `pylon explain <CODE>` |
|
|
50
|
+
|
|
51
|
+
`--json` works on every command for machine-readable output. Prefer one-shot/agent-safe flags (`pylon logs --limit N`, not a blocking `--follow`).
|
|
52
|
+
|
|
53
|
+
For full signatures, env vars, the complete CLI, and SSR/client/server-primitive details: **/llms-full.txt**.
|