caspian-utils 0.0.1
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/auth.md +690 -0
- package/dist/docs/cache.md +257 -0
- package/dist/docs/commands.md +117 -0
- package/dist/docs/database.md +351 -0
- package/dist/docs/fetch-data.md +260 -0
- package/dist/docs/index.md +65 -0
- package/dist/docs/installation.md +98 -0
- package/dist/docs/metadata.md +196 -0
- package/dist/docs/project-structure.md +193 -0
- package/dist/docs/pulsepoint.md +368 -0
- package/dist/docs/routing.md +231 -0
- package/dist/docs/state.md +264 -0
- package/dist/docs/validation.md +293 -0
- package/package.json +16 -0
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Cache
|
|
3
|
+
description: Cache rendered Caspian route HTML with `casp.cache_handler`, `Cache`, and `CacheHandler`, using route-level TTLs, file-system storage, and explicit invalidation for public read-heavy pages.
|
|
4
|
+
related:
|
|
5
|
+
title: Related docs
|
|
6
|
+
description: Use the routing guide to place route-level cache declarations correctly, then pair cache with fetch-data when deciding what can be safely served from reused HTML.
|
|
7
|
+
links:
|
|
8
|
+
- /docs/routing
|
|
9
|
+
- /docs/fetch-data
|
|
10
|
+
- /docs/project-structure
|
|
11
|
+
- /docs/index
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
This page explains the current Caspian page-cache API for route-level HTML caching, disk-backed cache storage, TTL handling, and manual invalidation.
|
|
15
|
+
|
|
16
|
+
Treat `casp.cache_handler` as the default page-caching layer in Caspian app code. Use it for public, read-heavy routes whose rendered HTML can be safely reused across requests. Do not cache personalized, auth-sensitive, or rapidly changing HTML unless you fully control invalidation and visibility.
|
|
17
|
+
|
|
18
|
+
## Overview
|
|
19
|
+
|
|
20
|
+
Caspian exposes page caching through `casp.cache_handler`.
|
|
21
|
+
|
|
22
|
+
Import the API like this:
|
|
23
|
+
|
|
24
|
+
```python
|
|
25
|
+
from casp.cache_handler import Cache, CacheHandler
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
The current installed implementation lives in `.venv/Lib/site-packages/casp/cache_handler.py`.
|
|
29
|
+
|
|
30
|
+
The real API surface is:
|
|
31
|
+
|
|
32
|
+
- declarative route config with `Cache(ttl=..., enabled=...)`
|
|
33
|
+
- disk-backed HTML lookup with `CacheHandler.serve_cache(...)`
|
|
34
|
+
- disk-backed HTML writes with `CacheHandler.save_cache(...)`
|
|
35
|
+
- selective invalidation with `CacheHandler.invalidate_by_uri(...)`
|
|
36
|
+
- full or targeted resets with `CacheHandler.reset_cache(...)`
|
|
37
|
+
|
|
38
|
+
Use caching when a route is expensive to render but the final HTML is stable enough to reuse, such as marketing pages, blog indexes, docs pages, and public content pages.
|
|
39
|
+
|
|
40
|
+
## Default Caching Rule
|
|
41
|
+
|
|
42
|
+
- Use `Cache(...)` at module scope in a route's `index.py` when you want that route to participate in Caspian's page cache.
|
|
43
|
+
- Cache public HTML that is safe to share between visitors.
|
|
44
|
+
- Avoid caching dashboards, auth callbacks, request-specific error states, flash-message flows, or any page whose HTML changes per user.
|
|
45
|
+
- Invalidate cached pages after writes, publishes, deletes, or admin actions that change what those routes should render.
|
|
46
|
+
- Treat page caching as HTML reuse, not as a replacement for database caching or RPC response caching.
|
|
47
|
+
|
|
48
|
+
## Declarative Route Config
|
|
49
|
+
|
|
50
|
+
The `Cache` dataclass is the project-facing API you define in route code.
|
|
51
|
+
|
|
52
|
+
Current fields:
|
|
53
|
+
|
|
54
|
+
- `ttl: int = 600`
|
|
55
|
+
- `enabled: bool = True`
|
|
56
|
+
|
|
57
|
+
Example:
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from casp.layout import render_page
|
|
61
|
+
from casp.cache_handler import Cache
|
|
62
|
+
|
|
63
|
+
cache_settings = Cache(ttl=3600, enabled=True)
|
|
64
|
+
|
|
65
|
+
async def page():
|
|
66
|
+
return render_page(__file__)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
You can also rely on the current auto-registration behavior and call `Cache(...)` bare at module scope:
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
from casp.layout import render_page
|
|
73
|
+
from casp.cache_handler import Cache
|
|
74
|
+
|
|
75
|
+
Cache(ttl=7200, enabled=True)
|
|
76
|
+
|
|
77
|
+
async def page():
|
|
78
|
+
return render_page(__file__)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Implementation notes from the installed file:
|
|
82
|
+
|
|
83
|
+
- `Cache.__post_init__()` inspects the caller frame.
|
|
84
|
+
- When `Cache(...)` is called at module scope, it auto-registers itself as `cache_settings` in that module's globals.
|
|
85
|
+
- That magic registration only happens for module-level calls where the caller code object name is `<module>`.
|
|
86
|
+
|
|
87
|
+
Prefer the explicit `cache_settings = Cache(...)` form in maintained project code because it makes the route intent obvious to readers and tooling.
|
|
88
|
+
|
|
89
|
+
To disable caching for a route explicitly:
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
from casp.cache_handler import Cache
|
|
93
|
+
|
|
94
|
+
cache_settings = Cache(enabled=False)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
Use this for routes that are public but too volatile or sensitive to serve from cached HTML.
|
|
98
|
+
|
|
99
|
+
## How The Disk Cache Works
|
|
100
|
+
|
|
101
|
+
`CacheHandler` stores cached HTML on disk under the current working directory.
|
|
102
|
+
|
|
103
|
+
Current paths:
|
|
104
|
+
|
|
105
|
+
- cache directory: `caches/`
|
|
106
|
+
- manifest file: `caches/cache_manifest.json`
|
|
107
|
+
|
|
108
|
+
The request lifecycle is conceptually:
|
|
109
|
+
|
|
110
|
+
1. A request arrives for a URI.
|
|
111
|
+
2. `CacheHandler.serve_cache(uri, default_ttl=600)` checks `cache_manifest.json` for that exact URI.
|
|
112
|
+
3. If the manifest entry is missing, the file is missing, or the entry has expired, the request is treated as a cache miss.
|
|
113
|
+
4. On a hit, Caspian returns the cached HTML string directly.
|
|
114
|
+
5. On a miss, the route renders normally and the framework can persist the rendered HTML with `CacheHandler.save_cache(...)`.
|
|
115
|
+
|
|
116
|
+
Filename generation is path-based:
|
|
117
|
+
|
|
118
|
+
- `/` becomes `index.html`
|
|
119
|
+
- other paths are lowercased, non-alphanumeric characters are replaced with `_`, and the result is saved as `*.html`
|
|
120
|
+
|
|
121
|
+
Examples:
|
|
122
|
+
|
|
123
|
+
- `/docs/cache` becomes `docs_cache.html`
|
|
124
|
+
- `/blog/post-1` becomes `blog_post-1.html`
|
|
125
|
+
|
|
126
|
+
## `CacheHandler` Methods
|
|
127
|
+
|
|
128
|
+
The installed `CacheHandler` class currently provides these main helpers:
|
|
129
|
+
|
|
130
|
+
| Method | Purpose | Return value |
|
|
131
|
+
| --- | --- | --- |
|
|
132
|
+
| `ensure_cache_dir()` | Creates `caches/` and `cache_manifest.json` if needed. | None |
|
|
133
|
+
| `serve_cache(uri, default_ttl=600)` | Returns cached HTML when the entry exists and is still fresh. | Cached `str` or `None` |
|
|
134
|
+
| `save_cache(uri, content, ttl=0)` | Writes the HTML file and updates the manifest entry. | None |
|
|
135
|
+
| `invalidate_by_uri(uris)` | Removes one or more cached URIs and their HTML files. | None |
|
|
136
|
+
| `reset_cache(uri=None)` | Removes a specific cached URI or clears the whole cache directory. | None |
|
|
137
|
+
|
|
138
|
+
Example manual usage:
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
from casp.cache_handler import CacheHandler
|
|
142
|
+
|
|
143
|
+
html = CacheHandler.serve_cache("/docs/cache", default_ttl=600)
|
|
144
|
+
if html is not None:
|
|
145
|
+
return html
|
|
146
|
+
|
|
147
|
+
CacheHandler.invalidate_by_uri("/docs/cache")
|
|
148
|
+
CacheHandler.invalidate_by_uri([
|
|
149
|
+
"/blog",
|
|
150
|
+
"/blog/python",
|
|
151
|
+
])
|
|
152
|
+
|
|
153
|
+
CacheHandler.reset_cache("/docs/cache")
|
|
154
|
+
# Or clear everything:
|
|
155
|
+
# CacheHandler.reset_cache()
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
In normal route code, `CacheHandler.serve_cache(...)` and `save_cache(...)` are usually framework-driven internals. App code most often interacts with `Cache(...)` and with invalidation helpers after content changes.
|
|
159
|
+
|
|
160
|
+
## Invalidate After Mutations
|
|
161
|
+
|
|
162
|
+
If a cached page depends on mutable content, invalidate it after the write succeeds.
|
|
163
|
+
|
|
164
|
+
Example:
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
from casp.rpc import rpc
|
|
168
|
+
from casp.cache_handler import CacheHandler
|
|
169
|
+
|
|
170
|
+
@rpc(require_auth=True)
|
|
171
|
+
async def publish_post(slug: str):
|
|
172
|
+
# Save post changes here.
|
|
173
|
+
|
|
174
|
+
CacheHandler.invalidate_by_uri([
|
|
175
|
+
"/blog",
|
|
176
|
+
f"/blog/{slug}",
|
|
177
|
+
])
|
|
178
|
+
|
|
179
|
+
return {"success": True}
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Use this pattern when:
|
|
183
|
+
|
|
184
|
+
- an RPC action updates a blog post, docs page, or product page
|
|
185
|
+
- an admin publish flow changes public route output
|
|
186
|
+
- a route index depends on records that were just created or deleted
|
|
187
|
+
|
|
188
|
+
For browser-triggered writes and invalidation flows, pair this page with [fetch-data.md](./fetch-data.md).
|
|
189
|
+
|
|
190
|
+
## TTL Behavior
|
|
191
|
+
|
|
192
|
+
The installed implementation stores a per-entry TTL in the manifest and compares it to the saved timestamp.
|
|
193
|
+
|
|
194
|
+
Important details:
|
|
195
|
+
|
|
196
|
+
- `Cache.ttl` defaults to `600` seconds.
|
|
197
|
+
- `CacheHandler.save_cache(...)` records the `created_at` timestamp and the provided `ttl` value.
|
|
198
|
+
- `CacheHandler.serve_cache(...)` uses the saved TTL when it is greater than `0`.
|
|
199
|
+
- If the saved TTL is `0` or negative, `serve_cache(...)` falls back to its `default_ttl` argument.
|
|
200
|
+
- Expired entries are invalidated automatically and then treated as cache misses.
|
|
201
|
+
|
|
202
|
+
This means `ttl=0` does not mean "cache forever" in the current implementation. It means "use the caller's default TTL fallback."
|
|
203
|
+
|
|
204
|
+
## Upstream Global Config Note
|
|
205
|
+
|
|
206
|
+
The upstream Caspian cache page also describes application-wide environment settings such as `CACHE_ENABLED` and `CACHE_TTL`.
|
|
207
|
+
|
|
208
|
+
Those settings are not parsed inside `casp.cache_handler.py` itself. Treat `Cache(...)` as the route-level override layer and treat any environment-driven defaults as framework configuration that is handled elsewhere in the stack for your specific Caspian version.
|
|
209
|
+
|
|
210
|
+
## Current Implementation Notes
|
|
211
|
+
|
|
212
|
+
- The manifest file name is currently `cache_manifest.json`, not `manifest.json`.
|
|
213
|
+
- `get_filename(uri)` strips the query string before generating the HTML filename.
|
|
214
|
+
- The manifest itself is keyed by the exact URI string passed into `save_cache(...)` and `serve_cache(...)`.
|
|
215
|
+
- Because filenames ignore the query string, different query variants of the same path can map to the same HTML file name.
|
|
216
|
+
- `invalidate_by_uri(...)` normalizes each URI to start with `/`, so use leading-slash URIs consistently.
|
|
217
|
+
- `save_cache(...)`, invalidation, and write failures log to stdout with `[Cache] ...` messages.
|
|
218
|
+
- `reset_cache()` removes files from `caches/` and then rewrites an empty manifest.
|
|
219
|
+
- `Cache(...)` auto-registration only occurs at module scope. Instantiating it inside a function does not declaratively register route cache settings.
|
|
220
|
+
|
|
221
|
+
## Recommended Usage Pattern
|
|
222
|
+
|
|
223
|
+
Validate whether the HTML is shareable first, then add cache configuration close to the route boundary.
|
|
224
|
+
|
|
225
|
+
Common placement patterns are:
|
|
226
|
+
|
|
227
|
+
- module-level `cache_settings = Cache(...)` inside `src/app/**/index.py`
|
|
228
|
+
- explicit invalidation inside `@rpc()` actions or admin flows after a successful write
|
|
229
|
+
- occasional maintenance resets through `CacheHandler.reset_cache()` in operational scripts or debugging sessions
|
|
230
|
+
|
|
231
|
+
Good candidates for page caching are:
|
|
232
|
+
|
|
233
|
+
- landing pages
|
|
234
|
+
- public docs pages
|
|
235
|
+
- blog indexes and published article pages
|
|
236
|
+
- public category or catalog pages whose HTML changes on a predictable cadence
|
|
237
|
+
|
|
238
|
+
Poor candidates are:
|
|
239
|
+
|
|
240
|
+
- authenticated dashboards
|
|
241
|
+
- per-user feeds or notification views
|
|
242
|
+
- forms whose server-rendered HTML includes request-specific or sensitive state
|
|
243
|
+
- pages that need sub-second freshness unless you have reliable invalidation hooks
|
|
244
|
+
|
|
245
|
+
## AI Routing Notes
|
|
246
|
+
|
|
247
|
+
If an AI agent is deciding whether or how to cache a Caspian route, apply these rules first.
|
|
248
|
+
|
|
249
|
+
- Use `Cache` from `casp.cache_handler` for route-level page caching.
|
|
250
|
+
- Prefer `cache_settings = Cache(...)` at module scope over a bare call when writing maintained project code.
|
|
251
|
+
- Use `enabled=False` for pages whose HTML is personalized, auth-sensitive, or too volatile to reuse safely.
|
|
252
|
+
- Use `CacheHandler.invalidate_by_uri(...)` after writes that change cached public content.
|
|
253
|
+
- Use `CacheHandler.reset_cache()` only for targeted maintenance, debugging, or full cache clears.
|
|
254
|
+
- Use leading-slash URIs consistently when interacting with `CacheHandler`.
|
|
255
|
+
- Treat `caches/` and `caches/cache_manifest.json` as framework cache artifacts, not as source files.
|
|
256
|
+
- Pair this page with [fetch-data.md](./fetch-data.md) when deciding how cached first-render HTML relates to interactive RPC updates.
|
|
257
|
+
- Check [routing.md](./routing.md) before deciding where a route's cache declaration belongs.
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Commands
|
|
3
|
+
description: Use the Caspian CLI reference to scaffold projects, generate code, and update framework files without confusing first-time setup with existing-project maintenance.
|
|
4
|
+
related:
|
|
5
|
+
title: Related docs
|
|
6
|
+
description: Start with installation for new apps, then use the routing and structure guides to place generated files correctly.
|
|
7
|
+
links:
|
|
8
|
+
- /docs/installation
|
|
9
|
+
- /docs/database
|
|
10
|
+
- /docs/routing
|
|
11
|
+
- /docs/project-structure
|
|
12
|
+
- /docs/index
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
This page summarizes the main Caspian CLI workflows for creating projects, generating code, and updating an existing app.
|
|
16
|
+
|
|
17
|
+
## Overview
|
|
18
|
+
|
|
19
|
+
Use Caspian CLI commands for three main tasks:
|
|
20
|
+
|
|
21
|
+
- Create a new application.
|
|
22
|
+
- Generate code from your Prisma schema.
|
|
23
|
+
- Update framework-managed project files.
|
|
24
|
+
|
|
25
|
+
Before running update commands, review `caspian.config.json` because it controls overwrite behavior.
|
|
26
|
+
|
|
27
|
+
## Project Creation
|
|
28
|
+
|
|
29
|
+
Use the interactive scaffold when starting a new Caspian app:
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
npx create-caspian-app@latest
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
You can also create a project with starter-kit flags:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
npx create-caspian-app my-app --starter-kit=fullstack
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
For a custom source setup, the CLI also supports a custom starter flow:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npx create-caspian-app my-tool --starter-kit=custom ...
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
After scaffolding, use `routing.md` to understand how Caspian maps `src/app` folders to URLs.
|
|
48
|
+
|
|
49
|
+
## Installation Flags
|
|
50
|
+
|
|
51
|
+
Common scaffold flags include:
|
|
52
|
+
|
|
53
|
+
- `--backend-only` for API-only projects without frontend assets
|
|
54
|
+
- `--tailwindcss` to install Tailwind CSS support
|
|
55
|
+
- `--typescript` to add TypeScript and Vite support
|
|
56
|
+
- `--mcp` to initialize a Model Context Protocol server for AI agents
|
|
57
|
+
- `--prisma` to initialize Prisma ORM support
|
|
58
|
+
|
|
59
|
+
## Code Generation
|
|
60
|
+
|
|
61
|
+
When your Prisma schema changes, use the generation command shown in the Caspian CLI docs:
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
npx ppy generate
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
This flow regenerates the Python Prisma client based on `prisma/schema.prisma`.
|
|
68
|
+
|
|
69
|
+
In Prisma-enabled Caspian apps, this is the step that keeps the shared imports under `src/lib/prisma/` aligned with the schema.
|
|
70
|
+
|
|
71
|
+
See `database.md` for the full Prisma workflow, including `.env`, `prisma.config.ts`, migrations, and async usage patterns.
|
|
72
|
+
|
|
73
|
+
## Update Project
|
|
74
|
+
|
|
75
|
+
Use the project update command for existing Caspian apps:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npx casp update project
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
This command updates framework-managed project files and can overwrite entry points, styles, or configuration files if they are not protected.
|
|
82
|
+
|
|
83
|
+
## Configuration
|
|
84
|
+
|
|
85
|
+
The CLI reads `caspian.config.json` to decide how it should interact with the project.
|
|
86
|
+
|
|
87
|
+
Important configuration areas include:
|
|
88
|
+
|
|
89
|
+
- Project identity and root path
|
|
90
|
+
- Feature toggles such as backend-only, Tailwind, MCP, Prisma, and TypeScript
|
|
91
|
+
- Component scan directories
|
|
92
|
+
- `excludeFiles` rules for protecting local changes during updates
|
|
93
|
+
|
|
94
|
+
## `excludeFiles` Strategy
|
|
95
|
+
|
|
96
|
+
Use `excludeFiles` in `caspian.config.json` to prevent the update command from overwriting files you have customized.
|
|
97
|
+
|
|
98
|
+
This is useful for protecting:
|
|
99
|
+
|
|
100
|
+
- Stylesheets
|
|
101
|
+
- Configuration files
|
|
102
|
+
- Entry-point files
|
|
103
|
+
- Other locally modified framework-managed files
|
|
104
|
+
|
|
105
|
+
If you exclude a file, it will be preserved during updates, but you may need to merge future framework changes into that file manually.
|
|
106
|
+
|
|
107
|
+
## AI Routing Notes
|
|
108
|
+
|
|
109
|
+
If an AI agent is deciding which command flow to use, apply these rules first.
|
|
110
|
+
|
|
111
|
+
- Use `npx create-caspian-app@latest` when the user is creating a new project.
|
|
112
|
+
- Use `npx casp update project` only for an existing Caspian project.
|
|
113
|
+
- Read `caspian.config.json` before running update commands.
|
|
114
|
+
- Use `npx ppy generate` after Prisma schema changes.
|
|
115
|
+
- Check `database.md` when the task involves Prisma setup, schema updates, or generated client files under `src/lib/prisma/`.
|
|
116
|
+
- Check [routing.md](./routing.md) before generating or modifying route folders under `src/app/`.
|
|
117
|
+
- Check [project-structure.md](./project-structure.md) before placing generated files into the project.
|