@webqit/webflo 0.20.11 → 0.20.12-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 CHANGED
@@ -1,26 +1,16 @@
1
- <div align="center">
2
-
3
- # Webflo
4
-
5
- _A web-native framework for the next generation of apps_
1
+ # Webflo – _A next-gen, web-native framework_
6
2
 
7
3
  [![npm version][npm-version-src]][npm-version-href]<!--[![npm downloads][npm-downloads-src]][npm-downloads-href]-->
8
4
  [![License][license-src]][license-href]
9
5
 
10
- </div>
11
-
12
- <div align="center">
13
-
14
6
  _Build the full spectrum of modern applications — backends, frontends, offline-first, and realtime apps — on raw platform power._ 🛸<br>
15
7
  [Webflo ↗](https://webflo.netlify.app/overview) is a web-native framework that lets you build absurdlly fast — with the whole sophistication and scale of modern apps solved from the foundation up.
16
8
 
17
- </div>
18
-
19
9
  ---
20
10
 
21
11
  > [!IMPORTANT]
22
12
  > 🚀 **Webflo is in active development and evolving daily.** Current status = **alpha**.<br>
23
- > You’re welcome to experiment, but it’s not yet suited for production workloads.
13
+ > You’re welcome to experiment, but it’s not yet suited for production apps.
24
14
 
25
15
  ---
26
16
 
@@ -38,12 +28,12 @@ For a quick intro, see the docs:
38
28
 
39
29
  | Category | Examples & Notes |
40
30
  | :------------------------- | :--------------------------------------------------------------------------------------------------------------- |
41
- | **Web apps** | From classic MPAs to rich SPAs, hybrid SSR/CSR experiences, and full PWAs — all built on one unified framework. |
42
- | **API backends** | REST endpoints, serverless-style handlers, and webhooks with streaming, partial responses, and live messaging. |
43
- | **Static sites** | Static-first or fully pre-rendered sites that seamlessly upgrade sections to live or interactive behavior. |
44
- | **Mobile experiences** | Installable, offline-capable PWAs with background sync, worker routing, and native-feeling navigation. |
45
- | **Realtime & multiplayer** | Chats, presence, dashboards, live docs, notifications realtime channels and dialogs available out of the box. |
46
- | **AI & agents** | Multi-step AI workflows, background agents, and automation powered by Webflo’s live request lifecycle. |
31
+ | **Web apps** | Anything from classic MPAs to rich SPAs with SSR/CSR/hybrid rendering patterns. |
32
+ | **API backends** | REST endpoints and webhooks with streaming, partial responses, and live messaging. |
33
+ | **Static sites** | Static-first or fully pre-rendered sites with the same client-side richness of a Webflo app. |
34
+ | **Mobile experiences** | Installable, offline-capable PWAs with background sync, push notifications, and more. |
35
+ | **Realtime & multiplayer** | Chats, presence, dashboards, live docs, notifications realtime channels and dialogs available out of the box. |
36
+ | **AI & agents** | Multi-step AI workflows, background agents, and automation powered by Webflo’s realtime capabilities. |
47
37
 
48
38
  ---
49
39
 
@@ -51,14 +41,12 @@ For a quick intro, see the docs:
51
41
 
52
42
  | Feature | Description |
53
43
  | :------------------------------------ | :-------------------------------------------------------------------------------------------------- |
54
- | 📁 **Folder-based routing** | Filesystem routing across client, worker, and server layers, with seamless interception and flow. |
55
- | 🌍 **Full-stack routing & lifecycle** | Every request flows through browser, worker, and server layers using the same handler model. |
56
- | 🔗 **Internal API composition** | Reuse your own routes as local function calls via `next(path)` — no extra networking required. |
44
+ | 📁 **Folder-based routing** | Filesystem routing across client, service worker, and server layers. |
45
+ | 🌍 **Service Worker routing** | Support for route handlers in the service worker. |
57
46
  | 🔐 **Sessions & auth** | Built-in cookie handling, session utilities, and helpers for gated routes and user-aware flows. |
58
- | ⚡ **Realtime capabilities** | Live responses, incremental updates, dialogs, and background channelsno explicit WebSocket setup. |
47
+ | ⚡ **Realtime capabilities** | Live responses, mutable/differential responses, two-way background messagingall built in. |
59
48
  | 🧠 **Mutation-based reactivity** | State is plain objects and arrays; mutations drive reactivity via the Observer API. |
60
49
  | 🧱 **OOHTML integration** | HTML-native templates, imports, and composition without a component DSL or build-heavy toolchain. |
61
- | 📦 **Offline & worker features** | Worker-side routing, caching, background sync, and offline-first behaviors built in. |
62
50
  | 🧩 **Dev mode & HMR** | Fast development server with fine-grained rebuilds and hot updates for HTML, JS, and CSS. |
63
51
 
64
52
  ---
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "vanila-javascript"
13
13
  ],
