@stacksjs/defaults 0.75.25 → 0.75.26

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.
@@ -113,6 +113,11 @@ await withNativeFeedback(() => saveActivity())
113
113
  The runtime is browser-safe. Craft-backed operations use the native bridge;
114
114
  supported web APIs provide fallback behavior outside a native host.
115
115
 
116
+ For a run or ride, `createRouteRecorder({ location, onUpdate })` starts, pauses,
117
+ resumes and stops the native recording, re-attaches to one that outlived the
118
+ app (`attach()`), and reports live distance and pace from `routeStats(fixes)`,
119
+ which ignores GPS drift, inaccurate fixes and the ground crossed during a pause.
120
+
116
121
  ## STX components
117
122
 
118
123
  - `<NativeAppShell>` applies iOS safe-area insets and reserves tab-bar space.
@@ -32,6 +32,28 @@ route.options('/users', handler)
32
32
  route.health() // GET /health endpoint
33
33
  ```
34
34
 
35
+ ### Zero-allocation static responses
36
+
37
+ Use `staticResponse()` only when the response is final at registration time and
38
+ must bypass the request pipeline entirely:
39
+
40
+ ```typescript
41
+ route.staticResponse('GET', '/ready', new Response('{"ready":true}', {
42
+ headers: { 'content-type': 'application/json' },
43
+ }))
44
+ ```
45
+
46
+ Bun serves that `Response` directly from its native route table. No handler,
47
+ middleware, request ID, CSRF check or cookie, rate limit, request context,
48
+ security or CORS header mutation, compression, or response formatting runs.
49
+ Supply the final status, headers, and body bytes yourself.
50
+
51
+ Static responses return the router, not a chainable route, so `.middleware()`,
52
+ `.name()`, `.skipCsrf()`, `.requireCsrf()`, and `.rateLimit()` cannot be attached
53
+ and silently bypassed. A static response inside a group with middleware or
54
+ `apiResponse: true` throws during registration. Prefix-only groups are valid.
55
+ Duplicate method and path registrations keep the first response.
56
+
35
57
  ### Chainable Methods
36
58
  ```typescript
37
59
  route.get('/admin', handler)
@@ -2,7 +2,7 @@
2
2
  "publisher": "Stacks",
3
3
  "name": "vscode-stacks",
4
4
  "displayName": "Stacks",
5
- "version": "0.75.25",
5
+ "version": "0.75.26",
6
6
  "description": "A modern Stacks development environment.",
7
7
  "license": "MIT",
8
8
  "funding": "https://github.com/sponsors/chrisbbreuer",
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@stacksjs/defaults",
3
3
  "type": "module",
4
4
  "sideEffects": false,
5
- "version": "0.75.25",
5
+ "version": "0.75.26",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/stacksjs/stacks.git",
@@ -55,7 +55,7 @@
55
55
  "dependencies": {
56
56
  "@iconify-json/f7": "^1.2.2",
57
57
  "@iconify-json/hugeicons": "^1.2.27",
58
- "@stacksjs/mobile": "^0.75.25",
58
+ "@stacksjs/mobile": "^0.75.26",
59
59
  "@stacksjs/sanitizer": "^0.2.113",
60
60
  "ts-qr-codes": "^0.1.8"
61
61
  }
@@ -1,22 +1,43 @@
1
1
  <script client>
2
- import { network } from '@stacksjs/mobile'
2
+ import { lifecycle, network, whenNativeMobile } from '@stacksjs/mobile'
3
3
  import { onDestroy, onMount } from 'stx'
4
4
 
5
5
  const className = useReactiveProp<string>('class', '')
6
6
  const offlineLabel = useReactiveProp<string>('offlineLabel', 'You are offline. Changes will sync automatically.')
7
7
  const connected = state(true)
8
8
  let removeListener: (() => void) | null = null
9
+ let removeLifecycle: (() => void) | null = null
9
10
 
10
11
  function applyStatus(status: { isConnected: boolean }): void {
11
12
  connected.set(status.isConnected)
12
13
  }
13
14
 
15
+ // Asking can fail (the bridge not ready yet at launch, a request that timed
16
+ // out): that is no answer, not "offline". Treating it as offline stuck the
17
+ // banner on screen while everything was loading fine.
18
+ function refresh(): void {
19
+ void network.getStatus().then(applyStatus).catch(() => {})
20
+ }
21
+
14
22
  onMount(() => {
15
- void network.getStatus().then(applyStatus).catch(() => connected.set(false))
23
+ refresh()
16
24
  removeListener = network.onChange(applyStatus)
25
+ // Once the native host is there, ask it; and again whenever the app comes
26
+ // back to the front, where a change may have gone by unseen.
27
+ void whenNativeMobile().then(native => native && refresh())
28
+ removeLifecycle = lifecycle.onStateChange((appState) => {
29
+ if (appState === 'active') refresh()
30
+ })
17
31
  })
18
32
 
19
- onDestroy(() => removeListener?.())
33
+ // The webview's own view, for the moments the host has not spoken yet.
34
+ useEventListener('online', () => connected.set(true))
35
+ useEventListener('offline', () => refresh())
36
+
37
+ onDestroy(() => {
38
+ removeListener?.()
39
+ removeLifecycle?.()
40
+ })
20
41
  </script>
21
42
 
22
43
  <!--