@webqit/webflo 0.20.2 → 0.20.4-next.0
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 +1 -2
- package/package.json +1 -1
- package/site/.vitepress/config.ts +2 -2
- package/site/docs/concepts/routing.md +39 -37
- package/site/index.md +2 -2
- package/site/overview.md +0 -2
package/README.md
CHANGED
|
@@ -4,8 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
_A web-native framework for the next generation of apps_
|
|
6
6
|
|
|
7
|
-
[![npm version][npm-version-src]][npm-version-href]
|
|
8
|
-
<!--[![npm downloads][npm-downloads-src]][npm-downloads-href]-->
|
|
7
|
+
[![npm version][npm-version-src]][npm-version-href]<!--[![npm downloads][npm-downloads-src]][npm-downloads-href]-->
|
|
9
8
|
[![License][license-src]][license-href]
|
|
10
9
|
|
|
11
10
|
</div>
|
package/package.json
CHANGED
|
@@ -32,10 +32,10 @@ const config = {
|
|
|
32
32
|
sidebar: {
|
|
33
33
|
'/': [
|
|
34
34
|
{
|
|
35
|
-
text: '
|
|
35
|
+
text: 'Overview',
|
|
36
36
|
items: [
|
|
37
37
|
{ text: 'What is Webflo', link: '/overview' },
|
|
38
|
-
{ text: '
|
|
38
|
+
{ text: 'Getting Started', link: '/docs/getting-started' },
|
|
39
39
|
]
|
|
40
40
|
},
|
|
41
41
|
{
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Webflo Routing
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Route handlers come into play in Webflo when you need to dynamically handle requests.
|
|
4
4
|
Routing defines how those requests map to functions in a Webflo application.
|
|
5
5
|
It determines which handler responds to a given URL, how requests move across layers of the stack, and how each step in that process composes into a complete response.
|
|
6
6
|
|
|
@@ -73,7 +73,7 @@ Use these for conditional delegation, or per-segment rules.
|
|
|
73
73
|
### Your First Handler (Again)
|
|
74
74
|
|
|
75
75
|
Your application's routes may be designed with as many or as few handlers as desired.<br>
|
|
76
|
-
|
|
76
|
+
In fact, if it calls for it, the contextual parameters `next.stepname` and `next.pathname` totally make it possible to fit routing logic into a single handler.
|
|
77
77
|
|
|
78
78
|
```js
|
|
79
79
|
export default function(event, next) {
|
|
@@ -97,12 +97,12 @@ export default function(event, next) {
|
|
|
97
97
|
}
|
|
98
98
|
```
|
|
99
99
|
|
|
100
|
-
But the power of Webflo routing
|
|
100
|
+
But the power of Webflo routing really shines as you spread out to more functions.
|
|
101
101
|
|
|
102
102
|
## The Delegation Model
|
|
103
103
|
|
|
104
|
-
In Webflo, nested URLs such as `/products/stickers` don’t directly invoke their corresponding leaf handler (`app/products/stickers/handler.server.js`)
|
|
105
|
-
Instead, requests are handled **step-by-step — from parent to child
|
|
104
|
+
In Webflo, nested URLs such as `/products/stickers` don’t directly invoke their corresponding leaf handler (`app/products/stickers/handler.server.js`).
|
|
105
|
+
Instead, requests are handled **step-by-step — from parent to child** until a handler returns a response, forming a **pipeline**.
|
|
106
106
|
|
|
107
107
|
The `next()` function is how a handler delegates control to the next step in that pipeline.
|
|
108
108
|
|
|
@@ -149,7 +149,7 @@ export default async function () {
|
|
|
149
149
|
|
|
150
150
|
### Internal Rerouting
|
|
151
151
|
|
|
152
|
-
Beyond the default parent-child flow, a handler can explicitly **reroute** a request to another path within the app by calling `next(path)
|
|
152
|
+
Beyond the default parent-child flow, a handler can explicitly **reroute** a request to another path within the app by calling `next({ redirect: path })`, or `next(path)`, for short.
|
|
153
153
|
|
|
154
154
|
This is simulated below for a URL like `/products/stickers`.<br>
|
|
155
155
|
Here, the root handler conditionally reroutes the request to `/api/inventory`, all within the same app.
|
|
@@ -195,7 +195,7 @@ export default async function (event, next) {
|
|
|
195
195
|
|
|
196
196
|
The rerouted request travels through the normal routing tree (`app/` → `api/` → `inventory/`) as if it had originated normally.
|
|
197
197
|
|
|
198
|
-
A relative path (e.g., `next('./api/inventory?range=7d')`) may be used to bypass lineage.
|
|
198
|
+
A relative path (e.g., `next('./api/inventory?range=7d')`) may be used to bypass the target route's lineage.
|
|
199
199
|
But this must be done intentionally: deeper routes often inherit authentication or other contexts that should not be bypassed.
|
|
200
200
|
|
|
201
201
|
This technique enables **in-app data composition** — using existing route logic without additional network requests.
|
|
@@ -215,7 +215,7 @@ export default async function (event, next) {
|
|
|
215
215
|
url.searchParams.set('p', 3);
|
|
216
216
|
|
|
217
217
|
// Delegate with the modified URL
|
|
218
|
-
const res = await next(
|
|
218
|
+
const res = await next(url.pathname + url.search);
|
|
219
219
|
|
|
220
220
|
// Post-process response before returning
|
|
221
221
|
const headers = new Headers(res.headers);
|
|
@@ -236,7 +236,7 @@ Through this mechanism, Webflo lets handlers **reshape requests or responses inl
|
|
|
236
236
|
|
|
237
237
|
## The Client-Server Flow
|
|
238
238
|
|
|
239
|
-
|
|
239
|
+
In addition to the handler-to-handler model, Webflo also has the **client-server flow** which represents the _vertical_ flow of the same request through the application stack (client → server).
|
|
240
240
|
|
|
241
241
|
Webflo follows a model that supports request handling and routing at all three layers in this stack: the browser window layer (**client**), the service worker layer (**worker**), the server layer (**server**).
|
|
242
242
|
|
|
@@ -265,7 +265,7 @@ Below is a conceptual diagram of how a navigation request flows donw the layers:
|
|
|
265
265
|
▼ └─────────────────────────────────┘
|
|
266
266
|
```
|
|
267
267
|
|
|
268
|
-
Handlers are optional; if a
|
|
268
|
+
Handlers across this vertical stack are optional; if a layer-specific file doesn’t exist, Webflo automatically falls back to the unsuffixed one `handler.js`,
|
|
269
269
|
if defined. Otherwise, the request continues to the next layer. Each request gets a graceful path from local logic to remote fulfillment.
|
|
270
270
|
|
|
271
271
|
As with the horizontal flow, each layer may intercept, fulfill, or delegate down the request.<br>
|
|
@@ -342,7 +342,7 @@ export default async function (event, next) {
|
|
|
342
342
|
|
|
343
343
|
#### Server-Side Handlers
|
|
344
344
|
|
|
345
|
-
Server handlers perform the heavy lifting — database queries,
|
|
345
|
+
Server handlers perform the heavy lifting — database queries, integrations, etc.
|
|
346
346
|
They represent the final dynamic layer before static content resolution.
|
|
347
347
|
|
|
348
348
|
```js
|
|
@@ -362,8 +362,8 @@ export default async function (event, next) {
|
|
|
362
362
|
|
|
363
363
|
#### Universal Handlers
|
|
364
364
|
|
|
365
|
-
Universal handlers (`handler.js`) are handlers declared without any layer binding.
|
|
366
|
-
They
|
|
365
|
+
Universal handlers (`handler.js`) are handlers declared without any layer binding. They represent the default handler for a route. And they imply logic that can run anywhere in the client-server stack.
|
|
366
|
+
They execute wherever no layer-specific handler exists for the current layer, making them perfect for universal logic.
|
|
367
367
|
|
|
368
368
|
```js
|
|
369
369
|
// app/handler.js
|
|
@@ -374,8 +374,7 @@ export default async function (event, next) {
|
|
|
374
374
|
```
|
|
375
375
|
|
|
376
376
|
::: tip Progressive Enhancement
|
|
377
|
-
- Because handlers are modular by filename, promoting a route from server-side to client-side is as simple as renaming the file.
|
|
378
|
-
- Webflo’s model turns *progressive enhancement* into a first-class development workflow.
|
|
377
|
+
- Because handlers are modular by filename, promoting a route from server-side to client-side, or the reverse, is as simple as renaming the file.
|
|
379
378
|
:::
|
|
380
379
|
|
|
381
380
|
### Fall-Through Behavior
|
|
@@ -443,13 +442,13 @@ This composability and control extend to static files handling.
|
|
|
443
442
|
|
|
444
443
|
At the end of Webflo’s routing chain lies the **static layer** — a built-in static file server that operates by the same rules as every other layer.
|
|
445
444
|
|
|
446
|
-
In Webflo, static
|
|
445
|
+
In Webflo, static files serving is not a separate middleware; it is simply the final stage of the routing pipeline.
|
|
447
446
|
|
|
448
447
|
This layer is reached **from the server routing layer**, when:
|
|
449
448
|
|
|
450
449
|
* a server handler calls `next()` and no further route step exists in the pipeline
|
|
451
450
|
|
|
452
|
-
Because static serving sits in this same flow, route handlers take first-seat
|
|
451
|
+
Because static files serving sits in this same flow, route handlers take first-seat control in how static URLs resolve — being able to intercept, rewrite, or even *simulate* static file responses before they are served.
|
|
453
452
|
|
|
454
453
|
This flow is simulated below for an image URL: `/img/logo.png` embedded on a page.<br>
|
|
455
454
|
Its resolution goes the standard routing flow until matching a file in the `app/public` directory.
|
|
@@ -480,7 +479,7 @@ This handler-first approach to static files serving ensures that asset delivery
|
|
|
480
479
|
But this also requires **proper delegation discipline** by handlers.
|
|
481
480
|
Handlers must consciously call `next()` for requests they're not explicitly designed to handle.
|
|
482
481
|
|
|
483
|
-
Overall, by merging dynamic logic and static delivery into one continuous flow, Webflo replaces special-case asset middleware with a **first-class, programmable static pipeline**.
|
|
482
|
+
Overall, by merging dynamic logic and static delivery into one continuous flow, Webflo replaces special-case asset middleware with a **first-class, programmable static files pipeline**.
|
|
484
483
|
|
|
485
484
|
### Default Resolution
|
|
486
485
|
|
|
@@ -492,7 +491,7 @@ When a request reaches the static layer, Webflo performs deterministic file reso
|
|
|
492
491
|
|
|
493
492
|
## Use Case Patterns
|
|
494
493
|
|
|
495
|
-
The following examples demonstrate how Webflo’s routing primitives—delegation, composition, and explicit fall-through—combine to express real application
|
|
494
|
+
The following examples demonstrate how Webflo’s routing primitives — delegation, composition, and explicit fall-through — combine to express real application architectures.
|
|
496
495
|
Each pattern is an applied scenario that builds directly on the models we’ve covered so far.
|
|
497
496
|
|
|
498
497
|
### Parent–Child Composition
|
|
@@ -502,10 +501,9 @@ This pattern allows *layered composition*—logic in parents, data or view in ch
|
|
|
502
501
|
|
|
503
502
|
```js
|
|
504
503
|
// app/handler.server.js
|
|
505
|
-
export default async function (event,
|
|
504
|
+
export default async function (event, next) {
|
|
506
505
|
if (next.stepname) {
|
|
507
|
-
const
|
|
508
|
-
const childResult = await next({ user });
|
|
506
|
+
const childResult = await next();
|
|
509
507
|
return { ...childResult, title: `${childResult.title} | ExampleApp` };
|
|
510
508
|
}
|
|
511
509
|
return { title: 'Home' };
|
|
@@ -517,7 +515,7 @@ export default async function (event, context, next) {
|
|
|
517
515
|
### Internal API Consumption
|
|
518
516
|
|
|
519
517
|
**Scenario:** A page handler calls an internal API route using `next(path)` instead of making an HTTP request.
|
|
520
|
-
This lets server code reuse API logic without duplication or latency.
|
|
518
|
+
This, for example, lets server code reuse API logic without duplication or latency.
|
|
521
519
|
|
|
522
520
|
```html
|
|
523
521
|
app/
|
|
@@ -542,16 +540,16 @@ export default async function (event, next) {
|
|
|
542
540
|
|
|
543
541
|
```js
|
|
544
542
|
// app/account/handler.server.js
|
|
545
|
-
export default async function (event,
|
|
546
|
-
|
|
547
|
-
if (!user) {
|
|
543
|
+
export default async function (event, next) {
|
|
544
|
+
// Using event.user.isSignedIn() to check authentication
|
|
545
|
+
if (!await event.user.isSignedIn()) {
|
|
548
546
|
return new Response(null, { status: 302, headers: { Location: '/login' } });
|
|
549
547
|
}
|
|
550
|
-
return next(
|
|
548
|
+
return next();
|
|
551
549
|
}
|
|
552
550
|
```
|
|
553
551
|
|
|
554
|
-
**Takeaway:** Authentication becomes just another layer in the routing flow—
|
|
552
|
+
**Takeaway:** Authentication becomes just another layer in the routing flow — as against external middleware.
|
|
555
553
|
|
|
556
554
|
### File Guards and Access Control
|
|
557
555
|
|
|
@@ -560,8 +558,12 @@ export default async function (event, context, next) {
|
|
|
560
558
|
```js
|
|
561
559
|
// app/files/handler.server.js
|
|
562
560
|
export default async function (event, next) {
|
|
563
|
-
|
|
564
|
-
if (!user
|
|
561
|
+
// Using event.user.isSignedIn() to check authentication
|
|
562
|
+
if (!await event.user.isSignedIn()) {
|
|
563
|
+
return new Response('Access denied', { status: 403 });
|
|
564
|
+
}
|
|
565
|
+
// Using 'is_premium' from an underlying users table to authorize access
|
|
566
|
+
if (!await event.user.get('is_premium')) {
|
|
565
567
|
return new Response('Access denied', { status: 403 });
|
|
566
568
|
}
|
|
567
569
|
return next();
|
|
@@ -588,11 +590,11 @@ export default async function (event, next) {
|
|
|
588
590
|
}
|
|
589
591
|
```
|
|
590
592
|
|
|
591
|
-
**Takeaway:** Handlers can shape even static responses—embedding application-level awareness into the file
|
|
593
|
+
**Takeaway:** Handlers can shape even static responses — embedding application-level awareness into the file response.
|
|
592
594
|
|
|
593
595
|
### Full-Stack Routing
|
|
594
596
|
|
|
595
|
-
**Scenario:** A single navigation passes through multiple layers—client
|
|
597
|
+
**Scenario:** A single navigation passes through multiple layers — `client`, `worker`, `server`, `public` — each adding incremental behavior.
|
|
596
598
|
|
|
597
599
|
```js
|
|
598
600
|
CLIENT (handler.client.js)
|
|
@@ -643,14 +645,14 @@ export default async function (event, next) {
|
|
|
643
645
|
|
|
644
646
|
Webflo’s routing system unifies **filesystem mapping**, **functional composition**, and **layered execution** into one consistent model.
|
|
645
647
|
|
|
646
|
-
* The filesystem defines your application structure.
|
|
648
|
+
* The filesystem defines your application URL structure.
|
|
647
649
|
* Handlers define logic for each URL segment.
|
|
648
|
-
* `next()` controls flow between steps and
|
|
650
|
+
* `next()` controls flow between steps and layers.
|
|
649
651
|
* Default fallbacks ensure graceful completion through the stack.
|
|
650
652
|
* Static serving is part of the same flow, enabling dynamic control.
|
|
651
653
|
|
|
652
654
|
## Next Steps
|
|
653
655
|
|
|
654
|
-
* [Rendering](./rendering
|
|
655
|
-
* [Templates](./templates
|
|
656
|
-
* [State & Reactivity](./state
|
|
656
|
+
* [Rendering](./rendering): How handler data becomes UI.
|
|
657
|
+
* [Templates](./templates): Composing reusable HTML layouts.
|
|
658
|
+
* [State & Reactivity](./state): Managing state and mutation across requests.
|
package/site/index.md
CHANGED
|
@@ -3,7 +3,7 @@ layout: home
|
|
|
3
3
|
hero:
|
|
4
4
|
name: Webflo
|
|
5
5
|
text: A Web-Native Framework for the Next Gen
|
|
6
|
-
tagline: Build
|
|
6
|
+
tagline: Build backends, frontends, offline-first, and realtime apps absurdly fast.
|
|
7
7
|
image:
|
|
8
8
|
src: /img/brand/logo-670x670.png
|
|
9
9
|
width: 600px
|
|
@@ -13,7 +13,7 @@ hero:
|
|
|
13
13
|
text: Get Started
|
|
14
14
|
link: /docs/getting-started
|
|
15
15
|
- theme: brand
|
|
16
|
-
text:
|
|
16
|
+
text: What is Webflo
|
|
17
17
|
link: /overview
|
|
18
18
|
- theme: alt
|
|
19
19
|
text: Star on GitHub
|
package/site/overview.md
CHANGED
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
|
|
3
3
|
_Build the full spectrum of modern apps — backends, frontends, offline-first, and realtime apps — on raw platform power._
|
|
4
4
|
|
|
5
|
-
Welcome to the docs.
|
|
6
|
-
|
|
7
5
|
## What is Webflo
|
|
8
6
|
|
|
9
7
|
Webflo is a web-native framework that lets you build backends, frontends, offline-first, and realtime apps absurdly fast.
|