14
14
  "homepage": "https://webqit.io/tooling/webflo",
15
- "version": "0.20.11",
15
+ "version": "0.20.12-next.0",
16
16
  "license": "MIT",
17
17
  "repository": {
18
18
  "type": "git",
@@ -45,15 +45,15 @@
45
45
  "@octokit/webhooks": "^7.15.1",
46
46
  "@webqit/backpack": "^0.1.12",
47
47
  "@webqit/oohtml-ssr": "^2.2.1",
48
- "@webqit/use-live": "^0.5.41",
48
+ "@webqit/use-live": "^0.5.44",
49
49
  "@webqit/util": "^0.8.11",
50
+ "chokidar": "^4.0.3",
50
51
  "dotenv": "^16.4.7",
51
52
  "esbuild": "^0.14.38",
53
+ "fast-glob": "^3.3.3",
52
54
  "mime-types": "^2.1.33",
53
55
  "simple-git": "^2.20.1",
54
- "urlpattern-polyfill": "^4.0.3",
55
- "chokidar": "^4.0.3",
56
- "fast-glob": "^3.3.3"
56
+ "urlpattern-polyfill": "^4.0.3"
57
57
  },
58
58
  "devDependencies": {
59
59
  "chai": "^4.3.6",
package/site/overview.md CHANGED
@@ -68,25 +68,23 @@ The service worker as a new routing site exposes this underutilized layer of the
68
68
 
69
69
  | Category | Examples & Notes |
70
70
  | :------------------------- | :--------------------------------------------------------------------------------------------------------------- |
71
- | **Web apps** | From classic MPAs to rich SPAs, hybrid SSR/CSR experiences, and full PWAs — all built on one unified framework. |
72
- | **API backends** | REST endpoints, serverless-style handlers, and webhooks with streaming, partial responses, and live messaging. |
73
- | **Static sites** | Static-first or fully pre-rendered sites that seamlessly upgrade sections to live or interactive behavior. |
74
- | **Mobile experiences** | Installable, offline-capable PWAs with background sync, worker routing, and native-feeling navigation. |
75
- | **Realtime & multiplayer** | Chats, presence, dashboards, live docs, notifications realtime channels and dialogs available out of the box. |
76
- | **AI & agents** | Multi-step AI workflows, background agents, and automation powered by Webflo’s live request lifecycle. |
71
+ | **Web apps** | Anything from classic MPAs to rich SPAs with SSR/CSR/hybrid rendering patterns. |
72
+ | **API backends** | REST endpoints and webhooks with streaming, partial responses, and live messaging. |
73
+ | **Static sites** | Static-first or fully pre-rendered sites with the same client-side richness of a Webflo app. |
74
+ | **Mobile experiences** | Installable, offline-capable PWAs with background sync, push notifications, and more. |
75
+ | **Realtime & multiplayer** | Chats, presence, dashboards, live docs, notifications realtime channels and dialogs available out of the box. |
76
+ | **AI & agents** | Multi-step AI workflows, background agents, and automation powered by Webflo’s realtime capabilities. |
77
77
 
78
78
  ## Features
79
79
 
80
80
  | Feature | Description |
81
81
  | :------------------------------------ | :-------------------------------------------------------------------------------------------------- |
82
- | 📁 **Folder-based routing** | Filesystem routing across client, worker, and server layers, with seamless interception and flow. |
83
- | 🌍 **Full-stack routing & lifecycle** | Every request flows through browser, worker, and server layers using the same handler model. |
84
- | 🔗 **Internal API composition** | Reuse your own routes as local function calls via `next(path)` — no extra networking required. |
82
+ | 📁 **Folder-based routing** | Filesystem routing across client, service worker, and server layers. |
83
+ | 🌍 **Service Worker routing** | Support for route handlers in the service worker. |
85
84
  | 🔐 **Sessions & auth** | Built-in cookie handling, session utilities, and helpers for gated routes and user-aware flows. |
86
- | ⚡ **Realtime capabilities** | Live responses, incremental updates, dialogs, and background channelsno explicit WebSocket setup. |
85
+ | ⚡ **Realtime capabilities** | Live responses, mutable/differential responses, two-way background messagingall built in. |
87
86
  | 🧠 **Mutation-based reactivity** | State is plain objects and arrays; mutations drive reactivity via the Observer API. |
88
87
  | 🧱 **OOHTML integration** | HTML-native templates, imports, and composition without a component DSL or build-heavy toolchain. |
89
- | 📦 **Offline & worker features** | Worker-side routing, caching, background sync, and offline-first behaviors built in. |
90
88
  | 🧩 **Dev mode & HMR** | Fast development server with fine-grained rebuilds and hot updates for HTML, JS, and CSS. |
91
89
 
92
90
  ## Get Started
@@ -1,4 +1,4 @@
1
- import { Observer, LiveMode } from '@webqit/use-live';
1
+ import { Observer, LiveProgramHandle } from '@webqit/use-live';
2
2
  import { _isObject, _isTypeObject } from '@webqit/util/js/index.js';
3
3
  import { publishMutations, applyMutations } from '../webflo-messaging/wq-message-port.js';
4
4
  import { WQBroadcastChannel } from '../webflo-messaging/WQBroadcastChannel.js';
@@ -22,9 +22,9 @@ export class LiveResponse extends EventTarget {
22
22
  if (isGenerator(data)) {
23
23
  return 'Generator';
24
24
  }
25
- if (data instanceof LiveMode
26
- || data?.[Symbol.toStringTag] === 'LiveMode') {
27
- return 'LiveMode';
25
+ if (data instanceof LiveProgramHandle
26
+ || data?.[Symbol.toStringTag] === 'LiveProgramHandle') {
27
+ return 'LiveProgramHandle';
28
28
  }
29
29
  return 'Default';
30
30
  }
@@ -39,8 +39,8 @@ export class LiveResponse extends EventTarget {
39
39
  if (this.test(data) === 'Generator') {
40
40
  return await this.fromGenerator(data, ...args);
41
41
  }
42
- if (this.test(data) === 'LiveMode') {
43
- return this.fromLiveMode(data, ...args);
42
+ if (this.test(data) === 'LiveProgramHandle') {
43
+ return this.fromLiveProgramHandle(data, ...args);
44
44
  }
45
45
  return new this(data, ...args);
46
46
  }
@@ -137,18 +137,18 @@ export class LiveResponse extends EventTarget {
137
137
  return instance;
138
138
  }
139
139
 
140
- static async fromLiveMode(liveMode, options = {}) {
141
- if (!this.test(liveMode) === 'LiveMode') {
142
- throw new Error('Argument must be a UseLive LiveMode instance.');
140
+ static async fromLiveProgramHandle(liveProgramHandle, options = {}) {
141
+ if (!this.test(liveProgramHandle) === 'LiveProgramHandle') {
142
+ throw new Error('Argument must be a UseLive LiveProgramHandle instance.');
143
143
  }
144
144
  const instance = new this;
145
- await instance.replaceWith(liveMode.value, { done: false, ...options });
145
+ await instance.replaceWith(liveProgramHandle.value, { done: false, ...options });
146
146
  if (instance.#generatorType === 'Default') {
147
- instance.#generator = liveMode;
148
- instance.#generatorType = 'LiveMode';
147
+ instance.#generator = liveProgramHandle;
148
+ instance.#generatorType = 'LiveProgramHandle';
149
149
  }
150
150
  Observer.observe(
151
- liveMode,
151
+ liveProgramHandle,
152
152
  'value',
153
153
  (e) => instance.#replaceWith(e.value),
154
154
  { signal: instance.#abortController.signal }
@@ -446,8 +446,8 @@ export class LiveResponse extends EventTarget {
446
446
  }));
447
447
  }
448
448
 
449
- toLiveMode({ signal: abortSignal } = {}) {
450
- const state = new LiveModeX;
449
+ toLiveProgramHandle({ signal: abortSignal } = {}) {
450
+ const state = new LiveProgramHandleX;
451
451
  const replaceHandler = () => Observer.defineProperty(state, 'value', { value: this.body, enumerable: true, configurable: true });
452
452
  this.addEventListener('replace', replaceHandler, { signal: abortSignal });
453
453
  replaceHandler();
@@ -469,7 +469,7 @@ export const isGenerator = (obj) => {
469
469
  typeof obj?.return === 'function';
470
470
  };
471
471
 
472
- class LiveModeX extends LiveMode {
472
+ class LiveProgramHandleX extends LiveProgramHandle {
473
473
  constructor() { }
474
474
  abort() { }
475
475
  }
@@ -1,6 +1,7 @@
1
1
  import { _isFunction, _isArray, _isObject } from '@webqit/util/js/index.js';
2
2
  import { _from as _arrFrom } from '@webqit/util/arr/index.js';
3
3
  import { LiveResponse } from '../webflo-fetch/LiveResponse.js';
4
+ import { request as requestShim } from '../webflo-fetch/index.js';
4
5
  import { path as Path } from '../webflo-url/util.js';
5
6
 
6
7
  export class WebfloRouter {
@@ -102,7 +103,7 @@ export class WebfloRouter {
102
103
  // Build request inheritance chain
103
104
  const requestInheritanceChain = [url];
104
105
  if (!isFetch && thisTick.event.request instanceof Request) {
105
- const { url: _, ...init } = await Request.copy(thisTick.event.request);
106
+ const { url: _, ...init } = await requestShim.copy.value(thisTick.event.request);
106
107
  requestInheritanceChain.push(init);
107
108
  }
108
109
  const noArg2 = () => {
@@ -110,7 +111,7 @@ export class WebfloRouter {
110
111
  };
111
112
  if (args[0] instanceof Request) {
112
113
  if (args[1]) noArg2();
113
- const { url: _, ...init } = await Request.copy(args[0]);
114
+ const { url: _, ...init } = await requestShim.copy.value(args[0]);
114
115
  requestInheritanceChain.push(init);
115
116
  } else if (!isFetch && _isObject(args[0])) {
116
117
  if (args[1]) noArg2();
@@ -173,7 +174,7 @@ export class WebfloRouter {
173
174
  const returnValue = await handler.call(thisContext, thisTick.event, $next/*next*/, $fetch/*fetch*/);
174
175
 
175
176
  // Handle cleanup on abort
176
- if (LiveResponse.test(returnValue) === 'LiveMode') {
177
+ if (LiveResponse.test(returnValue) === 'LiveProgramHandle') {
177
178
  thisTick.event.signal.addEventListener('abort', () => {
178
179
  returnValue.abort();
179
180
  });