caspian-utils 0.0.17 → 0.0.18
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/dist/docs/fetch-data.md
CHANGED
|
@@ -17,9 +17,9 @@ related:
|
|
|
17
17
|
- /docs/index
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
This page explains how data fetching works in Caspian. Use route functions for initial page data and use RPC actions for browser-triggered reads, writes, streams, and
|
|
20
|
+
This page explains how data fetching works in Caspian. Use route functions for initial page data and use RPC actions for browser-triggered reads, writes, streams, uploads, and normal CRUD work.
|
|
21
21
|
|
|
22
|
-
Treat RPC as the default way for browser code to talk to Python in Caspian. Do not reach for ad hoc fetch calls to custom JSON endpoints, alternate transport layers, or older helper names unless the task explicitly requires that shape.
|
|
22
|
+
Treat RPC as the default way for browser code to talk to Python in Caspian. For CRUD operations and any browser-initiated backend reads after first render, default to `@rpc()` on the server and `pp.rpc()` in PulsePoint code. Do not reach for ad hoc fetch calls to custom JSON endpoints, alternate transport layers, or older helper names unless the task explicitly requires that shape.
|
|
23
23
|
|
|
24
24
|
MCP is a separate integration surface. Do not place app-owned FastMCP tools in route `index.py` files or treat `@rpc()` actions as a replacement for MCP tools. Use `mcp.md` and `src/lib/mcp/` only when `caspian.config.json` has `mcp: true`. If `mcp` is false, do not assume those files exist.
|
|
25
25
|
|
|
@@ -36,15 +36,18 @@ In practice, most pages use both:
|
|
|
36
36
|
2. Render that data into `index.html`.
|
|
37
37
|
3. Call `pp.rpc()` for refreshes, form submits, toggles, infinite scroll, or streamed updates.
|
|
38
38
|
|
|
39
|
+
If a route only needs UI and does not need first-render data, metadata, or other backend behavior, skip `index.py` and keep the page in `index.html` alone.
|
|
40
|
+
|
|
39
41
|
## Default Data Rule
|
|
40
42
|
|
|
41
43
|
- Use `page()` for async or route-level data required before HTML renders, and use `layout()` only for synchronous shared props or metadata.
|
|
42
|
-
-
|
|
44
|
+
- When a route renders UI and also needs backend work, keep the HTML in the sibling `index.html`; `index.py` should prepare data and call `render_page(__file__, ...)`, not inline the route markup.
|
|
45
|
+
- Use `@rpc()` on the server and `pp.rpc()` in PulsePoint code for all browser-triggered data work after first render, including CRUD operations and follow-up reads.
|
|
43
46
|
- Keep custom REST or other endpoint patterns as explicit exceptions, not the baseline Caspian approach.
|
|
44
47
|
|
|
45
48
|
## Initial Data In `index.py`
|
|
46
49
|
|
|
47
|
-
Use the route's backend file for data that should exist before the template is rendered.
|
|
50
|
+
Use the route's backend file for data that should exist before the template is rendered. Keep the rendered page markup in the sibling `index.html`; if no backend data or logic is needed, omit `index.py` entirely.
|
|
48
51
|
|
|
49
52
|
Example:
|
|
50
53
|
|
|
@@ -120,6 +123,7 @@ Call it from the client with `pp.rpc()`:
|
|
|
120
123
|
|
|
121
124
|
Use RPC for:
|
|
122
125
|
|
|
126
|
+
- CRUD reads and writes after the initial render
|
|
123
127
|
- Button-triggered refreshes
|
|
124
128
|
- Form submissions and mutations
|
|
125
129
|
- Polling or background refreshes
|
|
@@ -292,7 +296,7 @@ If an AI agent is choosing how to load data in Caspian, apply these rules first.
|
|
|
292
296
|
- Put first-render data loading in `src/app/**/index.py`.
|
|
293
297
|
- Put shared section props in `layout.py` only when multiple child routes need the same synchronous data.
|
|
294
298
|
- Keep async I/O in `page()` or `@rpc()` because the current layout engine does not await `layout()`.
|
|
295
|
-
- Treat RPC as the default read and write layer between PulsePoint code and Python route logic.
|
|
299
|
+
- Treat RPC as the default read and write layer between PulsePoint code and Python route logic, especially for CRUD and interactive backend reads.
|
|
296
300
|
- Use `@rpc()` for backend functions that should be callable from the browser.
|
|
297
301
|
- Use `pp.rpc()` for client-side calls; do not prefer older `pp.fetchFunction()` wording.
|
|
298
302
|
- Prefer route-render data plus RPC over inventing parallel REST endpoints for normal Caspian page interactions.
|
package/dist/docs/metadata.md
CHANGED
|
@@ -31,6 +31,8 @@ Metadata is typically defined in one of two files:
|
|
|
31
31
|
- `layout.py` for defaults shared by everything below that folder
|
|
32
32
|
- `index.py` for route-specific metadata
|
|
33
33
|
|
|
34
|
+
On routes that render UI, keep the page markup in the sibling `index.html`. `index.py` is the metadata and backend companion, not the place to store route HTML. If a route needs no metadata or backend behavior, omit `index.py` and keep the page as `index.html` only.
|
|
35
|
+
|
|
34
36
|
The current `Metadata` implementation supports three fields:
|
|
35
37
|
|
|
36
38
|
- `title`
|
|
@@ -26,7 +26,7 @@ Caspian uses a lean project layout that keeps application code in `src`, databas
|
|
|
26
26
|
|
|
27
27
|
As an app grows, keep reusable rendered UI in `src/components/`, keep reusable non-UI support code in `src/lib/`, and keep route-owned files in `src/app/`. That split keeps page composition separate from shared component and service code.
|
|
28
28
|
|
|
29
|
-
In that layout, the default stack is Python components for reusable UI, PulsePoint in templates for reactive browser behavior, RPC for browser-triggered
|
|
29
|
+
In that layout, the default stack is Python components for reusable UI, PulsePoint in templates for reactive browser behavior, RPC for CRUD operations and browser-triggered backend reads, and `casp.validate` for input validation at route and action boundaries.
|
|
30
30
|
|
|
31
31
|
For public pages that can safely reuse rendered HTML, Caspian also supports route-level page caching through `casp.cache_handler`.
|
|
32
32
|
|
|
@@ -105,6 +105,8 @@ This is the main application area. It contains route files, templates, styles, a
|
|
|
105
105
|
|
|
106
106
|
This directory handles file-based routing. Route templates and route-specific backend logic live here.
|
|
107
107
|
|
|
108
|
+
For any route that renders UI, keep that markup in `src/app/**/index.html`. If the route is UI-only, `index.html` alone is enough. Add `src/app/**/index.py` only as a companion when the same route needs metadata, `page()`, `@rpc()` actions, auth checks, caching, redirects, or other server-side behavior. Use a lone `index.py` only for non-visual routes such as redirect-only or action-only handlers.
|
|
109
|
+
|
|
108
110
|
When authoring a route HTML file such as `src/app/**/index.html`, keep the whole template inside exactly one top-level lowercase HTML element. Treat it the same way you would a React component returning one parent element: wrap the route markup and any owned PulsePoint script in the same root.
|
|
109
111
|
|
|
110
112
|
Do not handwrite `pp-component="..."` or `type="text/pp"` in those source templates. Author a plain `<script>` inside the root when you need PulsePoint logic, and let Caspian add the runtime attributes during render.
|
|
@@ -227,7 +229,9 @@ If this layout imports reusable components, place each `<!-- @import ... -->` co
|
|
|
227
229
|
|
|
228
230
|
### `src/app/index.py`
|
|
229
231
|
|
|
230
|
-
The backend logic for the route.
|
|
232
|
+
The backend logic companion for the route. Use this file when the same route needs first-render data, metadata, `@rpc()` actions, auth helpers, `casp.validate`, route-level `Cache(...)` declarations, redirects, or other server behavior.
|
|
233
|
+
|
|
234
|
+
If the route renders UI, keep the markup in the sibling `index.html` and let `index.py` call `render_page(__file__, ...)` with whatever context the template needs. Do not store route HTML in `index.py`. A lone `index.py` should be reserved for non-visual routes.
|
|
231
235
|
|
|
232
236
|
When a route owns a file manager or upload UI, keep the owning upload and delete `@rpc()` actions in that route's `index.py` and move reusable filesystem or Prisma helpers into `src/lib/`. Do not move ordinary upload behavior into `main.py`.
|
|
233
237
|
|
|
@@ -235,6 +239,8 @@ When a route owns a file manager or upload UI, keep the owning upload and delete
|
|
|
235
239
|
|
|
236
240
|
The route template. It supports standard HTML, `<!-- @import ... -->` component imports, and PulsePoint directives, and it should be the default place for reactive frontend behavior in Caspian.
|
|
237
241
|
|
|
242
|
+
If a route renders UI and needs no backend behavior, this file alone is sufficient. If the route also has an `index.py` companion, keep the visible page markup here.
|
|
243
|
+
|
|
238
244
|
Treat import comments as top-of-file directives that belong above the route's single authored root element.
|
|
239
245
|
|
|
240
246
|
Use `components.md` when the task involves authoring reusable `<MyComponent />` tags backed by Python files.
|
|
@@ -281,7 +287,7 @@ If an AI agent is deciding where to make changes, use these rules first.
|
|
|
281
287
|
- Use `settings/bs-config.ts` when uploaded public assets should not trigger BrowserSync reloads during the local stack.
|
|
282
288
|
- Put app-owned FastMCP code in `src/lib/mcp/` only when `caspian.config.json` enables MCP.
|
|
283
289
|
- Use PulsePoint conventions in route templates for reactive frontend behavior.
|
|
284
|
-
- Use `@rpc()` in route/backend code and `pp.rpc()` in client code for browser-triggered data flows.
|
|
290
|
+
- Use `@rpc()` in route/backend code and `pp.rpc()` in client code for browser-triggered data flows, especially CRUD operations and interactive backend reads.
|
|
285
291
|
- Use `casp.cache_handler` when a route's first-render HTML should be reused safely across requests.
|
|
286
292
|
- Use `casp.validate` at route and RPC boundaries, and move reusable validators into `src/lib/` when multiple routes share them.
|
|
287
293
|
- Use `database.md` when the task involves Prisma schema changes, migrations, seed logic, or project-specific database helper conventions.
|
package/dist/docs/pulsepoint.md
CHANGED
|
@@ -44,6 +44,8 @@ If docs, generated examples, or older notes disagree with `public/js/pp-reactive
|
|
|
44
44
|
When a Caspian page needs reactive browser behavior, use PulsePoint.
|
|
45
45
|
|
|
46
46
|
- Use PulsePoint component roots, scripts, directives, and runtime helpers for interactive UI.
|
|
47
|
+
- Use PulsePoint state, effects, refs, and template directives as the default reactivity model in authored Caspian templates.
|
|
48
|
+
- When the browser needs CRUD operations or follow-up reads from the backend, call `pp.rpc()` from PulsePoint code and back it with route or backend `@rpc()` actions.
|
|
47
49
|
- Keep server-rendered HTML plus PulsePoint enhancement as the baseline architecture.
|
|
48
50
|
- Only introduce another frontend runtime when the user explicitly asks for it or the project already depends on one.
|
|
49
51
|
|
|
@@ -413,10 +415,12 @@ These are runtime details.
|
|
|
413
415
|
Use these rules when generating or editing PulsePoint runtime code:
|
|
414
416
|
|
|
415
417
|
- Treat PulsePoint as the default reactive frontend for Caspian app code.
|
|
418
|
+
- Treat `pp.rpc()` as the default browser-to-server path for CRUD operations and interactive backend reads.
|
|
416
419
|
- Use `public/js/pp-reactive-v2.js` as the shipped runtime contract AI should follow.
|
|
417
420
|
- Keep `main.py` in view because it injects the runtime-facing attributes and rewrites authored scripts before the browser sees them.
|
|
418
421
|
- If a development-only source tree exists behind the shipped runtime, treat it as optional implementation detail rather than something generated apps are guaranteed to contain.
|
|
419
422
|
- In authored Caspian templates, do not handwrite `pp-component` or `type="text/pp"`; let the render pipeline inject them.
|
|
423
|
+
- Prefer PulsePoint state and template directives over manual DOM mutation for reactive updates.
|
|
420
424
|
- If you are explicitly editing raw runtime HTML or internals, keep `pp-component` unique per live instance.
|
|
421
425
|
- In authored templates, use a plain `<script>` inside the root. In runtime HTML, the owned script appears as `script[type="text/pp"]`.
|
|
422
426
|
- Keep template-facing variables at top level.
|
package/dist/docs/routing.md
CHANGED
|
@@ -25,8 +25,10 @@ Caspian uses a high-performance file-system router built on top of FastAPI. Your
|
|
|
25
25
|
Start with these rules:
|
|
26
26
|
|
|
27
27
|
- Put application routes in `src/app/`.
|
|
28
|
-
-
|
|
29
|
-
-
|
|
28
|
+
- For any route that renders a page, put the markup in `index.html`.
|
|
29
|
+
- If a route is UI-only, `index.html` by itself is enough.
|
|
30
|
+
- Add `index.py` only when the same route needs metadata, `page()`, `@rpc()` actions, auth checks, caching, redirects, or other server-side logic.
|
|
31
|
+
- Use a standalone `index.py` only for non-visual routes such as redirects or action-only handlers.
|
|
30
32
|
- Use `layout.html` to wrap child routes.
|
|
31
33
|
- Use `layout.py` when a layout needs shared synchronous props or metadata before rendering.
|
|
32
34
|
|
|
@@ -46,7 +48,7 @@ If you already know the Next.js App Router, use this translation layer:
|
|
|
46
48
|
| Next.js concept | Caspian equivalent |
|
|
47
49
|
| --- | --- |
|
|
48
50
|
| `app/` | `src/app/` |
|
|
49
|
-
| `page.tsx` | `index.html`
|
|
51
|
+
| `page.tsx` | `index.html` plus optional `index.py` companion |
|
|
50
52
|
| `layout.tsx` | `layout.html` and optional `layout.py` |
|
|
51
53
|
| `[id]` | `[id]` |
|
|
52
54
|
| `[...slug]` | `[...slug]` |
|
|
@@ -61,20 +63,32 @@ This means most App Router habits carry over directly:
|
|
|
61
63
|
|
|
62
64
|
## Core Concepts
|
|
63
65
|
|
|
64
|
-
Every route lives inside `src/app`.
|
|
66
|
+
Every route lives inside `src/app`. For routes that render UI, `index.html` owns the markup and `index.py` is only an optional companion for server logic or metadata.
|
|
67
|
+
|
|
68
|
+
Use this decision rule when creating routes:
|
|
69
|
+
|
|
70
|
+
| Route shape | Files |
|
|
71
|
+
| --- | --- |
|
|
72
|
+
| UI only | `index.html` |
|
|
73
|
+
| UI plus backend logic or metadata | `index.html` and `index.py` |
|
|
74
|
+
| No rendered page, backend only | `index.py` |
|
|
65
75
|
|
|
66
76
|
Examples:
|
|
67
77
|
|
|
68
|
-
|
|
|
78
|
+
| Files | URL |
|
|
69
79
|
| --- | --- |
|
|
70
80
|
| `src/app/index.html` | `/` |
|
|
71
|
-
| `src/app/about/index.
|
|
81
|
+
| `src/app/about/index.html` | `/about` |
|
|
82
|
+
| `src/app/dashboard/index.html` and `src/app/dashboard/index.py` | `/dashboard` |
|
|
72
83
|
| `src/app/blog/posts/index.html` | `/blog/posts` |
|
|
84
|
+
| `src/app/(auth)/signout/index.py` | `/signout` |
|
|
73
85
|
|
|
74
86
|
### `index.html`
|
|
75
87
|
|
|
76
88
|
Use `index.html` for the route template. This is the route's view layer.
|
|
77
89
|
|
|
90
|
+
If a route renders visible page content, that content belongs here even when the route also has an `index.py` companion.
|
|
91
|
+
|
|
78
92
|
Route templates can import reusable Python components with `<!-- @import ... -->` comments and render them with JSX-style tags such as `<Button />`. Use [components.md](./components.md) for the component authoring rules.
|
|
79
93
|
|
|
80
94
|
Place those import comments at the top of the file, above the authored root element. They are file-level directives, not children of the route root.
|
|
@@ -152,7 +166,9 @@ Write the first form. Caspian produces the second form by injecting `pp-componen
|
|
|
152
166
|
|
|
153
167
|
### `index.py`
|
|
154
168
|
|
|
155
|
-
Use `index.py`
|
|
169
|
+
Use `index.py` as the backend companion when a route needs metadata or async server-side logic. For routes that render UI, keep the markup in the sibling `index.html` and let `page()` call `render_page(__file__, ...)`. Do not inline route HTML inside `index.py`.
|
|
170
|
+
|
|
171
|
+
Use `index.py` by itself only for non-visual routes such as redirects or action-only handlers. Because Caspian runs on FastAPI, the page entry should be async when it performs async work.
|
|
156
172
|
|
|
157
173
|
Example:
|
|
158
174
|
|
|
@@ -168,7 +184,7 @@ async def page():
|
|
|
168
184
|
return render_page(__file__)
|
|
169
185
|
```
|
|
170
186
|
|
|
171
|
-
Use this pattern when the route needs to fetch data, compute metadata, or do other non-blocking server work before rendering.
|
|
187
|
+
Use this pattern when the route needs to fetch data, compute metadata, or do other non-blocking server work before rendering the sibling `index.html`.
|
|
172
188
|
|
|
173
189
|
When a route owns a file manager or upload UI, keep the owning upload and delete `@rpc()` actions in that same `index.py` and move reusable filesystem or Prisma helpers into `src/lib/`. Do not move ordinary upload behavior into `main.py`. See [file-uploads.md](./file-uploads.md).
|
|
174
190
|
|
|
@@ -186,10 +202,12 @@ Wrap a folder name in brackets to make it variable.
|
|
|
186
202
|
|
|
187
203
|
| File | Example URL |
|
|
188
204
|
| --- | --- |
|
|
189
|
-
| `src/app/users/[id]/index.
|
|
205
|
+
| `src/app/users/[id]/index.html` | `/users/123` |
|
|
190
206
|
|
|
191
207
|
These segments are compiled into FastAPI path parameters for efficient route matching.
|
|
192
208
|
|
|
209
|
+
Add a sibling `index.py` when the dynamic route needs params during render, metadata, or other backend logic.
|
|
210
|
+
|
|
193
211
|
In the current `main.py` router, path params are collected into a single dict and passed as the first positional argument to `page()`. Matching query params can still be injected by name, and `request` is passed by keyword when declared.
|
|
194
212
|
|
|
195
213
|
Example:
|
|
@@ -208,20 +226,22 @@ Use an ellipsis inside brackets to match multiple path parts.
|
|
|
208
226
|
|
|
209
227
|
| File | Example URL |
|
|
210
228
|
| --- | --- |
|
|
211
|
-
| `src/app/docs/[...slug]/index.
|
|
229
|
+
| `src/app/docs/[...slug]/index.html` | `/docs/getting-started/setup` |
|
|
212
230
|
|
|
213
231
|
Use catch-all routes when the number of path segments is not fixed ahead of time.
|
|
214
232
|
|
|
233
|
+
Add a sibling `index.py` when that catch-all route also needs backend logic or metadata.
|
|
234
|
+
|
|
215
235
|
## Route Groups
|
|
216
236
|
|
|
217
237
|
Wrap a folder name in parentheses to organize code without adding that segment to the URL.
|
|
218
238
|
|
|
219
239
|
Examples:
|
|
220
240
|
|
|
221
|
-
|
|
|
241
|
+
| Files | URL |
|
|
222
242
|
| --- | --- |
|
|
223
|
-
| `src/app/(auth)/
|
|
224
|
-
| `src/app/(auth)/
|
|
243
|
+
| `src/app/(auth)/signin/index.html` and `src/app/(auth)/signin/index.py` | `/signin` |
|
|
244
|
+
| `src/app/(auth)/signup/index.html` and `src/app/(auth)/signup/index.py` | `/signup` |
|
|
225
245
|
|
|
226
246
|
Route groups are useful when you want to:
|
|
227
247
|
|
|
@@ -292,18 +312,25 @@ src/
|
|
|
292
312
|
index.html
|
|
293
313
|
users/
|
|
294
314
|
[id]/
|
|
315
|
+
index.html
|
|
295
316
|
index.py
|
|
296
317
|
docs/
|
|
297
318
|
[...slug]/
|
|
319
|
+
index.html
|
|
298
320
|
index.py
|
|
299
321
|
(auth)/
|
|
300
322
|
login/
|
|
323
|
+
index.html
|
|
301
324
|
index.py
|
|
302
325
|
register/
|
|
326
|
+
index.html
|
|
327
|
+
index.py
|
|
328
|
+
signout/
|
|
303
329
|
index.py
|
|
304
330
|
dashboard/
|
|
305
331
|
layout.html
|
|
306
332
|
settings/
|
|
333
|
+
index.html
|
|
307
334
|
index.py
|
|
308
335
|
```
|
|
309
336
|
|
|
@@ -313,7 +340,8 @@ If an AI agent is choosing where to add or update route code, apply these rules
|
|
|
313
340
|
|
|
314
341
|
- Treat `src/app/` as the routing source of truth.
|
|
315
342
|
- Use folder names to model URL segments.
|
|
316
|
-
-
|
|
343
|
+
- If a route renders UI, create or update `index.html` for the markup.
|
|
344
|
+
- Add `index.py` only when the same route needs metadata or server behavior; do not place route HTML in `index.py`.
|
|
317
345
|
- Use [cache.md](./cache.md) when an `index.py` route should opt into page-level HTML caching.
|
|
318
346
|
- Use `layout.html` for shared wrappers and `layout.py` for layout-level synchronous props or metadata.
|
|
319
347
|
- Keep `<!-- @import ... -->` directives at the top of `index.html` and `layout.html`, above the single authored root element.
|