caspian-utils 0.0.13 → 0.0.15
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/commands.md +5 -1
- package/dist/docs/components.md +3 -1
- package/dist/docs/database.md +13 -0
- package/dist/docs/fetch-data.md +53 -11
- package/dist/docs/file-uploads.md +171 -0
- package/dist/docs/index.md +9 -5
- package/dist/docs/installation.md +4 -0
- package/dist/docs/project-structure.md +33 -3
- package/dist/docs/pulsepoint.md +2 -0
- package/dist/docs/routing.md +3 -0
- package/dist/docs/validation.md +2 -0
- package/package.json +1 -1
package/dist/docs/commands.md
CHANGED
|
@@ -8,6 +8,7 @@ related:
|
|
|
8
8
|
- /docs/installation
|
|
9
9
|
- /docs/database
|
|
10
10
|
- /docs/mcp
|
|
11
|
+
- /docs/file-uploads
|
|
11
12
|
- /docs/routing
|
|
12
13
|
- /docs/project-structure
|
|
13
14
|
- /docs/index
|
|
@@ -19,7 +20,7 @@ This page documents the current Caspian command families used with this workspac
|
|
|
19
20
|
|
|
20
21
|
The current workspace includes a local `prisma` binary, but it does not include local `create-caspian-app`, `casp`, or `ppy` binaries under `node_modules/.bin`. Treat project creation, project update, and Python ORM generation as external `npx` workflows rather than project-local executables.
|
|
21
22
|
|
|
22
|
-
The current workspace `package.json` defines `projectName`, `tailwind`, `tailwind:build`, `browserSync`, `browserSync:build`, `dev`, and `build`.
|
|
23
|
+
The current workspace `package.json` defines `projectName`, `tailwind`, `tailwind:build`, `mcp`, `browserSync`, `browserSync:build`, `dev`, and `build`.
|
|
23
24
|
|
|
24
25
|
Examples below use `npx create-caspian-app` for readability. If you want to force the latest published scaffold package explicitly, you can use `npx create-caspian-app@latest` instead.
|
|
25
26
|
|
|
@@ -83,6 +84,8 @@ Use when the user explicitly wants the local BrowserSync plus PostCSS developmen
|
|
|
83
84
|
|
|
84
85
|
In this workspace, `npm run dev` is a long-running command that can regenerate framework-owned outputs such as `public/css/styles.css`, `settings/component-map.json`, `settings/files-list.json`, `__pycache__/`, and `.pyc` files.
|
|
85
86
|
|
|
87
|
+
Because runtime uploads write to `public/assets/file-manager/`, `settings/bs-config.ts` keeps that directory in `PUBLIC_IGNORE_DIRS` so uploads do not trigger BrowserSync reloads.
|
|
88
|
+
|
|
86
89
|
### Build generated assets for deployment
|
|
87
90
|
|
|
88
91
|
```bash
|
|
@@ -117,6 +120,7 @@ Use when `prisma/schema.prisma` changes and you need migrations, seed flow, and
|
|
|
117
120
|
- Use `npm run build` only for deployment prep or an explicit build request.
|
|
118
121
|
- Treat `public/css/styles.css`, `settings/component-map.json`, `settings/files-list.json`, `__pycache__/`, and `.pyc` files as generated outputs when a script intentionally runs.
|
|
119
122
|
- Analyze `settings/component-map.json` and `settings/files-list.json` when needed, but do not hand-edit them. `settings/component-map.ts` and `settings/files-list.ts` regenerate them during the intentional dev and build flows.
|
|
123
|
+
- Keep runtime upload directories such as `public/assets/file-manager` in `settings/bs-config.ts` `PUBLIC_IGNORE_DIRS` so BrowserSync does not reload on every uploaded blob.
|
|
120
124
|
- Do not edit `__pycache__/` directories or `.pyc` files, and do not leave them in the final diff.
|
|
121
125
|
|
|
122
126
|
## 3. Supported Flags And Options
|
package/dist/docs/components.md
CHANGED
|
@@ -18,12 +18,14 @@ Import them into a template with an `@import` comment, then render them with JSX
|
|
|
18
18
|
|
|
19
19
|
For the current workspace, component tooling scans Python files under the paths listed in `caspian.config.json`. Right now that means `src/`, so `src/components/` is the clean default location for reusable UI, even though any scanned path under `src/` can work.
|
|
20
20
|
|
|
21
|
+
As the app grows, treat `src/components/` as the default home for reusable application UI. Keep route-owned markup in `src/app/`, and keep non-UI helpers or services in `src/lib/`.
|
|
22
|
+
|
|
21
23
|
## Mental Model
|
|
22
24
|
|
|
23
25
|
- Use a Python component when you want a reusable server-rendered UI building block.
|
|
24
26
|
- Return an HTML string directly for small presentational components.
|
|
25
27
|
- Use `render_html(...)` with a same-name `.html` file when the component has more markup, PulsePoint behavior, or clearer separation between Python logic and UI.
|
|
26
|
-
- Keep page-level workflows in `src/app/`,
|
|
28
|
+
- Keep page-level workflows in `src/app/`, move reusable UI into `src/components/`, and keep helpers, services, validators, and adapters in `src/lib/`.
|
|
27
29
|
|
|
28
30
|
## Basic Component
|
|
29
31
|
|
package/dist/docs/database.md
CHANGED
|
@@ -273,6 +273,18 @@ async def create_user(email: str, name: str | None = None):
|
|
|
273
273
|
|
|
274
274
|
Use validation before writes, especially for form payloads and public RPC actions. See `validation.md` for the recommended boundary checks.
|
|
275
275
|
|
|
276
|
+
## Upload Metadata Pattern
|
|
277
|
+
|
|
278
|
+
When a Caspian file manager needs durable metadata, keep the blob and the metadata in separate layers.
|
|
279
|
+
|
|
280
|
+
- Write the uploaded blob to disk or object storage.
|
|
281
|
+
- Persist the durable metadata in Prisma.
|
|
282
|
+
- Store fields such as owner relation, original name, stored name, asset path, MIME type, collection, kind, size, and uploaded timestamp in the Prisma model.
|
|
283
|
+
- Remove both the stored blob and the Prisma row during delete flows.
|
|
284
|
+
- Do not use JSON manifests as the primary metadata store when Prisma is enabled.
|
|
285
|
+
|
|
286
|
+
See [file-uploads.md](./file-uploads.md) for the route-local RPC plus public asset storage pattern.
|
|
287
|
+
|
|
276
288
|
## Advanced Features
|
|
277
289
|
|
|
278
290
|
### Aggregations
|
|
@@ -338,6 +350,7 @@ If an AI agent is working on a Caspian app with Prisma enabled, apply these rule
|
|
|
338
350
|
- Never hand-edit generated Prisma or Python ORM classes.
|
|
339
351
|
- Read `prisma.config.ts` and `prisma/seed.ts` when you need the current workspace's Prisma tooling examples.
|
|
340
352
|
- Reuse the existing `src/lib/prisma/` package when the Python app needs database access.
|
|
353
|
+
- For file managers and uploads, persist metadata in Prisma and keep blob storage separate. See [file-uploads.md](./file-uploads.md).
|
|
341
354
|
- Put reusable database helpers in `src/lib/`; keep route and RPC orchestration in `src/app/`.
|
|
342
355
|
- Use `async def page()` for first-render reads. Keep `layout()` synchronous in the current runtime, and use `@rpc()` plus `pp.rpc()` for browser-triggered reads and writes.
|
|
343
356
|
- Check `fetch-data.md` for route versus RPC guidance and `validation.md` before writing public mutations.
|
package/dist/docs/fetch-data.md
CHANGED
|
@@ -9,6 +9,7 @@ related:
|
|
|
9
9
|
- /docs/mcp
|
|
10
10
|
- /docs/state
|
|
11
11
|
- /docs/database
|
|
12
|
+
- /docs/file-uploads
|
|
12
13
|
- /docs/cache
|
|
13
14
|
- /docs/routing
|
|
14
15
|
- /docs/pulsepoint
|
|
@@ -174,28 +175,68 @@ Use streaming when the user should see partial progress instead of waiting for a
|
|
|
174
175
|
|
|
175
176
|
## File Uploads
|
|
176
177
|
|
|
177
|
-
RPC actions can accept FastAPI upload types.
|
|
178
|
+
RPC actions can accept FastAPI upload types, but the preferred Caspian pattern is route-local upload actions in `src/app/**/index.py`, shared persistence helpers in `src/lib/`, and reactive client updates through `pp.rpc()`.
|
|
178
179
|
|
|
179
|
-
Example:
|
|
180
|
+
Example route-local upload action:
|
|
180
181
|
|
|
181
182
|
```python
|
|
182
183
|
from fastapi import File, UploadFile
|
|
183
184
|
from casp.rpc import rpc
|
|
184
|
-
import shutil
|
|
185
185
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
186
|
+
from src.lib.dashboard.file_manager import (
|
|
187
|
+
build_file_manager_payload,
|
|
188
|
+
save_file_manager_upload,
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
@rpc(require_auth=True)
|
|
192
|
+
async def upload_file(file: UploadFile = File(...), collection: str = "auto"):
|
|
193
|
+
user_id = current_user_id()
|
|
194
|
+
content = await file.read()
|
|
195
|
+
|
|
196
|
+
uploaded = await save_file_manager_upload(
|
|
197
|
+
user_id,
|
|
198
|
+
file_name=file.filename or "file",
|
|
199
|
+
content=content,
|
|
200
|
+
mime_type=file.content_type,
|
|
201
|
+
desired_group=collection,
|
|
202
|
+
)
|
|
190
203
|
|
|
191
204
|
return {
|
|
192
|
-
"
|
|
193
|
-
"
|
|
194
|
-
"
|
|
205
|
+
"success": True,
|
|
206
|
+
"uploaded": uploaded,
|
|
207
|
+
"data": await build_file_manager_payload(user_id),
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Client example:
|
|
212
|
+
|
|
213
|
+
```html
|
|
214
|
+
<script>
|
|
215
|
+
async function uploadSelectedFiles(fileList, collection = "auto") {
|
|
216
|
+
for (const file of Array.from(fileList ?? [])) {
|
|
217
|
+
const response = await pp.rpc("upload_file", { file, collection }, {
|
|
218
|
+
onUploadProgress: (progress) => {
|
|
219
|
+
console.log(progress.percentage ?? 0);
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
if (response?.data) {
|
|
224
|
+
setFileManagerData(response.data);
|
|
225
|
+
}
|
|
195
226
|
}
|
|
227
|
+
}
|
|
228
|
+
</script>
|
|
196
229
|
```
|
|
197
230
|
|
|
198
|
-
|
|
231
|
+
Use this pattern for real file managers:
|
|
232
|
+
|
|
233
|
+
- Keep upload and delete actions in the owning route `index.py`, not in `main.py`.
|
|
234
|
+
- Use `page()` to render the initial manager payload.
|
|
235
|
+
- Store durable metadata in Prisma and store the browser-accessible blob separately under `public/assets/file-manager/`.
|
|
236
|
+
- Use `pp.state(...)` plus `pp-for` for the list UI instead of manual `innerHTML` writes.
|
|
237
|
+
- Add `public/assets/file-manager` to `PUBLIC_IGNORE_DIRS` in `settings/bs-config.ts` so runtime uploads do not trigger BrowserSync reloads during `npm run dev`.
|
|
238
|
+
|
|
239
|
+
Read [file-uploads.md](./file-uploads.md) for the complete file-manager pattern.
|
|
199
240
|
|
|
200
241
|
## Auth, Roles, And Limits
|
|
201
242
|
|
|
@@ -255,6 +296,7 @@ If an AI agent is choosing how to load data in Caspian, apply these rules first.
|
|
|
255
296
|
- Use `@rpc()` for backend functions that should be callable from the browser.
|
|
256
297
|
- Use `pp.rpc()` for client-side calls; do not prefer older `pp.fetchFunction()` wording.
|
|
257
298
|
- Prefer route-render data plus RPC over inventing parallel REST endpoints for normal Caspian page interactions.
|
|
299
|
+
- Read [file-uploads.md](./file-uploads.md) when the task involves file pickers, upload progress, media libraries, or file-manager UI.
|
|
258
300
|
- Use [cache.md](./cache.md) when a route's initial HTML should be reused across requests and invalidated after writes.
|
|
259
301
|
- Use [state.md](./state.md) when an RPC mutation needs transient request-scoped success or error state outside the direct response payload.
|
|
260
302
|
- Use `onStream` for streamed responses and `onUploadProgress` for upload-aware client calls.
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: File Uploads And File Managers
|
|
3
|
+
description: Build Caspian file upload and file manager flows with route-local `@rpc()` actions, `pp.rpc()`, Prisma metadata, public asset storage, and BrowserSync-safe upload directories.
|
|
4
|
+
related:
|
|
5
|
+
title: Related docs
|
|
6
|
+
description: Use fetch-data for the route versus RPC split, PulsePoint for client runtime behavior, database for Prisma persistence, project structure for file placement, validation for upload guards, and commands for local watcher behavior.
|
|
7
|
+
links:
|
|
8
|
+
- /docs/fetch-data
|
|
9
|
+
- /docs/pulsepoint
|
|
10
|
+
- /docs/database
|
|
11
|
+
- /docs/project-structure
|
|
12
|
+
- /docs/validation
|
|
13
|
+
- /docs/commands
|
|
14
|
+
- /docs/index
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
This page documents the recommended file upload and file manager pattern for this workspace and similar Caspian applications.
|
|
18
|
+
|
|
19
|
+
Treat uploads as normal route behavior. Keep the owning browser UI in the route template, keep upload and delete `@rpc()` actions in the owning route `index.py`, and move reusable storage or persistence helpers into `src/lib/`.
|
|
20
|
+
|
|
21
|
+
## Default Pattern
|
|
22
|
+
|
|
23
|
+
- Keep first-render file manager data in `page()` so the initial HTML already contains the current asset list and storage summary.
|
|
24
|
+
- Keep upload and delete actions in the route's `index.py`; do not move ordinary upload flows into `main.py`.
|
|
25
|
+
- Keep reusable file-manager helpers in `src/lib/`.
|
|
26
|
+
- Store uploaded blobs under `public/assets/file-manager/...` when the files should be browser-accessible.
|
|
27
|
+
- Store durable metadata in Prisma, not in JSON manifests or ad hoc metadata files.
|
|
28
|
+
- Use `pp.state(...)` plus `pp-for` to render and update the file list from returned server payloads.
|
|
29
|
+
- Use `onUploadProgress` only for progress UI; let the RPC return refreshed manager data for the authoritative post-upload state.
|
|
30
|
+
|
|
31
|
+
## Recommended Placement
|
|
32
|
+
|
|
33
|
+
| Concern | Preferred location | Notes |
|
|
34
|
+
| --- | --- | --- |
|
|
35
|
+
| File picker UI, tabs, filters, progress state | `src/app/**/index.html` | Use PulsePoint state and template rendering. |
|
|
36
|
+
| Upload and delete `@rpc()` actions | `src/app/**/index.py` | Keep these route-local so they stay close to the owning page. |
|
|
37
|
+
| Shared storage, normalization, and persistence helpers | `src/lib/**` | Reuse helpers across routes without pushing route behavior into app bootstrap. |
|
|
38
|
+
| Upload metadata model | `prisma/schema.prisma` | Persist owner, file name, MIME type, path, size, collection, and timestamps in Prisma. |
|
|
39
|
+
| Browser-accessible uploaded blobs | `public/assets/file-manager/**` | Keep the public path predictable and derived from stored metadata. |
|
|
40
|
+
| BrowserSync upload ignore | `settings/bs-config.ts` | Keep `public/assets/file-manager` in `PUBLIC_IGNORE_DIRS`. |
|
|
41
|
+
|
|
42
|
+
## Route Flow
|
|
43
|
+
|
|
44
|
+
The normal Caspian file-manager flow is:
|
|
45
|
+
|
|
46
|
+
1. `page()` calls a shared helper such as `build_file_manager_payload(...)` and renders the first payload into the route template.
|
|
47
|
+
2. The route template hydrates that payload into `pp.state(...)`.
|
|
48
|
+
3. The file input calls `pp.rpc(...)` with a `File` object and optional `onUploadProgress` callback.
|
|
49
|
+
4. The route-local `@rpc()` action validates auth, file presence, size, and routing-specific inputs.
|
|
50
|
+
5. A shared helper writes the blob, creates or updates the Prisma row, and returns a serialized asset payload.
|
|
51
|
+
6. The RPC action returns refreshed manager data.
|
|
52
|
+
7. PulsePoint replaces the route state and `pp-for` rerenders the list.
|
|
53
|
+
|
|
54
|
+
## Example Route-Local RPC
|
|
55
|
+
|
|
56
|
+
```python
|
|
57
|
+
from fastapi import File, UploadFile
|
|
58
|
+
from casp.rpc import rpc
|
|
59
|
+
|
|
60
|
+
from src.lib.dashboard.file_manager import (
|
|
61
|
+
build_file_manager_payload,
|
|
62
|
+
save_file_manager_upload,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
@rpc(require_auth=True)
|
|
66
|
+
async def upload_asset(file: UploadFile = File(...), collection: str = "auto"):
|
|
67
|
+
user_id = current_user_id()
|
|
68
|
+
content = await file.read()
|
|
69
|
+
|
|
70
|
+
uploaded = await save_file_manager_upload(
|
|
71
|
+
user_id,
|
|
72
|
+
file_name=file.filename or "file",
|
|
73
|
+
content=content,
|
|
74
|
+
mime_type=file.content_type,
|
|
75
|
+
desired_group=collection,
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
return {
|
|
79
|
+
"success": True,
|
|
80
|
+
"uploaded": uploaded,
|
|
81
|
+
"data": await build_file_manager_payload(user_id),
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
Keep route-specific auth checks, input validation, and final response shape here. Keep file naming, directory choice, and Prisma persistence in the shared helper.
|
|
86
|
+
|
|
87
|
+
## Client Pattern
|
|
88
|
+
|
|
89
|
+
```html
|
|
90
|
+
<section class="files-page">
|
|
91
|
+
<input type="file" multiple onchange="{uploadSelectedFiles(event.target.files)}" />
|
|
92
|
+
|
|
93
|
+
<template pp-for="asset in assets">
|
|
94
|
+
<article key="{asset.id}">
|
|
95
|
+
<a href="{asset.url}">{asset.name}</a>
|
|
96
|
+
</article>
|
|
97
|
+
</template>
|
|
98
|
+
|
|
99
|
+
<script>
|
|
100
|
+
const [fileManagerData, setFileManagerData] = pp.state(initialFileManagerData);
|
|
101
|
+
const assets = fileManagerData.assets ?? [];
|
|
102
|
+
|
|
103
|
+
async function uploadSelectedFiles(fileList) {
|
|
104
|
+
for (const file of Array.from(fileList ?? [])) {
|
|
105
|
+
const response = await pp.rpc("upload_asset", { file }, {
|
|
106
|
+
onUploadProgress: (progress) => {
|
|
107
|
+
console.log(progress.percentage ?? 0);
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
if (response?.data) {
|
|
112
|
+
setFileManagerData(response.data);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
</script>
|
|
117
|
+
</section>
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Prefer this state-driven shape over manual `innerHTML` list painting. In Caspian pages, manual DOM writes are easy to lose when PulsePoint rerenders the owner template.
|
|
121
|
+
|
|
122
|
+
## Persistence Rules
|
|
123
|
+
|
|
124
|
+
When Prisma is enabled, the durable record of an uploaded file should live in the database.
|
|
125
|
+
|
|
126
|
+
- Write the blob to disk or object storage.
|
|
127
|
+
- Write the metadata to Prisma.
|
|
128
|
+
- Derive public URLs from the stored path.
|
|
129
|
+
- On delete, remove both the stored file and its Prisma row.
|
|
130
|
+
- Treat old JSON manifests only as migration input, not as the primary store.
|
|
131
|
+
|
|
132
|
+
Typical metadata fields include:
|
|
133
|
+
|
|
134
|
+
- owner or user relation
|
|
135
|
+
- original file name
|
|
136
|
+
- stored file name
|
|
137
|
+
- asset path
|
|
138
|
+
- MIME type
|
|
139
|
+
- collection or grouping key
|
|
140
|
+
- kind or preview type
|
|
141
|
+
- size in bytes
|
|
142
|
+
- uploaded timestamp
|
|
143
|
+
|
|
144
|
+
## BrowserSync And Uploaded Public Files
|
|
145
|
+
|
|
146
|
+
If runtime uploads write into `public/assets/file-manager/`, BrowserSync should ignore that directory during local development. Otherwise every upload can trigger a full browser reload.
|
|
147
|
+
|
|
148
|
+
Use a workspace-relative ignore entry in `settings/bs-config.ts`:
|
|
149
|
+
|
|
150
|
+
```ts
|
|
151
|
+
const PUBLIC_IGNORE_DIRS = ["public/assets/file-manager"];
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Match those entries against workspace-relative paths so nested uploads such as `public/assets/file-manager/user-1/media/example.png` are ignored too.
|
|
155
|
+
|
|
156
|
+
## What To Avoid
|
|
157
|
+
|
|
158
|
+
- Do not add ordinary upload routes or file-manager glue to `main.py`.
|
|
159
|
+
- Do not use JSON files under `storage/` as the active metadata store when Prisma is enabled.
|
|
160
|
+
- Do not treat `onUploadProgress` callbacks as the source of truth for the final asset list.
|
|
161
|
+
- Do not manually repaint the file list with `innerHTML` when PulsePoint state can own the list.
|
|
162
|
+
- Do not leave uploaded public directories out of BrowserSync ignore rules.
|
|
163
|
+
|
|
164
|
+
## AI Routing Notes
|
|
165
|
+
|
|
166
|
+
- Read this page first when the task mentions uploads, file pickers, file managers, media libraries, or upload progress UI.
|
|
167
|
+
- Use `fetch-data.md` for the route-render versus RPC split.
|
|
168
|
+
- Use `database.md` when Prisma models or relations must change for upload metadata.
|
|
169
|
+
- Use `validation.md` for MIME, extension, and other boundary checks, then keep explicit size and auth checks in the owning RPC action.
|
|
170
|
+
- Use `project-structure.md` for placement rules, especially `src/app/` versus `src/lib/` and `public/assets/file-manager/`.
|
|
171
|
+
- Use `commands.md` and `settings/bs-config.ts` when uploads should not trigger BrowserSync reloads during `npm run dev`.
|
package/dist/docs/index.md
CHANGED
|
@@ -8,6 +8,7 @@ related:
|
|
|
8
8
|
- /docs/installation
|
|
9
9
|
- /docs/commands
|
|
10
10
|
- /docs/mcp
|
|
11
|
+
- /docs/file-uploads
|
|
11
12
|
- /docs/project-structure
|
|
12
13
|
- /docs/components
|
|
13
14
|
---
|
|
@@ -46,12 +47,13 @@ The packaged Caspian docs distributed by the current toolchain also live here:
|
|
|
46
47
|
- `components.md` - Create reusable Python components, template-backed UI, JSX-style imports, and the single-parent root rule for component HTML files
|
|
47
48
|
- `pulsepoint.md` - Default reactive frontend runtime contract for component scripts, state, effects, directives, and client-side behaviors
|
|
48
49
|
- `fetch-data.md` - Initial server-side data loading and browser-triggered RPC flows with `pp.rpc()`, streaming, uploads, and auth-aware actions
|
|
50
|
+
- `file-uploads.md` - Route-local file uploads and file-manager flows with `@rpc()`, `pp.rpc()`, Prisma metadata, public asset storage, and BrowserSync ignore rules
|
|
49
51
|
- `state.md` - Request-scoped server state with `StateManager`, session-backed JSON persistence, and listener callbacks for transient flows
|
|
50
52
|
- `cache.md` - Route-level HTML caching with `Cache`, `CacheHandler`, TTL behavior, file-system storage, and invalidation patterns
|
|
51
53
|
- `validation.md` - Input validation and sanitization with `Validate`, `Rule`, direct field checks, and multi-rule workflows for routes and RPC actions
|
|
52
54
|
- `metadata.md` - Static and dynamic metadata, SEO inheritance, and Open Graph or Twitter card tags
|
|
53
55
|
- `routing.md` - Next.js App Router-style file-based routing with `src/app`, dynamic segments, route groups, nested layouts, and single-root route templates
|
|
54
|
-
- `project-structure.md` - Default Caspian layout and where
|
|
56
|
+
- `project-structure.md` - Default Caspian layout and where route files, reusable UI in `src/components/`, reusable non-UI code in `src/lib/`, and database files belong
|
|
55
57
|
|
|
56
58
|
## AI Awareness Notes
|
|
57
59
|
|
|
@@ -66,10 +68,12 @@ Preferred lookup order:
|
|
|
66
68
|
5. Treat generated outputs such as `public/css/styles.css`, `settings/component-map.json`, `settings/files-list.json`, `__pycache__/`, and `.pyc` files as framework-managed artifacts when the local stack is intentionally running. They are not authored source files and should not be kept in the final diff unless the task explicitly requires them.
|
|
67
69
|
6. Analyze `settings/component-map.json` and `settings/files-list.json` when you need the current generated view of components or routes, but do not hand-edit them. The framework regenerates them through `settings/component-map.ts` and `settings/files-list.ts` when the dev or build pipeline intentionally runs.
|
|
68
70
|
7. Read `database.md` only when `caspian.config.json` enables Prisma, read `mcp.md` only when `caspian.config.json` enables MCP, and use `auth.md`, `components.md`, `pulsepoint.md`, `fetch-data.md`, `state.md`, `cache.md`, and `validation.md` as the next routing docs for those non-flagged concerns.
|
|
69
|
-
8.
|
|
70
|
-
9.
|
|
71
|
-
10.
|
|
72
|
-
11.
|
|
71
|
+
8. Read `file-uploads.md` when the task mentions uploads, file pickers, file managers, media libraries, upload progress, or BrowserSync-safe public upload directories.
|
|
72
|
+
9. As the app grows, standardize on `src/app/` for route-owned files, `src/components/` for reusable rendered UI, and `src/lib/` for reusable non-UI support code such as services, validators, adapters, and shared helpers.
|
|
73
|
+
10. For authored component, route, and layout HTML files, generate exactly one top-level lowercase HTML element. Think React-style single parent wrapper: keep any owned PulsePoint logic in a plain `<script>` inside that root, do not handwrite `pp-component="..."` or `type="text/pp"` because Caspian injects those runtime attributes automatically, and treat `<!-- @import ... -->` comments as file-level directives that belong above the authored root element instead of inside `<div>`, `<section>`, or `<html>`. When several component tags come from one Python file, import them from that exact file path, for example `<!-- @import { Breadcrumb, BreadcrumbItem, BreadcrumbList } from "../components/Breadcrumb.py" -->`.
|
|
74
|
+
11. Prefer local docs before generating code, commands, or migration guidance.
|
|
75
|
+
12. Check `node_modules/caspian-utils/dist/docs/` for packaged Caspian docs when local docs need more detail.
|
|
76
|
+
13. Only fall back to upstream documentation when local and packaged markdown do not cover the topic.
|
|
73
77
|
|
|
74
78
|
## Maintenance
|
|
75
79
|
|
|
@@ -7,6 +7,7 @@ related:
|
|
|
7
7
|
links:
|
|
8
8
|
- /docs/commands
|
|
9
9
|
- /docs/mcp
|
|
10
|
+
- /docs/file-uploads
|
|
10
11
|
- /docs/routing
|
|
11
12
|
- /docs/project-structure
|
|
12
13
|
- /docs/index
|
|
@@ -92,6 +93,8 @@ If `npm run dev` is intentionally running, let that stack own generated outputs
|
|
|
92
93
|
|
|
93
94
|
Inspect `settings/component-map.json` and `settings/files-list.json` when you need the generated component or route inventory, but do not hand-edit them. The framework refreshes them from `settings/component-map.ts` and `settings/files-list.ts`.
|
|
94
95
|
|
|
96
|
+
If runtime uploads write into `public/assets/file-manager/`, keep that directory in `settings/bs-config.ts` `PUBLIC_IGNORE_DIRS` so BrowserSync does not reload on every uploaded file.
|
|
97
|
+
|
|
95
98
|
## After Setup
|
|
96
99
|
|
|
97
100
|
Once the project is scaffolded:
|
|
@@ -101,6 +104,7 @@ Once the project is scaffolded:
|
|
|
101
104
|
- Read `auth.md` before choosing public-vs-private route mode, wiring session config, sign-in or signout flows, route guards, or OAuth providers.
|
|
102
105
|
- Read `pulsepoint.md` before generating interactive frontend behavior.
|
|
103
106
|
- Read `fetch-data.md` before adding browser-triggered reads, writes, uploads, or streams.
|
|
107
|
+
- Read `file-uploads.md` before building file pickers, media libraries, or Prisma-backed file-manager flows.
|
|
104
108
|
- Read `validation.md` before handling forms, auth input, or RPC payloads.
|
|
105
109
|
- Read `routing.md` to learn how `src/app` folders map to URLs.
|
|
106
110
|
- Read `project-structure.md` to place route code, shared libraries, config, and database files in the correct directories.
|
|
@@ -12,6 +12,7 @@ related:
|
|
|
12
12
|
- /docs/routing
|
|
13
13
|
- /docs/cache
|
|
14
14
|
- /docs/database
|
|
15
|
+
- /docs/file-uploads
|
|
15
16
|
- /docs/index
|
|
16
17
|
---
|
|
17
18
|
|
|
@@ -21,6 +22,8 @@ This page explains the default layout of a Caspian application, where Caspian co
|
|
|
21
22
|
|
|
22
23
|
Caspian uses a lean project layout that keeps application code in `src`, database files in `prisma`, static assets in `public`, configuration in `caspian.config.json`, and framework internals in the installed package.
|
|
23
24
|
|
|
25
|
+
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.
|
|
26
|
+
|
|
24
27
|
In that layout, the default stack is Python components for reusable UI, PulsePoint in templates for reactive browser behavior, RPC for browser-triggered server calls, and `casp.validate` for input validation at route and action boundaries.
|
|
25
28
|
|
|
26
29
|
For public pages that can safely reuse rendered HTML, Caspian also supports route-level page caching through `casp.cache_handler`.
|
|
@@ -31,12 +34,14 @@ Treat `caspian.config.json` as the single source of truth for optional feature e
|
|
|
31
34
|
|
|
32
35
|
## Top-Level Areas
|
|
33
36
|
|
|
34
|
-
- `src/` contains routes, page templates, styles, and shared libraries.
|
|
35
|
-
- `src/components/` contains reusable
|
|
37
|
+
- `src/` contains routes, page templates, styles, reusable components, and shared libraries.
|
|
38
|
+
- `src/components/` contains reusable application UI components and optional same-name HTML templates.
|
|
39
|
+
- `src/lib/` contains reusable non-UI code such as helpers, services, validators, adapters, and shared support modules.
|
|
36
40
|
- `src/lib/auth/auth_config.py` contains auth-specific configuration for the app.
|
|
37
41
|
- `src/lib/mcp/` contains the app-owned FastMCP server and nested FastMCP config when MCP is enabled.
|
|
38
42
|
- `prisma/` contains the Prisma schema and seed scripts.
|
|
39
43
|
- `public/` contains static assets served directly.
|
|
44
|
+
- `settings/` contains BrowserSync, build, restart, and generated-project helper files.
|
|
40
45
|
- `main.py` is the application entry point.
|
|
41
46
|
- `caspian.config.json` is the core feature configuration file.
|
|
42
47
|
- `.venv/Lib/site-packages/casp/` contains the installed Caspian framework core.
|
|
@@ -51,6 +56,9 @@ my-app/
|
|
|
51
56
|
prisma/
|
|
52
57
|
schema.prisma
|
|
53
58
|
seed.ts
|
|
59
|
+
settings/
|
|
60
|
+
bs-config.ts
|
|
61
|
+
build.ts
|
|
54
62
|
public/
|
|
55
63
|
src/
|
|
56
64
|
app/
|
|
@@ -105,6 +113,8 @@ See `routing.md` for the full App Router-style rules for dynamic segments, route
|
|
|
105
113
|
|
|
106
114
|
Use this folder for reusable UI components that should be imported into route templates or other component templates.
|
|
107
115
|
|
|
116
|
+
As the app grows, default to `src/components/` for application-level UI that will be shared across routes or features. Keep page-only markup close to the route in `src/app/`, but move shared cards, forms, shells, navigation, and other reusable visual building blocks into `src/components/`.
|
|
117
|
+
|
|
108
118
|
The common Caspian pattern is a Python file such as `Button.py` with `@component`, optionally paired with a same-name HTML file such as `Button.html` when the component has richer markup or PulsePoint behavior.
|
|
109
119
|
|
|
110
120
|
One Python file can also export multiple related `@component` functions. When that happens, import those tags from that exact file path in HTML, for example `<!-- @import { Breadcrumb, BreadcrumbItem, BreadcrumbList } from "../components/Breadcrumb.py" -->`, instead of assuming each tag has its own sibling `.py` file.
|
|
@@ -117,7 +127,11 @@ This workspace's component tooling scans `src/` based on `caspian.config.json`,
|
|
|
117
127
|
|
|
118
128
|
### `src/lib/`
|
|
119
129
|
|
|
120
|
-
Use this folder for shared helpers, reusable validators, RPC-facing service wrappers,
|
|
130
|
+
Use this folder for shared helpers, reusable validators, RPC-facing service wrappers, data-access helpers, formatting utilities, and other app-level support code that is not itself a reusable rendered component.
|
|
131
|
+
|
|
132
|
+
If the code is primarily rendered UI that will be imported as a component tag, prefer `src/components/`. If the code is a helper, service, adapter, validator, or other non-visual support module, prefer `src/lib/`.
|
|
133
|
+
|
|
134
|
+
For file upload and manager flows, keep route-owned `@rpc()` actions in `src/app/**/index.py` and keep shared storage, naming, filesystem, and Prisma-backed persistence helpers in `src/lib/`.
|
|
121
135
|
|
|
122
136
|
This workspace already includes an app-owned Python database layer under `src/lib/prisma/`. Reuse that package for Python-side data access and keep any additional shared database helpers in `src/lib/`.
|
|
123
137
|
|
|
@@ -154,6 +168,10 @@ This folder contains your database model definitions in `schema.prisma` and any
|
|
|
154
168
|
|
|
155
169
|
Store static assets here, including images, fonts, and generated frontend assets that should be served directly.
|
|
156
170
|
|
|
171
|
+
Runtime-uploaded public blobs can also live here. In this workspace, file-manager uploads are stored under `public/assets/file-manager/`.
|
|
172
|
+
|
|
173
|
+
If the local BrowserSync stack is running, keep that upload directory in `settings/bs-config.ts` `PUBLIC_IGNORE_DIRS` so new uploads do not force a full browser reload.
|
|
174
|
+
|
|
157
175
|
## Key Files
|
|
158
176
|
|
|
159
177
|
### `main.py`
|
|
@@ -179,6 +197,12 @@ AI agents should read this file before making almost any feature-level decision.
|
|
|
179
197
|
|
|
180
198
|
In the current workspace, `caspian.config.json` shows `backendOnly: false`, `tailwindcss: true`, `mcp: false`, `prisma: true`, `typescript: false`, and `componentScanDirs: ["src"]`.
|
|
181
199
|
|
|
200
|
+
### `settings/bs-config.ts`
|
|
201
|
+
|
|
202
|
+
The BrowserSync watcher configuration for the local stack lives here.
|
|
203
|
+
|
|
204
|
+
When runtime uploads write into `public/assets/file-manager/`, keep `public/assets/file-manager` in `PUBLIC_IGNORE_DIRS` and match it against workspace-relative paths so nested uploaded files do not trigger reloads.
|
|
205
|
+
|
|
182
206
|
### `src/lib/auth/auth_config.py`
|
|
183
207
|
|
|
184
208
|
The project auth configuration file. Use this path when changing authentication behavior.
|
|
@@ -203,6 +227,8 @@ If this layout imports reusable components, place each `<!-- @import ... -->` co
|
|
|
203
227
|
|
|
204
228
|
The backend logic for the route. This is where route behavior can load first-render data, expose `@rpc()` actions, and import framework features such as auth helpers, `casp.validate`, and route-level `Cache(...)` declarations.
|
|
205
229
|
|
|
230
|
+
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`.
|
|
231
|
+
|
|
206
232
|
### `src/app/index.html`
|
|
207
233
|
|
|
208
234
|
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.
|
|
@@ -241,12 +267,16 @@ If an AI agent is deciding where to make changes, use these rules first.
|
|
|
241
267
|
- Treat `__pycache__/` directories, `.pyc` files, `public/css/styles.css`, `settings/component-map.json`, and `settings/files-list.json` as generated artifacts when the local stack is intentionally running. They are not authored source files.
|
|
242
268
|
- Inspect `settings/component-map.json` and `settings/files-list.json` when you need the generated component or route inventory, but do not hand-edit them. The workspace regenerates them from `settings/component-map.ts` and `settings/files-list.ts`.
|
|
243
269
|
- Put route templates and route-specific backend logic in `src/app/`.
|
|
270
|
+
- As the app grows, keep route-owned code in `src/app/`, reusable rendered UI in `src/components/`, and reusable non-UI support code in `src/lib/`.
|
|
271
|
+
- Read [file-uploads.md](./file-uploads.md) when the task involves upload widgets, media libraries, or file-manager flows.
|
|
244
272
|
- Check [routing.md](./routing.md) when you need URL segment rules, layout nesting behavior, or dynamic route conventions.
|
|
245
273
|
- Put reusable component files in `src/components/` and check [components.md](./components.md) for `@component`, `render_html(__file__)`, import comments, and single-root template rules.
|
|
274
|
+
- When deciding between `src/components/` and `src/lib/`, use `src/components/` for anything rendered as reusable UI and `src/lib/` for helpers, services, validators, adapters, and shared business logic.
|
|
246
275
|
- Use [mcp.md](./mcp.md) only when `caspian.config.json` enables MCP and the task involves FastMCP tool definitions, nested config discovery, or local MCP commands.
|
|
247
276
|
- Keep `<!-- @import ... -->` comments above the single authored root element in route, layout, and component HTML files.
|
|
248
277
|
- For route and component HTML files, always emit one top-level lowercase HTML element. Good: one wrapper containing the content and a plain `<script>` when needed. Bad: a wrapper element followed by a sibling top-level `<script>`, or handwritten `pp-component="..."` and `type="text/pp"` attributes in source.
|
|
249
278
|
- Put shared helpers and reusable libraries in `src/lib/`.
|
|
279
|
+
- Use `settings/bs-config.ts` when uploaded public assets should not trigger BrowserSync reloads during the local stack.
|
|
250
280
|
- Put app-owned FastMCP code in `src/lib/mcp/` only when `caspian.config.json` enables MCP.
|
|
251
281
|
- Use PulsePoint conventions in route templates for reactive frontend behavior.
|
|
252
282
|
- Use `@rpc()` in route/backend code and `pp.rpc()` in client code for browser-triggered data flows.
|
package/dist/docs/pulsepoint.md
CHANGED
|
@@ -376,6 +376,7 @@ RPC notes:
|
|
|
376
376
|
- Passing `true` as the third argument means `abortPrevious: true`.
|
|
377
377
|
- The options object supports `abortPrevious`, `onStream`, `onStreamError`, `onStreamComplete`, `onUploadProgress`, and `onUploadComplete`.
|
|
378
378
|
- File uploads switch to the XHR path when upload progress callbacks are needed.
|
|
379
|
+
- For file managers, use upload callbacks for progress UI but replace the asset list from returned RPC state with `pp.state(...)` and `pp-for` instead of manual DOM repainting. See [file-uploads.md](./file-uploads.md).
|
|
379
380
|
- Streamed `text/event-stream` responses are supported when a stream handler is provided.
|
|
380
381
|
- Redirect headers are honored through `pp.redirect()`.
|
|
381
382
|
|
|
@@ -419,6 +420,7 @@ Use these rules when generating or editing PulsePoint runtime code:
|
|
|
419
420
|
- Use native `on*` attributes, not framework-specific event syntax.
|
|
420
421
|
- Use refs and portals only through the implemented `pp` APIs.
|
|
421
422
|
- Use `pp.rpc()` for the bundled runtime API instead of older `pp.fetchFunction()` wording.
|
|
423
|
+
- For upload managers, keep the authoritative asset list in `pp.state(...)` and route uploads through `pp.rpc()` with `onUploadProgress` as needed.
|
|
422
424
|
- Avoid generating internal runtime attributes.
|
|
423
425
|
- Avoid scriptless nested components when the child template contains its own bindings.
|
|
424
426
|
- Prefer authored-template examples over runtime-inspected HTML examples unless the doc is specifically explaining runtime internals.
|
package/dist/docs/routing.md
CHANGED
|
@@ -8,6 +8,7 @@ related:
|
|
|
8
8
|
- /docs/project-structure
|
|
9
9
|
- /docs/components
|
|
10
10
|
- /docs/cache
|
|
11
|
+
- /docs/file-uploads
|
|
11
12
|
- /docs/metadata
|
|
12
13
|
- /docs/pulsepoint
|
|
13
14
|
- /docs/index
|
|
@@ -169,6 +170,8 @@ async def page():
|
|
|
169
170
|
|
|
170
171
|
Use this pattern when the route needs to fetch data, compute metadata, or do other non-blocking server work before rendering.
|
|
171
172
|
|
|
173
|
+
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
|
+
|
|
172
175
|
For static and dynamic metadata rules, inheritance order, and social card fields, see [metadata.md](./metadata.md).
|
|
173
176
|
|
|
174
177
|
If the rendered HTML for that route is public and safe to reuse, declare route-level caching in the same file with `Cache(...)`. See [cache.md](./cache.md).
|
package/dist/docs/validation.md
CHANGED
|
@@ -203,6 +203,8 @@ The installed file includes upload-oriented helpers and rules.
|
|
|
203
203
|
|
|
204
204
|
Use these rules for RPC uploads and form submissions that accept files.
|
|
205
205
|
|
|
206
|
+
Combine them with explicit auth, size, and storage-boundary checks in the owning RPC action before writing files to disk or Prisma. See [file-uploads.md](./file-uploads.md) for the recommended file-manager pattern.
|
|
207
|
+
|
|
206
208
|
## Sanitization
|
|
207
209
|
|
|
208
210
|
Validation in Caspian is more than rule checking. The installed implementation also sanitizes or normalizes several values.
|