@chidchanun/bcp 0.1.9 → 0.1.11
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/CHANGELOG.md +83 -1
- package/README.md +263 -8
- package/docs/form-actions.md +314 -0
- package/docs/releasing.md +34 -19
- package/docs/route-guards.md +240 -0
- package/docs/updating.md +130 -0
- package/package.json +1 -1
- package/packages/bundler/src/server-production-actions.ts +523 -0
- package/packages/bundler/src/server-production-guards.ts +497 -0
- package/packages/bundler/src/server-production-middleware.ts +50 -8
- package/packages/cli/src/args.ts +58 -0
- package/packages/cli/src/index.ts +41 -13
- package/packages/cli/src/update.ts +860 -0
- package/packages/client/src/form.tsx +548 -0
- package/packages/client/src/index.tsx +11 -0
- package/packages/client/src/loader-data.tsx +171 -41
- package/packages/client/src/server.ts +6 -0
- package/packages/server/src/form-action-dev-proxy.ts +601 -0
- package/packages/server/src/form-action-transport.ts +271 -0
- package/packages/server/src/form-action.ts +493 -0
- package/packages/server/src/middleware-dev-server.ts +56 -2
- package/packages/server/src/page-guard.ts +529 -0
- package/packages/server/src/page-loader.ts +317 -20
- package/packages/server/src/standalone-production-runtime-v2-action.ts +765 -0
- package/packages/server/src/standalone-production-runtime-v2-guard.ts +815 -0
- package/packages/server/src/standalone-production-runtime-v3.ts +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,88 @@
|
|
|
2
2
|
|
|
3
3
|
All notable framework changes are tracked here before release.
|
|
4
4
|
|
|
5
|
+
## 0.1.11 - Form actions and server mutations
|
|
6
|
+
|
|
7
|
+
### Route mutations
|
|
8
|
+
|
|
9
|
+
- Added route-level `actions.ts` / `actions.tsx` files next to `page.tsx` for server-only create, update and delete operations without requiring an API route for every page-owned mutation.
|
|
10
|
+
- Actions are named exports and receive browser `FormData` plus route `params`, target `searchParams`, merged `guardData` and the semantic mutation `method`.
|
|
11
|
+
- Supported action methods are `POST`, `PUT`, `PATCH` and `DELETE`; GET remains a loader/API read concern.
|
|
12
|
+
- Added `PageAction`, `PageActionContext` and `PageActionMethod` types through the server-only `bcp/server` entrypoint.
|
|
13
|
+
- Action modules may use normal server-only application/database imports plus request/session APIs such as `cookies()`, `getSession()`, `requestUrl()` and `requestMethod()`.
|
|
14
|
+
- `requestMethod()` reflects the semantic action method even though progressive HTML forms use POST as the browser transport.
|
|
15
|
+
- Actions may return JSON-safe data, `undefined` (normalized to `null`) or a Web `Response` such as `redirect()`.
|
|
16
|
+
- Action data uses JSON-safe validation and rejects unsupported/circular values before browser transport.
|
|
17
|
+
|
|
18
|
+
### Form client API and progressive enhancement
|
|
19
|
+
|
|
20
|
+
- Added public `<Form action="name">` with `post`, `put`, `patch` and `delete` semantic methods.
|
|
21
|
+
- Added `useFormStatus()` for pending/action/method/error state, `useActionData<T>()` for the latest serializable mutation result and `useActionError()` for transport/runtime failures.
|
|
22
|
+
- Enhanced submissions send the original `FormData` through the internal `/_bcp/action` transport without a document reload.
|
|
23
|
+
- Named actions use strings instead of importing server functions into the client graph, preserving server-only boundaries until the later compiler-backed Server Actions milestone.
|
|
24
|
+
- Same-origin redirects from enhanced actions continue through BCP client navigation while response cookies remain intact.
|
|
25
|
+
- Forms without JavaScript use normal HTML POST and POST/Redirect/GET `303` behavior for data-returning actions, preventing duplicate resubmission on browser refresh.
|
|
26
|
+
- Added optional `<Form refresh>` support to rerun the current BCP navigation/loader after a successful data-returning mutation.
|
|
27
|
+
|
|
28
|
+
### Authorization, caching and production
|
|
29
|
+
|
|
30
|
+
- Route guards execute before matching actions and can stop a mutation with a redirect/Response; merged authorization data is passed to the action through `context.guardData`.
|
|
31
|
+
- Project middleware and framework security remain outside the action gateway, so mutation requests keep the existing request interception and body-limit policy.
|
|
32
|
+
- Cookies created by actions or guards are preserved for data and redirect responses in both enhanced and progressive paths.
|
|
33
|
+
- `revalidatePath()` and `revalidateTag()` can be called directly inside actions using the shared process-local BCP cache runtime.
|
|
34
|
+
- Pages with sibling form actions are excluded from the automatic production response-cache manifest to avoid stale POST/Redirect/GET pages after mutations.
|
|
35
|
+
- Standalone builds generate `server/actions.mjs` only when action routes exist and execute bundled action modules entirely on the server.
|
|
36
|
+
- Added development and standalone action gateways without exposing action/database modules to browser bundles.
|
|
37
|
+
|
|
38
|
+
### Reliability and documentation
|
|
39
|
+
|
|
40
|
+
- Added `/action-demo/[id]` plus guarded mutation fixtures for FormData, semantic methods, cookies, redirects, cache revalidation hooks, progressive enhancement and guard-data handoff.
|
|
41
|
+
- Added unit coverage for action naming, method normalization, route context, Response returns and serialization rejection.
|
|
42
|
+
- Added development integration and standalone E2E coverage for enhanced mutations, no-JavaScript PRG behavior, response cookies and guards-before-actions ordering.
|
|
43
|
+
- Added publish-artifact smoke checks for the public Form API, server mutation runtime, dev gateway, standalone action gateway and production action bundle.
|
|
44
|
+
- Added dedicated Form Actions and Server Mutations documentation.
|
|
45
|
+
|
|
46
|
+
## 0.1.10 - Framework updater and protected route guards
|
|
47
|
+
|
|
48
|
+
### Framework updater
|
|
49
|
+
|
|
50
|
+
- Added `bcp update` to resolve and install the current `@chidchanun/bcp@latest` release from an existing BCP application.
|
|
51
|
+
- Added `bcp update <version-or-tag>` for explicitly targeting a published version or npm dist-tag.
|
|
52
|
+
- Added `bcp update --check` and `bcp update --dry-run` so projects can inspect an available update without changing package metadata or lockfiles.
|
|
53
|
+
- Existing generated `bcp` npm aliases and direct `@chidchanun/bcp` dependencies are detected automatically.
|
|
54
|
+
- Package-manager detection supports npm, pnpm, Yarn and Bun lockfiles and refuses to guess when conflicting lockfiles are present.
|
|
55
|
+
- Failed installs restore the original `package.json` and detected lockfile before returning an error.
|
|
56
|
+
- Projects published before the updater can bootstrap it once with `npx @chidchanun/bcp@latest update`; subsequent releases can use `bcp update` or the generated `npm run update` script directly.
|
|
57
|
+
- Generated applications pin the exact resolved BCP version so a normal package-manager install does not silently cross framework releases.
|
|
58
|
+
- Added unit coverage for updater argument parsing, dependency planning, package-manager detection and ambiguous dependency rejection.
|
|
59
|
+
- Added publish-artifact smoke checks requiring the updater source and CLI dispatch wiring.
|
|
60
|
+
|
|
61
|
+
### Protected routes and auth guards
|
|
62
|
+
|
|
63
|
+
- Added scoped `guard.ts` / `guard.tsx` files that protect pages in their route directory and descendant page directories.
|
|
64
|
+
- Guards execute from app root toward the matched page and receive `params`, target `searchParams` and merged ancestor `guardData`.
|
|
65
|
+
- A guard may return JSON-safe authorization data or a Web `Response`; redirects stop the pipeline before loader/page execution.
|
|
66
|
+
- Guards run inside the normal BCP request context, so sessions, cookies, headers, request URLs, request IDs and other `bcp/server` helpers are available directly.
|
|
67
|
+
- Loader context now receives merged `guardData`, avoiding repeated session/role lookups after a guard has already validated the request.
|
|
68
|
+
- Added public `useGuardData<T>()` so pages can consume the same guard result during SSR, hydration and SPA navigation.
|
|
69
|
+
- Guard-only routes are supported without requiring a page loader.
|
|
70
|
+
- Response cookies set by allowed guards or redirecting guards are preserved on document and navigation responses.
|
|
71
|
+
- Guard return values use the same JSON-safe validation rules as loader data and reject unsupported/circular values before transport.
|
|
72
|
+
- Direct requests and SPA navigation use the same authorization policy, including target-page params/query values and redirects.
|
|
73
|
+
- Standalone production generates a server-only `guards.mjs` evaluator and places the guard gateway after project middleware but before loader/page execution.
|
|
74
|
+
- User-supplied internal guard transport headers are stripped before authorization evaluation so clients cannot forge guard results.
|
|
75
|
+
- Internal serialized guard data is size-limited before it is proxied to the inner standalone runtime.
|
|
76
|
+
- Route-guarded pages are excluded from the automatic production response cache because their output may depend on session/role identity.
|
|
77
|
+
- Added `/guard-demo/[id]` and guard-only fixtures covering parent/child guard data, roles, cookies, loader integration and redirects.
|
|
78
|
+
- Added unit, development integration and standalone E2E coverage for guards, including forged-header rejection and guard-only production routes.
|
|
79
|
+
- Added publish-artifact smoke checks for the guard evaluator, standalone guard runtime, public hook and loader/guard bridge.
|
|
80
|
+
- Added dedicated protected-route documentation and updated README guidance for middleware versus route guards.
|
|
81
|
+
|
|
82
|
+
### Release channel
|
|
83
|
+
|
|
84
|
+
- Stable BCP releases now publish to the npm `latest` dist-tag by default even while the framework is pre-1.0.
|
|
85
|
+
- Maintainers can still select `next`, `beta` or another channel explicitly through `BCP_DIST_TAG`.
|
|
86
|
+
|
|
5
87
|
## 0.1.9 - Server data loaders
|
|
6
88
|
|
|
7
89
|
### Server rendering and data
|
|
@@ -24,7 +106,7 @@ All notable framework changes are tracked here before release.
|
|
|
24
106
|
- Navigation loaders receive a request context for the target page URL rather than the internal navigation transport URL, preserving target query parameters, cookies, sessions and request helpers.
|
|
25
107
|
- Loader redirects are converted to a navigation redirect payload while preserving all response cookies; same-origin redirects continue through the SPA router and cross-origin redirects use normal browser navigation.
|
|
26
108
|
- Non-navigation Web `Response` values continue to fall back to a document request so their original HTTP semantics remain authoritative.
|
|
27
|
-
- Client navigation explicitly sends same-origin credentials, aborts superseded requests and uses a monotonically increasing navigation sequence so stale responses cannot update
|
|
109
|
+
- Client navigation explicitly sends same-origin credentials, aborts superseded requests and uses a monotonically increasing navigation sequence so stale responses cannot update the active route after a newer navigation has started.
|
|
28
110
|
- Navigation redirect chains are capped at 10 redirects to prevent loops.
|
|
29
111
|
- `useNavigation()` becomes active before the server request starts and route loading markup can be displayed while the target client runtime/assets finish after the payload arrives.
|
|
30
112
|
- Standalone loader navigation is placed inside the existing middleware/security chain rather than bypassing application middleware or framework security gateways.
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
BCP Framework is a React full-stack framework with file-based routing, SSR, client navigation, API routes, middleware, metadata, client islands, cache/revalidation, security defaults and standalone production builds.
|
|
4
4
|
|
|
5
|
-
> Current
|
|
5
|
+
> Current release target: `0.1.11`. BCP is still pre-1.0 and validates each release candidate before the manual npm publish step.
|
|
6
6
|
|
|
7
7
|
## Quick start
|
|
8
8
|
|
|
@@ -33,10 +33,14 @@ app/
|
|
|
33
33
|
├─ loading.tsx
|
|
34
34
|
├─ error.tsx
|
|
35
35
|
├─ not-found.tsx
|
|
36
|
-
├─
|
|
37
|
-
│
|
|
38
|
-
│
|
|
39
|
-
│
|
|
36
|
+
├─ dashboard/
|
|
37
|
+
│ ├─ guard.ts
|
|
38
|
+
│ ├─ page.tsx
|
|
39
|
+
│ └─ users/
|
|
40
|
+
│ └─ [id]/
|
|
41
|
+
│ ├─ loader.ts
|
|
42
|
+
│ ├─ actions.ts
|
|
43
|
+
│ └─ page.tsx
|
|
40
44
|
└─ api/
|
|
41
45
|
└─ hello/
|
|
42
46
|
└─ route.ts
|
|
@@ -74,7 +78,7 @@ Server-only modules can declare:
|
|
|
74
78
|
import "bcp/server-only";
|
|
75
79
|
```
|
|
76
80
|
|
|
77
|
-
Database helpers generated by `create-bcp-app` include the server-only marker automatically. A server-only helper must not be imported from a hydrated page/client graph. Use an API route or
|
|
81
|
+
Database helpers generated by `create-bcp-app` include the server-only marker automatically. A server-only helper must not be imported from a hydrated page/client graph. Use an API route or a server-only route primitive such as `loader.ts`, `guard.ts` or `actions.ts`.
|
|
78
82
|
|
|
79
83
|
See [Application Modules](docs/application-modules.md) for the complete boundary model and examples.
|
|
80
84
|
|
|
@@ -89,11 +93,42 @@ bcp dev
|
|
|
89
93
|
bcp routes
|
|
90
94
|
bcp build
|
|
91
95
|
bcp start
|
|
96
|
+
bcp update
|
|
92
97
|
bcp version
|
|
93
98
|
```
|
|
94
99
|
|
|
95
100
|
CLI server overrides are available with `--port` and `--hostname`.
|
|
96
101
|
|
|
102
|
+
## Updating an existing project
|
|
103
|
+
|
|
104
|
+
Once a project is on a BCP version that contains the updater, update to the current npm `latest` release with:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
bcp update
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Preview an update without changing files:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
bcp update --check
|
|
114
|
+
bcp update --dry-run
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Or select a published version/dist-tag explicitly:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
bcp update 0.1.11
|
|
121
|
+
bcp update next
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Versions published before the updater do not recognize `bcp update`. Bootstrap the newest CLI once from those projects:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
npx @chidchanun/bcp@latest update
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The updater changes the framework dependency and package-manager lockfile, detects npm/pnpm/Yarn/Bun from the project lockfile, and restores package metadata if installation fails. It does not overwrite application source files, database schemas or authentication code. See [Updating BCP Framework](docs/updating.md) for the complete behavior and migration notes.
|
|
131
|
+
|
|
97
132
|
## Routing
|
|
98
133
|
|
|
99
134
|
BCP supports:
|
|
@@ -124,7 +159,7 @@ Supported methods include GET, POST, PUT, PATCH, DELETE, HEAD and OPTIONS. HEAD
|
|
|
124
159
|
|
|
125
160
|
## Server request APIs
|
|
126
161
|
|
|
127
|
-
BCP 0.1.7 adds request-scoped server helpers through `bcp/server`. These helpers are server-only and are available from API handlers
|
|
162
|
+
BCP 0.1.7 adds request-scoped server helpers through `bcp/server`. These helpers are server-only and are available from API handlers, server data loaders, route guards and form actions.
|
|
128
163
|
|
|
129
164
|
```ts
|
|
130
165
|
import {
|
|
@@ -273,6 +308,217 @@ Loader-backed pages now use the same SPA navigation model as normal BCP routes.
|
|
|
273
308
|
|
|
274
309
|
See [Server Data Loaders](docs/server-data-loaders.md) for serialization rules, authentication patterns, redirect behavior, SPA navigation, cache safety and request-context semantics.
|
|
275
310
|
|
|
311
|
+
## Protected routes and auth guards
|
|
312
|
+
|
|
313
|
+
BCP 0.1.10 adds scoped `guard.ts` / `guard.tsx` files for page authorization. A guard protects the pages in its directory and descendant route directories, runs before the page loader, and can use the same request/session APIs as a loader.
|
|
314
|
+
|
|
315
|
+
```text
|
|
316
|
+
app/dashboard/
|
|
317
|
+
├─ guard.ts
|
|
318
|
+
├─ page.tsx
|
|
319
|
+
└─ users/
|
|
320
|
+
└─ [id]/
|
|
321
|
+
├─ loader.ts
|
|
322
|
+
└─ page.tsx
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
```ts
|
|
326
|
+
// app/dashboard/guard.ts
|
|
327
|
+
import {
|
|
328
|
+
getSession,
|
|
329
|
+
redirect,
|
|
330
|
+
} from "bcp/server";
|
|
331
|
+
|
|
332
|
+
export async function guard() {
|
|
333
|
+
const session =
|
|
334
|
+
await getSession<{
|
|
335
|
+
userId: number;
|
|
336
|
+
email: string;
|
|
337
|
+
role: string;
|
|
338
|
+
}>();
|
|
339
|
+
|
|
340
|
+
if (!session) {
|
|
341
|
+
return redirect(
|
|
342
|
+
"/login",
|
|
343
|
+
303
|
|
344
|
+
);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
return {
|
|
348
|
+
session,
|
|
349
|
+
role:
|
|
350
|
+
session.role,
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
Descendant loaders receive the merged result as `guardData`, so they do not need to repeat `getSession()`:
|
|
356
|
+
|
|
357
|
+
```ts
|
|
358
|
+
export async function loader({
|
|
359
|
+
params,
|
|
360
|
+
guardData,
|
|
361
|
+
}) {
|
|
362
|
+
return {
|
|
363
|
+
id:
|
|
364
|
+
params.id,
|
|
365
|
+
user:
|
|
366
|
+
guardData.session,
|
|
367
|
+
role:
|
|
368
|
+
guardData.role,
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
A page can consume the same authorization data with `useGuardData<T>()`:
|
|
374
|
+
|
|
375
|
+
```tsx
|
|
376
|
+
"use client";
|
|
377
|
+
|
|
378
|
+
import {
|
|
379
|
+
useGuardData,
|
|
380
|
+
} from "bcp";
|
|
381
|
+
|
|
382
|
+
export default function DashboardPage() {
|
|
383
|
+
const guard =
|
|
384
|
+
useGuardData<{
|
|
385
|
+
session: {
|
|
386
|
+
email: string;
|
|
387
|
+
};
|
|
388
|
+
role: string;
|
|
389
|
+
}>();
|
|
390
|
+
|
|
391
|
+
return (
|
|
392
|
+
<main>
|
|
393
|
+
{guard.session.email}
|
|
394
|
+
</main>
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
Nested guards execute from root to child and receive merged ancestor output as `guardData`. Guard redirects and response cookies work for both direct document requests and SPA navigation. Guarded pages are excluded from the automatic production response cache, and standalone production strips user-supplied internal guard transport headers before evaluating authorization.
|
|
400
|
+
|
|
401
|
+
See [Protected Route Guards](docs/route-guards.md) for nested role policies, serialization rules, middleware ordering, cookie behavior and production hardening.
|
|
402
|
+
|
|
403
|
+
## Form actions and server mutations
|
|
404
|
+
|
|
405
|
+
BCP 0.1.11 adds route-owned server mutations with `actions.ts` / `actions.tsx`. Actions stay on the server and let page forms perform create, update and delete operations without creating a dedicated API route for every mutation.
|
|
406
|
+
|
|
407
|
+
```text
|
|
408
|
+
app/users/[id]/
|
|
409
|
+
├─ guard.ts
|
|
410
|
+
├─ loader.ts
|
|
411
|
+
├─ actions.ts
|
|
412
|
+
└─ page.tsx
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
```ts
|
|
416
|
+
// app/users/[id]/actions.ts
|
|
417
|
+
import "bcp/server-only";
|
|
418
|
+
|
|
419
|
+
import {
|
|
420
|
+
redirect,
|
|
421
|
+
type PageActionContext,
|
|
422
|
+
} from "bcp/server";
|
|
423
|
+
|
|
424
|
+
import {
|
|
425
|
+
revalidatePath,
|
|
426
|
+
} from "bcp/cache";
|
|
427
|
+
|
|
428
|
+
export async function saveUser(
|
|
429
|
+
formData: FormData,
|
|
430
|
+
context: PageActionContext
|
|
431
|
+
) {
|
|
432
|
+
const name =
|
|
433
|
+
String(
|
|
434
|
+
formData.get("name") ?? ""
|
|
435
|
+
).trim();
|
|
436
|
+
|
|
437
|
+
// await db.execute(...)
|
|
438
|
+
|
|
439
|
+
revalidatePath("/users");
|
|
440
|
+
|
|
441
|
+
if (!name) {
|
|
442
|
+
return {
|
|
443
|
+
ok: false,
|
|
444
|
+
message: "Name is required",
|
|
445
|
+
};
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
if (
|
|
449
|
+
context.searchParams.get("done") === "1"
|
|
450
|
+
) {
|
|
451
|
+
return redirect(
|
|
452
|
+
"/users",
|
|
453
|
+
303
|
|
454
|
+
);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
return {
|
|
458
|
+
ok: true,
|
|
459
|
+
id: context.params.id,
|
|
460
|
+
name,
|
|
461
|
+
method: context.method,
|
|
462
|
+
};
|
|
463
|
+
}
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
Client forms reference the named server action without importing it into the browser graph:
|
|
467
|
+
|
|
468
|
+
```tsx
|
|
469
|
+
"use client";
|
|
470
|
+
|
|
471
|
+
import {
|
|
472
|
+
Form,
|
|
473
|
+
useActionData,
|
|
474
|
+
useActionError,
|
|
475
|
+
useFormStatus,
|
|
476
|
+
} from "bcp";
|
|
477
|
+
|
|
478
|
+
function SubmitButton() {
|
|
479
|
+
const status =
|
|
480
|
+
useFormStatus();
|
|
481
|
+
|
|
482
|
+
return (
|
|
483
|
+
<button
|
|
484
|
+
type="submit"
|
|
485
|
+
disabled={status.pending}
|
|
486
|
+
>
|
|
487
|
+
{status.pending
|
|
488
|
+
? "Saving..."
|
|
489
|
+
: "Save"}
|
|
490
|
+
</button>
|
|
491
|
+
);
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
export default function UserForm() {
|
|
495
|
+
const result =
|
|
496
|
+
useActionData<{
|
|
497
|
+
ok: boolean;
|
|
498
|
+
message?: string;
|
|
499
|
+
}>();
|
|
500
|
+
const error =
|
|
501
|
+
useActionError();
|
|
502
|
+
|
|
503
|
+
return (
|
|
504
|
+
<Form
|
|
505
|
+
action="saveUser"
|
|
506
|
+
method="patch"
|
|
507
|
+
refresh
|
|
508
|
+
>
|
|
509
|
+
<input name="name" />
|
|
510
|
+
<SubmitButton />
|
|
511
|
+
{result?.message}
|
|
512
|
+
{error?.message}
|
|
513
|
+
</Form>
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
```
|
|
517
|
+
|
|
518
|
+
Supported semantic methods are POST, PUT, PATCH and DELETE. Guards execute before actions and pass merged authorization state through `context.guardData`. Actions can use cookies, JWT sessions, `requestMethod()`, redirects and cache revalidation. Enhanced forms submit through the BCP SPA transport; forms without JavaScript fall back to standard HTML POST with POST/Redirect/GET semantics. Action-backed pages are excluded from automatic production response caching.
|
|
519
|
+
|
|
520
|
+
See [Form Actions and Server Mutations](docs/form-actions.md) for action return values, pending/error state, progressive enhancement, guards, redirects, cookies, cache invalidation and standalone behavior.
|
|
521
|
+
|
|
276
522
|
## JWT cookie sessions
|
|
277
523
|
|
|
278
524
|
BCP 0.1.8 adds HS256 JWT cookie sessions directly to `bcp/server`. Configure a server-only secret of at least 32 bytes:
|
|
@@ -412,7 +658,7 @@ import {
|
|
|
412
658
|
} from "bcp/cache";
|
|
413
659
|
```
|
|
414
660
|
|
|
415
|
-
The current cache implementation is process-local and intentionally does not provide distributed invalidation across multiple Node.js instances. Loader-backed pages are excluded from the automatic production response-cache manifest
|
|
661
|
+
The current cache implementation is process-local and intentionally does not provide distributed invalidation across multiple Node.js instances. Loader-backed, route-guarded and action-backed pages are excluded from the automatic production response-cache manifest when their output or mutation flow may depend on request/session state. Cache server data explicitly only when the application has a safe user-aware cache key and invalidation strategy.
|
|
416
662
|
|
|
417
663
|
## Middleware
|
|
418
664
|
|
|
@@ -437,6 +683,8 @@ export function middleware(
|
|
|
437
683
|
}
|
|
438
684
|
```
|
|
439
685
|
|
|
686
|
+
Use middleware for request-wide interception and `guard.ts` for page-subtree authorization that needs to feed identity/role data into loaders, actions and pages. In standalone production, project middleware runs before route guards and form actions.
|
|
687
|
+
|
|
440
688
|
## Configuration
|
|
441
689
|
|
|
442
690
|
```ts
|
|
@@ -488,10 +736,14 @@ The standalone output is generated under:
|
|
|
488
736
|
└─ server/
|
|
489
737
|
├─ server.mjs
|
|
490
738
|
├─ middleware.mjs
|
|
739
|
+
├─ guards.mjs
|
|
740
|
+
├─ actions.mjs
|
|
491
741
|
├─ cache-manifest.json
|
|
492
742
|
└─ config.json
|
|
493
743
|
```
|
|
494
744
|
|
|
745
|
+
`guards.mjs` is generated only when the application contains protected route guards. `actions.mjs` is generated only when the application contains route form actions.
|
|
746
|
+
|
|
495
747
|
## Package preparation
|
|
496
748
|
|
|
497
749
|
The development monorepo stays private. Publishable artifacts are produced separately:
|
|
@@ -523,7 +775,10 @@ No real npm publish command is run automatically by the repository.
|
|
|
523
775
|
- [Application Modules](docs/application-modules.md)
|
|
524
776
|
- [Server Request APIs](docs/server-request-apis.md)
|
|
525
777
|
- [Server Data Loaders](docs/server-data-loaders.md)
|
|
778
|
+
- [Protected Route Guards](docs/route-guards.md)
|
|
779
|
+
- [Form Actions and Server Mutations](docs/form-actions.md)
|
|
526
780
|
- [JWT Cookie Sessions](docs/session-auth.md)
|
|
781
|
+
- [Updating BCP Framework](docs/updating.md)
|
|
527
782
|
- [Routing](docs/routing.md)
|
|
528
783
|
- [Configuration](docs/configuration.md)
|
|
529
784
|
- [Caching](docs/caching.md)
|