create-prisma-php-app 5.1.0-alpha.3 → 5.1.0-alpha.30
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/README.md +23 -2
- package/dist/.github/copilot-instructions.md +80 -33
- package/dist/AGENTS.md +59 -25
- package/dist/bootstrap.php +207 -187
- package/dist/index.js +2 -2
- package/dist/phpunit.xml +25 -0
- package/dist/postcss.config.js +4 -2
- package/dist/public/.htaccess +1 -1
- package/dist/public/js/pp-reactive-v2.min.js +1 -0
- package/dist/settings/bs-config.ts +44 -1
- package/dist/settings/run-postcss.ts +205 -0
- package/dist/settings/run-tests.ts +35 -0
- package/dist/src/Lib/Auth/Auth.php +12 -25
- package/dist/src/Lib/MCP/mcp-server.php +2 -3
- package/dist/src/Lib/Websocket/ConnectionManager.php +500 -47
- package/dist/src/Lib/Websocket/Socket.php +170 -0
- package/dist/src/Lib/Websocket/SocketPool.php +50 -0
- package/dist/src/Lib/Websocket/SocketRegistry.php +88 -0
- package/dist/src/Lib/Websocket/sockets.php +50 -0
- package/dist/src/Lib/Websocket/websocket-server.php +10 -3
- package/dist/src/app/globals.css +3 -1
- package/dist/src/app/layout.php +1 -1
- package/dist/tests/AuthTest.php +59 -0
- package/dist/tests/ConnectionManagerTest.php +277 -0
- package/dist/tests/CsrfTest.php +119 -0
- package/dist/tests/DeferComponentRootsTest.php +147 -0
- package/dist/tests/FeaturesTest.php +41 -0
- package/dist/tests/README.md +119 -0
- package/dist/tests/RpcWireContractTest.php +101 -0
- package/dist/tests/SocketPoolTest.php +69 -0
- package/dist/tests/SocketRegistryTest.php +77 -0
- package/dist/tests/SocketTest.php +124 -0
- package/dist/tests/SocketsRegistrationTest.php +40 -0
- package/dist/tests/Support/FakeConnection.php +62 -0
- package/dist/tests/Support/Features.php +38 -0
- package/dist/tests/Support/RequiresFeature.php +26 -0
- package/dist/tests/bootstrap.php +44 -0
- package/dist/ts/main.ts +5 -8
- package/dist/ts/tailwind-merge.ts +13 -0
- package/package.json +4 -4
- package/dist/public/js/pp-reactive-v2.js +0 -1
package/README.md
CHANGED
|
@@ -36,10 +36,14 @@ If you are using XAMPP on Windows, enabling `extension=zip` in `php.ini` is reco
|
|
|
36
36
|
Prisma PHP brings together the core pieces needed to build full-stack PHP apps:
|
|
37
37
|
|
|
38
38
|
- **Native PHP + modern reactivity** with PulsePoint
|
|
39
|
+
- **Direct RPC from the frontend** with `pp.rpc(...)` calling `#[Exposed]` PHP functions — JSON in, JSON out, SSE streaming when the function yields, and framework failures reported as real HTTP statuses
|
|
40
|
+
- **Named sockets for realtime** with `pp.socket(...)` — long-lived bidirectional messaging (chat, presence, live feeds) served by a Ratchet-based socket server with per-socket auth, origin checks, and rate limits
|
|
39
41
|
- **PHPX component system** for reusable UI composition
|
|
40
42
|
- **Prisma PHP ORM** for schema-first, type-safe database access
|
|
41
43
|
- **Built-in authentication patterns** for sessions, route protection, RBAC, credentials auth, and provider login
|
|
44
|
+
- **Hardened request pipeline** with double-submit CSRF (`pp_csrf` cookie family), origin validation, content-type checks, and per-function rate limiting
|
|
42
45
|
- **File-based routing** with clear route file conventions
|
|
46
|
+
- **App-level test suite** with PHPUnit in a root `tests/` directory, run with `npm run test`, feature-aware via `prisma-php.json`
|
|
43
47
|
- **CLI scaffolding** for new apps, starter kits, and optional features
|
|
44
48
|
- **Flexible deployment options** for local development and production workflows
|
|
45
49
|
|
|
@@ -117,7 +121,10 @@ Use these docs as the main entry points for common work:
|
|
|
117
121
|
- `project-structure.md` for project structure, route placement, and file conventions
|
|
118
122
|
- `layouts-and-pages.md` for pages, layouts, nested routes, and dynamic routes
|
|
119
123
|
- `components.md` for PHPX components, props, children, fragments, icons, buttons, and composition
|
|
120
|
-
- `fetching-data.md` for `pp.
|
|
124
|
+
- `fetching-data.md` for `pp.rpc(...)`, `#[Exposed]`, streaming, and the RPC error contract
|
|
125
|
+
- `websocket.md` for named sockets, `pp.socket(...)`, `SocketRegistry`, and the realtime wire contract
|
|
126
|
+
- `bootstrap-runtime.md` for the runtime init order, PulsePoint wire headers, and the `pp_csrf` CSRF contract
|
|
127
|
+
- `testing.md` for the root `tests/` directory, `npm run test`, and feature-gated tests
|
|
121
128
|
- `prisma-php-orm.md` for Prisma ORM, `schema.prisma`, migrations, and generated PHP classes
|
|
122
129
|
- `authentication.md` for auth strategy, sessions, RBAC, credentials auth, and provider flows
|
|
123
130
|
- `file-manager.md` for uploads, `multipart/form-data`, `$_FILES`, and `PP\FileManager\UploadFile`
|
|
@@ -152,13 +159,15 @@ For task-specific route decision rules and framework generation rules, read `AGE
|
|
|
152
159
|
|
|
153
160
|
## PulsePoint and Frontend Reactivity
|
|
154
161
|
|
|
155
|
-
Prisma PHP uses PulsePoint for browser-side reactivity.
|
|
162
|
+
Prisma PHP uses PulsePoint for browser-side reactivity and as the wire between the page and PHP.
|
|
156
163
|
|
|
157
164
|
When working with runtime features such as:
|
|
158
165
|
|
|
159
166
|
- `pp.state`
|
|
160
167
|
- `pp.effect`
|
|
161
168
|
- `pp.ref`
|
|
169
|
+
- `pp.rpc` for frontend-to-PHP calls (with streaming, uploads, and redirects)
|
|
170
|
+
- `pp.socket` for named-socket realtime messaging
|
|
162
171
|
- `pp-for`
|
|
163
172
|
- `pp-spread`
|
|
164
173
|
- `pp-ref`
|
|
@@ -179,11 +188,23 @@ prisma-php-project/
|
|
|
179
188
|
├── public/ # public entry point and assets
|
|
180
189
|
├── settings/ # project configuration
|
|
181
190
|
├── src/ # application source code
|
|
191
|
+
├── tests/ # app-level PHPUnit tests (npm run test)
|
|
182
192
|
├── package.json # frontend/dev scripts
|
|
183
193
|
├── composer.json # PHP dependencies
|
|
194
|
+
├── phpunit.xml # test suite configuration
|
|
184
195
|
└── prisma-php.json # Prisma PHP project capability manifest
|
|
185
196
|
```
|
|
186
197
|
|
|
198
|
+
## Testing
|
|
199
|
+
|
|
200
|
+
App tests live in the root `tests/` directory and run with:
|
|
201
|
+
|
|
202
|
+
```bash
|
|
203
|
+
npm run test
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
The suite runs PHPUnit on the PHP binary configured in `prisma-php.json`, uses a deterministic test environment (the real `.env` is never loaded), and is feature-aware: tests for optional features such as WebSocket skip cleanly when the feature is disabled in `prisma-php.json`. Read `testing.md` in the installed docs and the project's `tests/README.md` for the full contract.
|
|
207
|
+
|
|
187
208
|
## Updating Existing Projects
|
|
188
209
|
|
|
189
210
|
When enabling features or syncing framework-managed project files:
|
|
@@ -7,13 +7,14 @@
|
|
|
7
7
|
- Treat `node_modules/prisma-php/dist/docs` as framework reference docs that teach AI how Prisma PHP works. The presence of a page in that docs folder does not mean the current workspace has that feature enabled.
|
|
8
8
|
- Read the matching doc in `node_modules/prisma-php/dist/docs` before generating or editing framework-specific Prisma PHP code.
|
|
9
9
|
- Expect `AGENTS.md` in the project root and keep it aligned with the installed Prisma PHP docs contract.
|
|
10
|
-
- In the Prisma PHP package source repo, keep `AGENTS.md`, `.github/copilot-instructions.md`, any `.github/instructions/**/*.instructions.md`, and `dist/docs` aligned so the published docs remain correct after install.
|
|
10
|
+
- In the Prisma PHP package source repo, keep the source-repo `AGENTS.md`, `.github/copilot-instructions.md`, any `.github/instructions/**/*.instructions.md`, and source-repo `dist/docs` aligned so the published docs remain correct after install. In consumer apps, the installed docs path is `node_modules/prisma-php/dist/docs`.
|
|
11
11
|
- Do not assume installed consumer apps also ship a root `.github/copilot-instructions.md` unless the generator explicitly creates one.
|
|
12
12
|
- If `.github/instructions/**/*.instructions.md` exists, treat those files as workspace-local task instructions for third-party libraries, component systems, icon packs, and other implementation-specific rules.
|
|
13
13
|
- Before generating or editing code, inspect `.github/instructions/` and read any `*.instructions.md` files that match the current task, named library, target files, or implementation surface.
|
|
14
|
-
-
|
|
14
|
+
- In the Prisma PHP package source repo, keep every `dist/docs/*.md` page AI-discoverable on its own. In consumer apps, those installed docs live at `node_modules/prisma-php/dist/docs/*.md`. The frontmatter description and opening section should clearly say when agents should read that file and which adjacent docs to consult next.
|
|
15
15
|
- When a task maps to an optional feature such as `backendOnly`, `swaggerDocs`, `typescript`, `websocket`, or `mcp`, inspect `./prisma-php.json` first, then read the matching docs page to learn the implementation contract.
|
|
16
|
-
- When docs and project files still leave a runtime gap, inspect the narrow core file that owns the behavior: `TemplateCompiler.php` for HTML fragment compilation and route root scoping, `ImportComponent.php` for imported partials, `MainLayout.php` for metadata and head/footer scripts, `PrismaPHPSettings.php` plus generated settings JSON for component and route maps, `Request.php` for request handling, `Validator.php`/`Rule.php` for validation, and feature-specific files such as `UploadFile.php`, `Mailer.php`, or `Streaming/SSE.php`.
|
|
16
|
+
- When docs and project files still leave a runtime gap, inspect the narrow core file that owns the behavior: `TemplateCompiler.php` for HTML fragment compilation and route root scoping, `PHPX.php` plus `TwMerge.php` for PHPX class composition and frontend `twMerge(...)` emission, `ImportComponent.php` for imported partials, `MainLayout.php` for metadata and head/footer scripts, `PrismaPHPSettings.php` plus generated settings JSON for component and route maps, `Request.php` for request handling, `Validator.php`/`Rule.php` for validation, and feature-specific files such as `UploadFile.php`, `Mailer.php`, or `Streaming/SSE.php`.
|
|
17
|
+
- When validation or rule-builder syntax is involved, read `node_modules/prisma-php/dist/docs/validator.md` first. If method shape is still unclear after that, inspect `vendor/tsnc/prisma-php/src/Rule.php` to confirm which `Rule` methods are static entry points and which methods must be chained on a builder instance.
|
|
17
18
|
|
|
18
19
|
## Workspace Task Instructions
|
|
19
20
|
|
|
@@ -28,9 +29,11 @@
|
|
|
28
29
|
- Keep `src/app` focused on route files, layouts, handlers, and route-scoped partials.
|
|
29
30
|
- Prefer `src/Components` for reusable application UI components shared across pages or layouts.
|
|
30
31
|
- Keep reusable non-UI code such as services, auth, middleware, Prisma classes, and helpers in `src/Lib`.
|
|
32
|
+
- Treat route-private folders such as `src/app/<route>/_components` as an implementation detail for files that stay owned by that route only.
|
|
31
33
|
- Treat `./public/uploads` as the default local public upload directory for file uploads.
|
|
32
34
|
- Treat generated component libraries such as `src/Lib/PHPXUI` and `src/Lib/PPIcons` as library-specific surfaces governed by their manifests and `.github/instructions/*.instructions.md` files.
|
|
33
35
|
- If a partial starts as route-local but becomes shared across the app, move it from `src/app` to `src/Components`.
|
|
36
|
+
- Do not default to creating `src/app/<route>/_components` for app-owned section components such as `HeroSection`, `FormSection`, or `SidebarSection`; prefer `src/Components` unless the user explicitly wants route-local colocation and the files are truly private to that route.
|
|
34
37
|
- Suggest this structure by default when helping users organize growing Prisma PHP apps.
|
|
35
38
|
|
|
36
39
|
## Component Tag Contract
|
|
@@ -43,6 +46,14 @@
|
|
|
43
46
|
- Use mustache values for reactive props, such as `selected-date="{selectedDate}"` and `on-date-select="{setSelectedDate}"`.
|
|
44
47
|
- Write component examples as HTML-first Prisma PHP markup using the current `x-` tag contract.
|
|
45
48
|
|
|
49
|
+
## Tailwind Merge Contract
|
|
50
|
+
|
|
51
|
+
- In Tailwind-enabled Prisma PHP apps, Tailwind utility conflict resolution belongs to the frontend `twMerge(...)` runtime helper.
|
|
52
|
+
- `getMergeClasses(...)` and `PP\PHPX\TwMerge::merge(...)` emit frontend `twMerge(...)` expressions for the browser runtime to resolve.
|
|
53
|
+
- `twMerge(...)` is an app-level browser helper, not a PulsePoint built-in.
|
|
54
|
+
- In TypeScript-enabled apps, Prisma PHP registers that helper from `ts/main.ts`; in non-TypeScript Tailwind apps it is registered from `public/js/main.js` (importing `public/js/tailwind-merge.mjs`). Use `typescript.md` for route usage and `components.md` for PHPX usage.
|
|
55
|
+
- Keep Tailwind merge decisions on the frontend runtime instead of trying to finalize conflicting utility classes in PHP.
|
|
56
|
+
|
|
46
57
|
## Framework-Managed Package Scripts
|
|
47
58
|
|
|
48
59
|
- Prisma PHP can generate `package.json` scripts for BrowserSync, Tailwind, TypeScript, WebSocket, MCP, Swagger docs, and related helpers.
|
|
@@ -50,7 +61,7 @@
|
|
|
50
61
|
- Do not default to telling users to run `npm run tailwind`, `npm run tailwind:build`, `npm run ts:watch`, or `npm run ts:build` after routine file changes, because those are usually orchestrated through the generated top-level scripts.
|
|
51
62
|
- Use `npm run websocket` or `npm run mcp` only when isolating local runtime startup, debugging, or when the project's scripts show those services are not already covered by the normal development flow.
|
|
52
63
|
- Use `npm run create-swagger-docs` only when Swagger or OpenAPI output must be intentionally generated or refreshed.
|
|
53
|
-
- When package-script behavior matters, read `dist/docs/commands.md` first and inspect the actual `package.json` in the target project before assuming which scripts exist.
|
|
64
|
+
- When package-script behavior matters, read `node_modules/prisma-php/dist/docs/commands.md` first and inspect the actual `package.json` in the target project before assuming which scripts exist.
|
|
54
65
|
|
|
55
66
|
## BrowserSync URL Source Of Truth
|
|
56
67
|
|
|
@@ -79,6 +90,7 @@
|
|
|
79
90
|
## Authentication Route Strategy
|
|
80
91
|
|
|
81
92
|
- Prisma PHP defaults to public routes.
|
|
93
|
+
- Auth classes are app-owned under `src/Lib/Auth` in the `Lib\Auth` namespace: `use Lib\Auth\Auth;`, `use Lib\Auth\AuthConfig;`, `use Lib\Auth\AuthRole;` — never `PP\Auth\...`.
|
|
82
94
|
- Choose the route privacy strategy at the start of the app, before creating most routes.
|
|
83
95
|
- If the app will have many public pages, keep the public-default strategy.
|
|
84
96
|
- If the app will have only a few public entry points and most routes should require login, use the private-default strategy.
|
|
@@ -91,20 +103,32 @@
|
|
|
91
103
|
## PulsePoint-First Frontend Rules
|
|
92
104
|
|
|
93
105
|
- In full-stack Prisma PHP apps, treat PulsePoint as the primary JavaScript authoring model for frontend behavior.
|
|
94
|
-
- For page-local interactivity, prefer `index.php` or nested `layout.php` with a plain inline `<script>` that contains PulsePoint state and functions directly, and use `pp.
|
|
106
|
+
- For page-local interactivity, prefer `index.php` or nested `layout.php` with a plain inline `<script>` that contains PulsePoint state and functions directly, and use `pp.rpc(...)` for backend calls.
|
|
95
107
|
- Do not wrap inline PulsePoint code in `DOMContentLoaded`, IIFEs, manual `pp.mount()` calls, or custom scoping/bootstrap helpers. Prisma PHP scopes the component boundary and runs the script for you.
|
|
96
108
|
- Reserve plain browser JavaScript or TypeScript modules for reusable helpers in `ts/`, third-party libraries, low-level browser APIs, or behavior that does not belong inside a PulsePoint component boundary.
|
|
97
|
-
-
|
|
109
|
+
- Do not treat app-registered helpers such as `twMerge(...)` as PulsePoint built-ins; only use them after the relevant Prisma PHP feature flag and entry-file docs confirm they exist.
|
|
110
|
+
- Use `pp-style` whenever inline CSS contains `{...}` interpolation or any other template-driven/reactive value, reserve plain `style` for fully static inline CSS, use `pp-spread="{...attrs}"` for dynamic attribute objects, keep `pp-for` only on `<template>`, and use plain `key` for keyed diffing.
|
|
111
|
+
- Do not generate reactive inline CSS inside a plain `style` attribute such as `style="width: {progress}%";` use `pp-style="width: {progress}%";` instead so editor CSS validation does not flag the source markup as invalid.
|
|
98
112
|
- Use `pp.ref(...)`, `pp-ref`, `pp.portal(...)`, `pp.createContext(...)`, `Context.Provider`, and `pp.context(...)` according to `pulsepoint.md`.
|
|
99
113
|
- Use `value`, `defaultvalue`, and `defaultchecked` form bindings according to `pulsepoint.md`; do not author internal `data-pp-*` runtime attributes.
|
|
100
114
|
|
|
115
|
+
## Runtime Wire Contract
|
|
116
|
+
|
|
117
|
+
- `pp.rpc(functionName, data?, optionsOrAbort?)` is the frontend-to-PHP call API.
|
|
118
|
+
- Every function called through `pp.rpc(...)` must be marked `#[Exposed]` on the PHP side.
|
|
119
|
+
- Framework-level RPC failures (unknown function, auth, roles, CSRF, origin, content type, rate limit, server error) arrive as HTTP error statuses with an `{"error": "..."}` JSON body and reject the `pp.rpc(...)` promise; wrap calls in `try/catch` when the UI reacts to failures. Return routine validation feedback as structured data instead of throwing. Throwing `InvalidArgumentException` in an exposed function is the sanctioned validation crossover: its message reaches the caller as a 400.
|
|
120
|
+
- Streamed responses: an exposed function that yields streams SSE `data:` lines; consume them with `onStream`, `onStreamError`, and `onStreamComplete`.
|
|
121
|
+
- CSRF: the runtime reads the `pp_csrf` cookie family (`pp_csrf_<port>` in development, `pp_csrf` otherwise), managed server-side by `PP\Security\Csrf` and signed with `FUNCTION_CALL_SECRET`.
|
|
122
|
+
- Realtime: use `pp.socket(name, args, handlers)` (named sockets) for long-lived bidirectional flows. Server handlers are registered with `SocketRegistry::register(...)` in `src/Lib/Websocket/sockets.php`; the wire is one endpoint (`/__pulsepoint/ws?name=...`), arguments as the first JSON frame, JSON frames both ways, and `{"error": "..."}` reserved for failures. Do not generate raw `new WebSocket(...)` wiring for app realtime work.
|
|
123
|
+
- Read `node_modules/prisma-php/dist/docs/fetching-data.md`, `bootstrap-runtime.md`, and `websocket.md` for the full contracts.
|
|
124
|
+
|
|
101
125
|
## Route File Conventions
|
|
102
126
|
|
|
103
127
|
- For PulsePoint-aware `index.php` and nested `layout.php`, keep file order as PHP first, then one parent HTML element as the route boundary, then the visible route content inside that boundary, and keep the PulsePoint `<script>` as the last child of that boundary root.
|
|
104
128
|
- `index.php` and nested `layout.php` must render a single parent HTML element. Treat that root like a component boundary rather than loose sibling markup.
|
|
105
129
|
- If the visible page or layout content should stay inside a semantic element such as `<main>`, `<section>`, or `<article>`, wrap it in a neutral parent such as `<div>` so the route boundary can still own the `<script>`.
|
|
106
130
|
- For pages and nested layouts, author a plain single root element and let Prisma PHP inject the PulsePoint `pp-component` scope automatically.
|
|
107
|
-
- Author plain `<script>` tags inside that boundary root when PulsePoint is needed, usually as a sibling of the visible content container instead of nesting the script inside the semantic content element by default. Put the PulsePoint code at the top level of that script. Do not
|
|
131
|
+
- Author plain `<script>` tags inside that boundary root when PulsePoint is needed, usually as a sibling of the visible content container instead of nesting the script inside the semantic content element by default. Put the PulsePoint code at the top level of that script. Never put a `type` attribute on a component script — the runtime only recognizes untyped scripts. Do not add `DOMContentLoaded` wrappers, IIFEs, or manual bootstrap code.
|
|
108
132
|
- Do not leave the route `<script>` outside the route boundary.
|
|
109
133
|
- Only the root `layout.php` should define `<html>`, `<head>`, and `<body>`. When PulsePoint is present, keep `MainLayout::$children;` and any `<script>` inside one clear wrapper.
|
|
110
134
|
|
|
@@ -113,32 +137,55 @@
|
|
|
113
137
|
- Distinguish PHPX class components from `ImportComponent` partials.
|
|
114
138
|
- `ImportComponent` partials must output exactly one root element because Prisma PHP uses that root as the imported component boundary and serializes props there.
|
|
115
139
|
- Do not manually add `pp-component` inside `ImportComponent` partial source; Prisma PHP injects it there.
|
|
116
|
-
- When imported partials need PulsePoint logic, keep the `<script>` inside that same root element and author it as a plain `<script>` tag
|
|
140
|
+
- When imported partials need PulsePoint logic, keep the `<script>` inside that same root element and author it as a plain `<script>` tag with no `type` attribute (the runtime ignores typed scripts), without DOM-ready wrappers or manual bootstrap code.
|
|
141
|
+
|
|
142
|
+
## Validation Rules
|
|
143
|
+
|
|
144
|
+
- Use `PP\Validator` as the backend validation and normalization layer.
|
|
145
|
+
- Prefer the `Rule` builder for rule-based validation.
|
|
146
|
+
- Start `Rule` builders with `Rule::required()`, `Rule::optional()`, or `Rule::make()`.
|
|
147
|
+
- Chain rule methods such as `->min(...)`, `->max(...)`, `->email()`, and `->regex(...)` on that builder instance.
|
|
148
|
+
- Do not generate static calls such as `Rule::max(80)` or `Rule::email()`.
|
|
149
|
+
- For optional constrained fields, use `Rule::optional()->max(80)` or `Rule::make()->max(80)`.
|
|
150
|
+
- Validate in PHP even when the frontend already performs local checks.
|
|
151
|
+
- Return structured validation results for expected failures instead of treating routine invalid input as an uncaught exception.
|
|
152
|
+
- When internals matter, inspect `vendor/tsnc/prisma-php/src/Validator.php` and `vendor/tsnc/prisma-php/src/Rule.php`.
|
|
153
|
+
|
|
154
|
+
## Testing Rules
|
|
155
|
+
|
|
156
|
+
- App tests live in the root `tests/` directory and run with `npm run test` (PHPUnit via `settings/run-tests.ts`, using the PHP binary from `prisma-php.json`). Narrow runs with `npm run test -- --filter <NameOrMethod>`.
|
|
157
|
+
- When adding or changing app behavior with logic worth protecting (exposed-function validation, socket handlers, auth rules, `src/Lib` helpers), add or update the matching `tests/*Test.php` in the same change and run `npm run test` before declaring the work done.
|
|
158
|
+
- Tests cover app-level code and the wire contracts the app depends on; do not test Prisma PHP framework internals from the app suite.
|
|
159
|
+
- Tests of optional features (`websocket`, `mcp`, `swaggerDocs`, `prisma`, ...) must guard on the `prisma-php.json` flag via the `Tests\Support\RequiresFeature` trait (`$this->requireFeature('websocket')` as the first line of `setUp()`), so a disabled feature skips cleanly instead of fataling on missing scaffold classes. Core surfaces (CSRF, wire headers, auth) are never gated.
|
|
160
|
+
- `tests/bootstrap.php` sets a deterministic env (no real `.env`); shared fakes live in `tests/Support` (`Tests\Support\...`). Socket wire tests use `Tests\Support\FakeConnection` and assert frames plus close codes.
|
|
161
|
+
- Read `node_modules/prisma-php/dist/docs/testing.md` and the project's `tests/README.md` before writing tests.
|
|
117
162
|
|
|
118
163
|
## Relevant Docs
|
|
119
164
|
|
|
120
|
-
- Project structure and feature placement: `dist/docs/project-structure.md`
|
|
121
|
-
- CLI project creation and update commands: `dist/docs/commands.md`
|
|
122
|
-
- First-time project installation and local setup: `dist/docs/installation.md`
|
|
123
|
-
- Existing-project upgrades and feature refreshes: `dist/docs/upgrading.md`
|
|
124
|
-
- TypeScript frontend tooling, the `typescript` flag, and `ts/main.ts` registration: `dist/docs/typescript.md`
|
|
125
|
-
- Backend-only API usage and `backendOnly`: `dist/docs/backend-only.md`
|
|
126
|
-
- Route and layout structure: `dist/docs/layouts-and-pages.md`
|
|
127
|
-
- AI integration, provider-backed chat, streaming, and MCP boundary: `dist/docs/get-started-ia.md`
|
|
128
|
-
- Data loading, `#[Exposed]`, and SSE streaming: `dist/docs/fetching-data.md`
|
|
129
|
-
- Bootstrap flow, runtime init order, request initialization, and function-call protection: `dist/docs/bootstrap-runtime.md`
|
|
130
|
-
- PulsePoint runtime rules: `dist/docs/pulsepoint.md`
|
|
131
|
-
- Component and `ImportComponent` rules: `dist/docs/components.md`
|
|
132
|
-
-
|
|
133
|
-
-
|
|
134
|
-
-
|
|
135
|
-
-
|
|
136
|
-
-
|
|
137
|
-
-
|
|
138
|
-
-
|
|
139
|
-
-
|
|
140
|
-
-
|
|
141
|
-
-
|
|
142
|
-
-
|
|
143
|
-
-
|
|
144
|
-
-
|
|
165
|
+
- Project structure and feature placement: `node_modules/prisma-php/dist/docs/project-structure.md`
|
|
166
|
+
- CLI project creation and update commands: `node_modules/prisma-php/dist/docs/commands.md`
|
|
167
|
+
- First-time project installation and local setup: `node_modules/prisma-php/dist/docs/installation.md`
|
|
168
|
+
- Existing-project upgrades and feature refreshes: `node_modules/prisma-php/dist/docs/upgrading.md`
|
|
169
|
+
- TypeScript frontend tooling, the `typescript` flag, and `ts/main.ts` registration: `node_modules/prisma-php/dist/docs/typescript.md`
|
|
170
|
+
- Backend-only API usage and `backendOnly`: `node_modules/prisma-php/dist/docs/backend-only.md`
|
|
171
|
+
- Route and layout structure: `node_modules/prisma-php/dist/docs/layouts-and-pages.md`
|
|
172
|
+
- AI integration, provider-backed chat, streaming, and MCP boundary: `node_modules/prisma-php/dist/docs/get-started-ia.md`
|
|
173
|
+
- Data loading, `#[Exposed]`, and SSE streaming: `node_modules/prisma-php/dist/docs/fetching-data.md`
|
|
174
|
+
- Bootstrap flow, runtime init order, request initialization, and function-call protection: `node_modules/prisma-php/dist/docs/bootstrap-runtime.md`
|
|
175
|
+
- PulsePoint runtime rules: `node_modules/prisma-php/dist/docs/pulsepoint.md`
|
|
176
|
+
- Component and `ImportComponent` rules: `node_modules/prisma-php/dist/docs/components.md`
|
|
177
|
+
- Frontend Tailwind class composition and `twMerge(...)`: `node_modules/prisma-php/dist/docs/components.md`, `node_modules/prisma-php/dist/docs/typescript.md`, and `node_modules/prisma-php/dist/docs/layouts-and-pages.md`
|
|
178
|
+
- Cache behavior and `CacheHandler`: `node_modules/prisma-php/dist/docs/caching.md`
|
|
179
|
+
- Validation rules: `node_modules/prisma-php/dist/docs/validator.md`
|
|
180
|
+
- Prisma ORM schema, migrations, and generated PHP classes: `node_modules/prisma-php/dist/docs/prisma-php-orm.md`
|
|
181
|
+
- Environment variables and `PP\Env` usage: `node_modules/prisma-php/dist/docs/env.md`
|
|
182
|
+
- File uploads and file manager behavior: `node_modules/prisma-php/dist/docs/file-manager.md`
|
|
183
|
+
- Email and SMTP workflows: `node_modules/prisma-php/dist/docs/email.md`
|
|
184
|
+
- WebSocket and realtime behavior: `node_modules/prisma-php/dist/docs/websocket.md`
|
|
185
|
+
- MCP server and tool rules: `node_modules/prisma-php/dist/docs/mcp.md`
|
|
186
|
+
- Authentication: `node_modules/prisma-php/dist/docs/authentication.md`
|
|
187
|
+
- Error handling, expected failures, and route error files: `node_modules/prisma-php/dist/docs/error-handling.md`
|
|
188
|
+
- Metadata and icons: `node_modules/prisma-php/dist/docs/metadata-and-og-images.md`
|
|
189
|
+
- API-style handlers and webhooks: `node_modules/prisma-php/dist/docs/route-handlers.md`
|
|
190
|
+
- Swagger/OpenAPI generation and `swaggerDocs`: `node_modules/prisma-php/dist/docs/swagger-docs.md`
|
|
191
|
+
- App test suite, `tests/` layout, and `npm run test`: `node_modules/prisma-php/dist/docs/testing.md`
|
package/dist/AGENTS.md
CHANGED
|
@@ -35,7 +35,8 @@ Important rules:
|
|
|
35
35
|
- expect `./AGENTS.md` at the project root
|
|
36
36
|
- when the installed docs and a habit from another framework conflict, follow Prisma PHP
|
|
37
37
|
- when a workspace instruction file and the general Prisma PHP docs both apply, follow both; keep `./prisma-php.json` as the source of truth for feature enablement and prefer the most specific matching instruction for library- or file-scoped implementation details
|
|
38
|
-
-
|
|
38
|
+
- in consumer apps, use `./node_modules/prisma-php/dist/docs` as the installed docs location; do not assume a root-level `./dist/docs` directory exists
|
|
39
|
+
- when updating Prisma PHP package/docs sources in the Prisma PHP package source repo, keep the source-repo `AGENTS.md` and source-repo `dist/docs` aligned; if that repo also maintains `.github/copilot-instructions.md` or `.github/instructions/**/*.instructions.md`, keep those source-repo files aligned there too
|
|
39
40
|
|
|
40
41
|
## Runtime lookup for AI
|
|
41
42
|
|
|
@@ -44,10 +45,12 @@ Use this map only after `prisma-php.json`, matching workspace instructions, inst
|
|
|
44
45
|
| Need to verify | Runtime/source file |
|
|
45
46
|
| --- | --- |
|
|
46
47
|
| route root scoping, HTML fragment parsing, component tag compilation, prop casing | `vendor/tsnc/prisma-php/src/PHPX/TemplateCompiler.php` |
|
|
48
|
+
| PHPX class composition, `getMergeClasses(...)`, and frontend `twMerge(...)` expression generation | `vendor/tsnc/prisma-php/src/PHPX/PHPX.php`, `vendor/tsnc/prisma-php/src/PHPX/TwMerge.php` |
|
|
47
49
|
| imported PHP partial execution, one-root enforcement, prop serialization, imported `#[Exposed]` functions | `vendor/tsnc/prisma-php/src/ImportComponent.php` |
|
|
48
50
|
| metadata, custom head tags, dynamic head/footer scripts | `vendor/tsnc/prisma-php/src/MainLayout.php` |
|
|
49
51
|
| route and component maps | `vendor/tsnc/prisma-php/src/PrismaPHPSettings.php`, `settings/files-list.json`, `settings/component-map.json` |
|
|
50
|
-
| request data, dynamic params, redirects,
|
|
52
|
+
| request data, dynamic params, redirects, RPC/navigation wire detection (`$isRpc`, `$isNavigation`, `$isWire`) | `vendor/tsnc/prisma-php/src/Request.php` |
|
|
53
|
+
| CSRF cookie family (`pp_csrf`, `pp_csrf_<port>`), token issuing and validation | `vendor/tsnc/prisma-php/src/Security/Csrf.php` |
|
|
51
54
|
| exposed functions | `vendor/tsnc/prisma-php/src/Attributes/Exposed.php`, `vendor/tsnc/prisma-php/src/Attributes/ExposedRegistry.php` |
|
|
52
55
|
| validation | `vendor/tsnc/prisma-php/src/Validator.php`, `vendor/tsnc/prisma-php/src/Rule.php` |
|
|
53
56
|
| env values | `vendor/tsnc/prisma-php/src/Env.php` |
|
|
@@ -116,10 +119,13 @@ Use the docs router to learn how Prisma PHP implements a task. Use `./prisma-php
|
|
|
116
119
|
- **Creating, editing, composing, or reviewing PHPX components, props, children, fragments, icons, buttons, accordions, or component file placement**
|
|
117
120
|
Read `components.md`
|
|
118
121
|
|
|
122
|
+
- **Tailwind utility class composition, `getMergeClasses(...)`, `PP\PHPX\TwMerge`, or frontend `twMerge(...)` usage**
|
|
123
|
+
Confirm `tailwindcss` in `prisma-php.json`, then read `components.md` for PHPX emission, `typescript.md` for app-level helper registration, and `layouts-and-pages.md` for route examples
|
|
124
|
+
|
|
119
125
|
- **TypeScript frontend tooling, the `typescript` feature flag, the root `ts/` directory, `ts/main.ts`, npm packages, or registered browser helpers used from template expressions and PulsePoint scripts**
|
|
120
126
|
Read `typescript.md`, then use `pulsepoint.md`, `layouts-and-pages.md`, or `components.md` for the affected component boundary
|
|
121
127
|
|
|
122
|
-
- **Loading data, calling backend logic from the frontend, `pp.
|
|
128
|
+
- **Loading data, calling backend logic from the frontend, `pp.rpc(...)`, `#[Exposed]`, route-local mutations, streaming responses, or interactive backend validation**
|
|
123
129
|
Read `fetching-data.md`
|
|
124
130
|
|
|
125
131
|
- **AI integration, provider SDKs, chat UIs, streamed assistant output, or deciding between page-local assistant UI, websocket, and MCP tools**
|
|
@@ -134,7 +140,7 @@ Use the docs router to learn how Prisma PHP implements a task. Use `./prisma-php
|
|
|
134
140
|
- **Environment variables, `.env`, `PP\Env`, `Env::get`, `Env::string`, `Env::bool`, `Env::int`, feature flags, host and port config, or runtime bootstrap settings**
|
|
135
141
|
Read `env.md`, then verify the official env docs at `env` and `env-file`
|
|
136
142
|
|
|
137
|
-
- **Bootstrap flow, request initialization, `FUNCTION_CALL_SECRET`, `
|
|
143
|
+
- **Bootstrap flow, request initialization, `FUNCTION_CALL_SECRET`, `pp_csrf`, route resolution, or runtime init order**
|
|
138
144
|
Read `bootstrap-runtime.md`, then use `env.md`, `fetching-data.md`, or `error-handling.md` as needed
|
|
139
145
|
|
|
140
146
|
- **File uploads, `multipart/form-data`, `$_FILES`, `PP\FileManager\UploadFile`, rename flows, replace flows, delete flows, allowed file types, upload size rules, or file manager UI behavior**
|
|
@@ -143,7 +149,7 @@ Use the docs router to learn how Prisma PHP implements a task. Use `./prisma-php
|
|
|
143
149
|
- **SMTP setup, `.env` mail variables, `PP\PHPMailer\Mailer`, HTML bodies, plain-text bodies, recipients, reply-to, CC, BCC, or attachments**
|
|
144
150
|
Read `email.md`, then verify the official email docs at `email-get-started`
|
|
145
151
|
|
|
146
|
-
- **
|
|
152
|
+
- **Named sockets, `pp.socket(...)`, `SocketRegistry`, `Socket`, `SocketPool`, the Ratchet socket server, or realtime route behavior**
|
|
147
153
|
Read `websocket.md`, then verify the official websocket docs in this order: `websocket-get-started`, `websocket-chat-app`
|
|
148
154
|
|
|
149
155
|
- **MCP support, `#[McpTool]`, `#[Schema]`, `PhpMcp\Server\Server`, `StreamableHttpServerTransport`, AI tool endpoints, or `src/Lib/MCP/mcp-server.php`**
|
|
@@ -167,9 +173,12 @@ Use the docs router to learn how Prisma PHP implements a task. Use `./prisma-php
|
|
|
167
173
|
- **API-style routes, JSON responses, handlers, webhooks, form-processing endpoints, `route.php`, or request validation in handlers**
|
|
168
174
|
Read `route-handlers.md`
|
|
169
175
|
|
|
170
|
-
- **Swagger or OpenAPI generation, `swaggerDocs`,
|
|
176
|
+
- **Swagger or OpenAPI generation, `swaggerDocs`, generated per-model swagger docs, `create-swagger-docs`, or `settings/prisma-schema-config.json`**
|
|
171
177
|
Read `swagger-docs.md`
|
|
172
178
|
|
|
179
|
+
- **Writing or running app tests, PHPUnit, the root `tests/` directory, `npm run test`, or verifying a change with the test suite**
|
|
180
|
+
Read `testing.md`, then the project's `tests/README.md`
|
|
181
|
+
|
|
173
182
|
- **Upgrading Prisma PHP, enabling features, syncing framework-managed project files, or running project updates**
|
|
174
183
|
Read `upgrading.md`
|
|
175
184
|
|
|
@@ -202,6 +211,7 @@ The current Prisma PHP docs shipped here include:
|
|
|
202
211
|
- `pulsepoint.md`
|
|
203
212
|
- `route-handlers.md`
|
|
204
213
|
- `swagger-docs.md`
|
|
214
|
+
- `testing.md`
|
|
205
215
|
- `typescript.md`
|
|
206
216
|
- `upgrading.md`
|
|
207
217
|
- `validator.md`
|
|
@@ -211,7 +221,7 @@ This inventory exists to help AI find the right Prisma PHP guidance quickly. It
|
|
|
211
221
|
|
|
212
222
|
When a task depends on optional capabilities such as `backendOnly`, `swaggerDocs`, `typescript`, `websocket`, or `mcp`, inspect `./prisma-php.json` before assuming the generated scaffold exists.
|
|
213
223
|
|
|
214
|
-
When adding or reviewing AI guidance, do not stop at older docs only. Make sure the guidance also covers `backend-only.md`, `email.md`, `env.md`, `get-started-ia.md`, `mcp.md`, `swagger-docs.md`, `typescript.md`, and `websocket.md`, plus newer behavior documented in `fetching-data.md
|
|
224
|
+
When adding or reviewing AI guidance, do not stop at older docs only. Make sure the guidance also covers `backend-only.md`, `email.md`, `env.md`, `get-started-ia.md`, `mcp.md`, `swagger-docs.md`, `typescript.md`, and `websocket.md`, plus newer behavior documented in `fetching-data.md`, `metadata-and-og-images.md`, and `testing.md`.
|
|
215
225
|
|
|
216
226
|
## Framework-generated files
|
|
217
227
|
|
|
@@ -232,8 +242,10 @@ When organizing a growing Prisma PHP app, keep route code and reusable code sepa
|
|
|
232
242
|
- keep `src/app` focused on the route tree, route-local layouts, pages, handlers, and route-scoped partials
|
|
233
243
|
- prefer `src/Components` for reusable application UI components shared across multiple routes or layouts
|
|
234
244
|
- keep reusable non-UI code such as services, auth, middleware, Prisma classes, and helper libraries in `src/Lib`
|
|
245
|
+
- treat route-private folders such as `src/app/<route>/_components` as an implementation detail for files that stay owned by that route only
|
|
235
246
|
- treat generated libraries such as `src/Lib/PHPXUI` and `src/Lib/PPIcons` as library-specific surfaces governed by their manifests and matching `.github/instructions/**/*.instructions.md` files
|
|
236
247
|
- if a partial starts in `src/app` but becomes shared across the app, promote it into `src/Components`
|
|
248
|
+
- do **not** default to creating `src/app/<route>/_components` for app-owned section components such as `HeroSection`, `FormSection`, or `SidebarSection`; prefer `src/Components` unless the user explicitly wants route-local colocation and the files are truly private to that route
|
|
237
249
|
- do **not** default to placing app-wide reusable components under `src/app` unless the user explicitly wants route-local colocation
|
|
238
250
|
|
|
239
251
|
## HTML-first component tag contract
|
|
@@ -306,15 +318,18 @@ When a task involves Prisma PHP CLI usage, keep the command guidance aligned wit
|
|
|
306
318
|
|
|
307
319
|
For normal full-stack Prisma PHP work, assume the user wants the PulsePoint-first approach unless they explicitly ask otherwise.
|
|
308
320
|
|
|
309
|
-
PulsePoint is the primary JavaScript authoring model for frontend work in Prisma PHP. For normal page behavior, keep the client logic inside a plain inline `<script>` within the route or imported-partial root, let Prisma PHP scope and execute it, and prefer `pp.
|
|
321
|
+
PulsePoint is the primary JavaScript authoring model for frontend work in Prisma PHP. For normal page behavior, keep the client logic inside a plain inline `<script>` within the route or imported-partial root, let Prisma PHP scope and execute it, and prefer `pp.rpc(...)` over ad hoc endpoints.
|
|
310
322
|
|
|
311
323
|
Default interaction stack:
|
|
312
324
|
|
|
313
325
|
1. render route UI with `index.php`
|
|
314
326
|
2. keep browser-side interactivity in PulsePoint
|
|
315
|
-
3. call backend PHP from the frontend with `pp.
|
|
327
|
+
3. call backend PHP from the frontend with `pp.rpc(...)`
|
|
316
328
|
4. mark callable PHP functions or methods with `#[Exposed]`
|
|
317
329
|
5. validate and normalize input on the PHP side with `PP\Validator`
|
|
330
|
+
6. use `pp.socket(...)` (named sockets) only when the flow is genuinely long-lived and bidirectional — chat, presence, live feeds
|
|
331
|
+
|
|
332
|
+
`pp.rpc(...)` is the runtime RPC API. Framework-level RPC failures (unknown function, auth, roles, CSRF, origin, rate limit, server error) arrive as HTTP error statuses with an `{"error": "..."}` body and **reject** the `pp.rpc(...)` promise, so wrap calls in `try/catch` when the UI reacts to failures. Routine, expected validation feedback should still be returned as structured data (`success`, `errors`, normalized values), not thrown.
|
|
318
333
|
|
|
319
334
|
Treat this as the default for:
|
|
320
335
|
|
|
@@ -336,7 +351,7 @@ Do **not** default to:
|
|
|
336
351
|
- a PHP-only interaction style
|
|
337
352
|
- plain browser-DOM wiring when PulsePoint state, bindings, and native `on*` handlers already fit the task
|
|
338
353
|
- ad hoc `fetch('/api/...')` patterns
|
|
339
|
-
- extra `route.php` files for page-local interactions that already fit `pp.
|
|
354
|
+
- extra `route.php` files for page-local interactions that already fit `pp.rpc(...)`
|
|
340
355
|
- a separate Node realtime or tool server when the documented Prisma PHP runtime already fits the task
|
|
341
356
|
|
|
342
357
|
Choose a more PHP-only or handler-only pattern only when:
|
|
@@ -364,7 +379,7 @@ Also follow these route-file rules:
|
|
|
364
379
|
- `index.php` and nested `layout.php` must render a single parent HTML element
|
|
365
380
|
- use that single parent element as the route boundary; if the visible content should stay inside a semantic element such as `<main>`, `<section>`, or `<article>`, wrap it in a neutral parent such as `<div>`
|
|
366
381
|
- for normal pages and nested layouts, do **not** manually author `pp-component` on that root; Prisma PHP adds it automatically
|
|
367
|
-
- author a plain `<script>` tag inside that root when PulsePoint logic is needed and do **not**
|
|
382
|
+
- author a plain `<script>` tag inside that root when PulsePoint logic is needed and do **not** put any `type` attribute on it — the runtime only recognizes untyped component scripts
|
|
368
383
|
- keep the `<script>` as the last child of the route boundary, usually as a sibling of the visible content container instead of nesting it inside the semantic content element by default
|
|
369
384
|
- do **not** leave the `<script>` outside the route boundary
|
|
370
385
|
- write PulsePoint state, derived values, and functions directly at the top level of that script; do **not** wrap them in `DOMContentLoaded`, an IIFE, manual `pp.mount()` calls, or custom scoping helpers
|
|
@@ -424,7 +439,7 @@ Do not:
|
|
|
424
439
|
|
|
425
440
|
- put a sibling `<script>` next to a route root or imported partial root
|
|
426
441
|
- manually add `pp-component` inside imported partial source
|
|
427
|
-
-
|
|
442
|
+
- add any `type` attribute to route or imported-partial component scripts
|
|
428
443
|
- wrap imported-partial PulsePoint code in `DOMContentLoaded`, an IIFE, manual `pp.mount()` calls, or custom auto-execute helpers
|
|
429
444
|
|
|
430
445
|
## Metadata rules
|
|
@@ -440,19 +455,19 @@ Important metadata rules:
|
|
|
440
455
|
|
|
441
456
|
## Streaming and SSE rules
|
|
442
457
|
|
|
443
|
-
Prisma PHP supports streaming through `pp.
|
|
458
|
+
Prisma PHP supports streaming through `pp.rpc(...)` when an exposed function yields values.
|
|
444
459
|
|
|
445
460
|
Default streaming rules:
|
|
446
461
|
|
|
447
462
|
- prefer an exposed generator that simply yields strings or arrays
|
|
448
|
-
- let Prisma PHP handle the SSE response automatically for normal `pp.
|
|
463
|
+
- let Prisma PHP handle the SSE response automatically for normal `pp.rpc(...)` streaming
|
|
449
464
|
- on the client, put stream UI updates in `onStream`, `onStreamError`, and `onStreamComplete`
|
|
450
465
|
- do not wait for a final JSON payload when the response is streamed
|
|
451
466
|
|
|
452
467
|
Current parsing rules AI should know:
|
|
453
468
|
|
|
454
469
|
- Prisma PHP sends streamed payloads as SSE `data:` lines
|
|
455
|
-
- the built-in `pp.
|
|
470
|
+
- the built-in `pp.rpc(...)` stream parser currently forwards only `data:` lines to `onStream`
|
|
456
471
|
- `event:`, `id:`, and `retry:` may be emitted by low-level SSE helpers, but the built-in stream callback currently ignores them
|
|
457
472
|
- prefer JSON values or single-line strings for streamed chunks instead of multi-line text blobs
|
|
458
473
|
|
|
@@ -481,7 +496,7 @@ Important: creating a route means creating or updating the correct folder and ro
|
|
|
481
496
|
- use `error.php` for route or app-level error UI
|
|
482
497
|
- use `loading.php` when the task is specifically about a loading UI state for a route subtree
|
|
483
498
|
|
|
484
|
-
For normal route-local interactivity, prefer `index.php` plus PulsePoint and `pp.
|
|
499
|
+
For normal route-local interactivity, prefer `index.php` plus PulsePoint and `pp.rpc(...)` over inventing extra handlers.
|
|
485
500
|
|
|
486
501
|
In a consumer app, also verify `backendOnly` in `prisma-php.json`:
|
|
487
502
|
|
|
@@ -516,6 +531,7 @@ Use this auth decision flow:
|
|
|
516
531
|
|
|
517
532
|
Important auth rules:
|
|
518
533
|
|
|
534
|
+
- the auth classes are app-owned files under `src/Lib/Auth` in the `Lib\Auth` namespace — write `use Lib\Auth\Auth;` and `use Lib\Auth\AuthConfig;`, never `PP\Auth\...`
|
|
519
535
|
- route privacy strategy is configured from `AuthConfig.php`
|
|
520
536
|
- Prisma PHP supports both public-default and private-default route protection strategies
|
|
521
537
|
- Prisma PHP defaults to public routes, so keep the public-default strategy when the app will expose many public pages
|
|
@@ -610,26 +626,34 @@ Important env rules:
|
|
|
610
626
|
|
|
611
627
|
## WebSocket rules
|
|
612
628
|
|
|
613
|
-
When the task involves realtime messaging, presence, live dashboards, `
|
|
629
|
+
When the task involves realtime messaging, presence, live dashboards, chat, `pp.socket(...)`, or `Ratchet`, read `websocket.md` first.
|
|
614
630
|
|
|
615
|
-
Prisma PHP
|
|
631
|
+
Prisma PHP realtime support is built on **named sockets**: `pp.socket(name, args, handlers)` in the browser, and a Ratchet-based server under `src/Lib/Websocket` that dispatches each connection to a handler registered with `SocketRegistry`. Do not replace that default with Socket.IO, a separate Node server, raw `new WebSocket(...)` wiring, or an unrelated hosted realtime service unless the user explicitly asks for a different architecture.
|
|
616
632
|
|
|
617
633
|
Use this websocket workflow:
|
|
618
634
|
|
|
619
635
|
1. read `websocket.md`
|
|
620
636
|
2. inspect whether websocket support is enabled in `prisma-php.json` in the target app
|
|
621
|
-
3. inspect `src/Lib/Websocket`
|
|
622
|
-
4. inspect the route
|
|
637
|
+
3. inspect `src/Lib/Websocket`, especially `sockets.php` for the registered socket names
|
|
638
|
+
4. inspect the route script that calls `pp.socket(...)`
|
|
623
639
|
5. inspect `settings/restart-websocket.ts` when local restart behavior matters
|
|
624
640
|
6. inspect framework internals only when the docs do not answer the task
|
|
625
641
|
|
|
626
642
|
Important websocket rules:
|
|
627
643
|
|
|
644
|
+
- connect from the browser with `pp.socket(name, args, handlers)`; do **not** generate raw `new WebSocket(...)` wiring for app realtime work
|
|
645
|
+
- register server handlers with `SocketRegistry::register(...)` in `src/Lib/Websocket/sockets.php`; socket names are unique application-wide
|
|
646
|
+
- do not put socket handlers in route files — route files are not loaded by the socket server process
|
|
647
|
+
- keep the wire contract intact: one endpoint (`/__pulsepoint/ws`), the function named in the `name` query parameter, arguments as the connection's first JSON frame, one JSON value per frame in either direction, and `{"error": "..."}` (that key alone) reserved for failures
|
|
628
648
|
- use `src/Lib/Websocket/websocket-server.php` as the source of truth for startup behavior
|
|
629
|
-
- use `src/Lib/Websocket/ConnectionManager.php` as the lifecycle boundary
|
|
630
|
-
-
|
|
649
|
+
- use `src/Lib/Websocket/ConnectionManager.php` as the wire and lifecycle boundary (handshake security, argument frame, dispatch, limits)
|
|
650
|
+
- use `SocketPool` for broadcasts; keep authenticated and guest traffic in separate pools
|
|
651
|
+
- declare auth with `requireAuth` / `allowedRoles` at registration; the handshake is verified against the JWT auth cookie before the handler runs
|
|
652
|
+
- a `Socket::send(...)` that returns `false` means the browser is gone — stop sending, it is not an error
|
|
653
|
+
- preserve documented env vars and defaults: `WS_NAME`, `WS_VERSION`, `WS_HOST`, `WS_PORT`, `WS_VERBOSE`, `APP_TIMEZONE`, `MAX_WEBSOCKET_CONNECTIONS`, `MAX_WEBSOCKET_MESSAGE_BYTES`, `MAX_WEBSOCKET_MESSAGES_PER_WINDOW`, `WEBSOCKET_RATE_WINDOW_SECONDS`, `WEBSOCKET_IDLE_TIMEOUT_SECONDS`, `WEBSOCKET_ALLOWED_ORIGINS`
|
|
631
654
|
- preserve CLI overrides through `--host=...`, `--port=...`, and `--verbose=...`
|
|
632
655
|
- preserve the documented casing `src/Lib/Websocket`
|
|
656
|
+
- in development, `settings/bs-config.ts` proxies `/__pulsepoint/ws` from the BrowserSync origin to the Ratchet server, so `pp.socket(...)` needs no `url` option; pass `url` only outside that proxy
|
|
633
657
|
- for existing apps, enable `websocket` in `prisma-php.json` and run `npx pp update project -y` before inventing manual scaffolding
|
|
634
658
|
|
|
635
659
|
## MCP rules
|
|
@@ -681,12 +705,15 @@ Important ORM rules:
|
|
|
681
705
|
|
|
682
706
|
## Validation rules
|
|
683
707
|
|
|
684
|
-
When a task involves user input, form handling, search params, JSON payloads, `pp.
|
|
708
|
+
When a task involves user input, form handling, search params, JSON payloads, `pp.rpc(...)`, `route.php` bodies, or tool parameters, do not trust raw values.
|
|
685
709
|
|
|
686
710
|
Default Prisma PHP validation rules:
|
|
687
711
|
|
|
688
712
|
- use `PP\Validator` as the backend validation and normalization layer
|
|
689
713
|
- prefer the `Rule` builder for rule-based validation
|
|
714
|
+
- start `Rule` builders with `Rule::required()`, `Rule::optional()`, or `Rule::make()`
|
|
715
|
+
- chain rule methods such as `->min(...)`, `->max(...)`, `->email()`, and `->regex(...)` on that builder instance
|
|
716
|
+
- do **not** generate static calls such as `Rule::max(80)`; for optional constrained fields use `Rule::optional()->max(80)` or `Rule::make()->max(80)`
|
|
690
717
|
- validate in PHP even when the frontend already performs local checks
|
|
691
718
|
- return structured validation results for expected failures
|
|
692
719
|
- do not treat routine invalid input as an uncaught exception
|
|
@@ -696,6 +723,7 @@ When internals matter, the documented Prisma PHP core validator location is:
|
|
|
696
723
|
|
|
697
724
|
```txt
|
|
698
725
|
vendor/tsnc/prisma-php/src/Validator.php
|
|
726
|
+
vendor/tsnc/prisma-php/src/Rule.php
|
|
699
727
|
```
|
|
700
728
|
|
|
701
729
|
## PulsePoint rules
|
|
@@ -706,13 +734,15 @@ Also follow these rules:
|
|
|
706
734
|
|
|
707
735
|
- treat PulsePoint as the primary JavaScript authoring model for normal full-stack frontend work
|
|
708
736
|
- keep page and imported-partial client logic inside the boundary's plain `<script>` tag instead of building extra DOM-ready or self-executing wrappers
|
|
709
|
-
- prefer `pp.
|
|
737
|
+
- prefer `pp.rpc(...)` over ad hoc `fetch('/api/...')` calls for page-local PHP interactions
|
|
710
738
|
- reserve plain browser JavaScript outside PulsePoint for external libraries, low-level browser APIs, and reusable helpers in `ts/`
|
|
711
739
|
- do not invent undocumented PulsePoint helpers or directives
|
|
712
740
|
- do not write React, Vue, Alpine, or Livewire syntax and call it PulsePoint
|
|
713
741
|
- keep backend concerns separate from PulsePoint runtime concerns
|
|
714
742
|
- prefer simple documented runtime primitives over abstractions copied from other ecosystems
|
|
715
|
-
-
|
|
743
|
+
- do not treat app-registered helpers such as `twMerge(...)` as PulsePoint built-ins; route those tasks through the Tailwind-enabled Prisma PHP docs after checking feature flags
|
|
744
|
+
- use `pp-style` whenever inline CSS contains `{...}` interpolation or any other template-driven/reactive value, and reserve plain `style` for fully static inline CSS
|
|
745
|
+
- do **not** generate reactive inline CSS inside a plain `style` attribute such as `style="width: {progress}%";` use `pp-style="width: {progress}%";` instead so source markup stays editor-friendly
|
|
716
746
|
- use `pp-spread="{...attrs}"` for dynamic attribute objects and omit nullish values from those objects
|
|
717
747
|
- use `pp-for` only on `<template>` with `item in items` or `(item, index) in items`
|
|
718
748
|
- use plain `key` for keyed diffing; do not invent `pp-key`
|
|
@@ -730,6 +760,8 @@ Also follow these rules:
|
|
|
730
760
|
- use kebab-case component attributes and rely on the runtime to hydrate camelCase PHPX properties and PulsePoint props
|
|
731
761
|
- keep component file names and class names aligned
|
|
732
762
|
- preserve documented PHPX patterns for `$props`, `$children`, `$class`, and `getAttributes(...)`
|
|
763
|
+
- in Tailwind-enabled apps, use `getMergeClasses(...)` and `PP\PHPX\TwMerge::merge(...)` as emitters of frontend `twMerge(...)` expressions instead of finalizing Tailwind class conflicts in PHP
|
|
764
|
+
- when a route or imported partial needs direct Tailwind-aware class composition, treat `twMerge(...)` as an app-level browser helper available only when `tailwindcss` is enabled
|
|
733
765
|
- follow documented component placement and grouping conventions before inspecting framework internals
|
|
734
766
|
|
|
735
767
|
## When to inspect framework internals
|
|
@@ -740,6 +772,8 @@ Useful app-mode core locations include:
|
|
|
740
772
|
|
|
741
773
|
```txt
|
|
742
774
|
vendor/tsnc/prisma-php/src
|
|
775
|
+
vendor/tsnc/prisma-php/src/PHPX/PHPX.php
|
|
776
|
+
vendor/tsnc/prisma-php/src/PHPX/TwMerge.php
|
|
743
777
|
vendor/tsnc/prisma-php/src/PHPX/TemplateCompiler.php
|
|
744
778
|
vendor/tsnc/prisma-php/src/ImportComponent.php
|
|
745
779
|
vendor/tsnc/prisma-php/src/MainLayout.php
|