@stacksjs/defaults 0.75.250 → 0.75.253

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.
@@ -88,6 +88,8 @@ Full-page screenshot at each breakpoint and a horizontal-overflow check:
88
88
  | Wide | 1920 | 1080 |
89
89
 
90
90
  Reports `horizontalOverflowPx` per breakpoint (0 = no overflow). Shots in `storage/framework/runtime/shots/responsive/`.
91
+ Overflow is measured against the requested device width, so mobile Chrome's
92
+ automatic viewport expansion cannot hide a page wider than the device.
91
93
 
92
94
  ### Monitor (console + network)
93
95
  ```bash
@@ -115,6 +117,8 @@ bun storage/framework/defaults/ai/skills/stacks-browse/scripts/browse.ts scenari
115
117
  ```
116
118
 
117
119
  Steps run in order within one isolated browser page, preserving reactive STX state and SPA navigation. Supported actions are `click`, `fill`, `focus`, `press`, `wait`, `evaluate`, and `assert`. Each step is a JSON object passed through a repeatable `--step` flag. Click and focus steps may include `text` to select the matching control from their CSS selector. They scroll matched controls into view before interacting, including controls inside horizontal overflow regions. Evaluate steps run a JavaScript expression in the isolated page and return its serialized value, which is useful for inspecting STX signals and DevTools state between interactions. The command reports every completed step, the final URL and page text, console messages, console exceptions, failed requests, and an optional screenshot. It exits nonzero when the scenario assertion, evaluation, browser console, or network fails.
120
+ On a failed step, execution stops and the report retains its number and error,
121
+ the completed steps, final page state and requested screenshot.
118
122
  Use `{"action":"assert","selector":"...","absent":true}` to verify that an element is missing or hidden after an interaction.
119
123
  Use `{"action":"assert","selector":"button","text":"Save","focused":true}` to verify keyboard focus and focus restoration.
120
124
 
@@ -833,7 +833,9 @@ async function main() {
833
833
  const cdp = await openPage(session.port)
834
834
  const state = await gotoAndInstrument(cdp, url, { viewport: { w: bp.w, h: bp.h }, cookies, settleMs, scheme, reducedMotion: true })
835
835
  const overflow = await cdp.send('Runtime.evaluate', {
836
- expression: 'document.body.scrollWidth > window.innerWidth ? document.body.scrollWidth - window.innerWidth : 0',
836
+ // Mobile Chrome may expand innerWidth to fit overflowing content.
837
+ // Compare the page with the requested device width, not that expansion.
838
+ expression: `Math.max(0, Math.max(document.body.scrollWidth, document.documentElement.scrollWidth) - ${bp.w})`,
837
839
  returnByValue: true,
838
840
  })
839
841
  const out = join(outDir, `${bp.device.toLowerCase().replace(/\s+/g, '-')}.png`)
@@ -914,8 +916,16 @@ async function main() {
914
916
  })()`,
915
917
  })
916
918
 
919
+ let scenarioFailed = false
917
920
  for (const step of steps) {
918
- results.push(await runScenarioStep(cdp, step))
921
+ try {
922
+ results.push(await runScenarioStep(cdp, step))
923
+ }
924
+ catch (error) {
925
+ results.push({ action: step.action, ok: false, step: results.length + 1, error: error instanceof Error ? error.message : String(error) })
926
+ scenarioFailed = true
927
+ break
928
+ }
919
929
  if (step.action !== 'wait')
920
930
  await Bun.sleep(step.settle ?? 250)
921
931
  }
@@ -954,7 +964,7 @@ async function main() {
954
964
  consoleErrors: state.consoleErrors,
955
965
  failedRequests,
956
966
  }, null, 2))
957
- if (state.consoleErrors.length || failedRequests.length)
967
+ if (scenarioFailed || state.consoleErrors.length || failedRequests.length)
958
968
  process.exitCode = 1
959
969
  state.dispose()
960
970
  cdp.close()
@@ -1022,7 +1032,7 @@ async function main() {
1022
1032
  expression: `(() => ({
1023
1033
  title: document.title,
1024
1034
  links: Array.from(document.querySelectorAll('a[href]')).map(link => link.href),
1025
- overflow: Math.max(0, document.body.scrollWidth - window.innerWidth),
1035
+ overflow: Math.max(0, Math.max(document.body.scrollWidth, document.documentElement.scrollWidth) - ${crawlViewport.w}),
1026
1036
  layout: (() => {
1027
1037
  const main = document.querySelector('[data-stx-content]')
1028
1038
  return {
@@ -1031,7 +1041,7 @@ async function main() {
1031
1041
  mainClientWidth: main?.clientWidth ?? null,
1032
1042
  mainOverflowX: main ? getComputedStyle(main).overflowX : null,
1033
1043
  mainScrollWidth: main?.scrollWidth ?? null,
1034
- viewportWidth: window.innerWidth,
1044
+ viewportWidth: ${crawlViewport.w},
1035
1045
  }
1036
1046
  })(),
1037
1047
  overflowing: Array.from(document.querySelectorAll('body *'))
@@ -1076,8 +1086,8 @@ async function main() {
1076
1086
  ...(overflowContainer ? { overflowContainer } : {}),
1077
1087
  }
1078
1088
  })
1079
- .filter(item => item.width > 0 && (item.left < -1 || item.right > window.innerWidth + 1))
1080
- .sort((a, b) => Math.max(b.right - window.innerWidth, -b.left) - Math.max(a.right - window.innerWidth, -a.left))
1089
+ .filter(item => item.width > 0 && (item.left < -1 || item.right > ${crawlViewport.w} + 1))
1090
+ .sort((a, b) => Math.max(b.right - ${crawlViewport.w}, -b.left) - Math.max(a.right - ${crawlViewport.w}, -a.left))
1081
1091
  .slice(0, 10),
1082
1092
  }))()`,
1083
1093
  returnByValue: true,
@@ -52,11 +52,18 @@ re-exported CacheLock contract and selected driver separately.
52
52
  and prefix. Clone-on-read/write is enabled by default.
53
53
  `createRedisCache(options?)` accepts URL or host/port/credentials/database/TLS
54
54
  plus TTL/prefix options. `createSingleStoreCache(options?)` exposes the
55
- experimental SQL-backed cache. `createCache(driver, options?)` selects one
56
- of memory, redis or singlestore.
57
-
58
- The `cache` export is the same memory instance as `memory`. Use an explicit
59
- Redis instance for application data that must be shared across processes.
55
+ experimental SQL-backed cache. `createSqliteCache(options?)` keeps entries in
56
+ a table of a SQLite file (`path`, `table`, `prefix`, `stdTTL`), so they outlive
57
+ the process: use it for results that are expensive and safe to keep across
58
+ deploys, pointing `path` at a file the deploy preserves (the app's own SQLite
59
+ database works; the table is the driver's alone). `createCache(driver,
60
+ options?)` selects one of memory, redis, singlestore or sqlite.
61
+
62
+ The `cache` export is the driver `config/cache.ts` selects (`driver`, with
63
+ `prefix` and `ttl` applied to the non-memory drivers), resolved on first use
64
+ and once the app's config has loaded. With the default `driver: 'memory'` it
65
+ answers from the `memory` instance itself. `cacheFromConfig(settings?)` builds
66
+ the same choice explicitly; `resetConfiguredCache()` forgets it.
60
67
  The capability registry proves memory and a versioned Redis core/TTL contract;
61
68
  TLS/authenticated Redis deployments need separate provider evidence. SingleStore
62
69
  has no dedicated service conformance matrix. Source:
@@ -79,7 +86,8 @@ are distinct from StacksCache and auth's RateLimiter.
79
86
  ## Source and verification
80
87
 
81
88
  `storage/framework/core/cache/src/drivers/index.ts` is the facade/factory
82
- contract. `drivers/singlestore.ts` owns the experimental backend.
89
+ contract. `drivers/singlestore.ts` owns the experimental backend and
90
+ `drivers/sqlite.ts` the durable file-backed one (`sqlite-cache.test.ts`).
83
91
  Retained tests: `ttl.test.ts`, `getorset-timeout.test.ts`,
84
92
  `tagged-flush-race.test.ts`, `redis-contract.test.ts` and
85
93
  `cache-factory.test.ts` under `core/cache/tests/`.
@@ -15,14 +15,24 @@ ambient browser manifest is a type declaration input, not this delivery map.
15
15
  3. Explicit application-module imports are bundled separately. Their bindings
16
16
  do not leak into another imported module or magically change Ref contracts.
17
17
 
18
- Installed STX 0.2.422 delivers `useForm`, `useIntersectionObserver`,
19
- `useMouse`, `useParallax`, and `useScroll` on demand. It eagerly supplies
20
- `useMediaQuery` and `usePreferredReducedMotion` through the runtime/compiler.
18
+ Verified in STX 0.2.422: demand delivery for `useForm`, `useIntersectionObserver`,
19
+ `useMouse`, `useParallax`, and `useScroll`. The runtime/compiler eagerly supplies
20
+ `useMediaQuery` and `usePreferredReducedMotion`.
21
21
  An older installation must be checked against its own runtime and demand
22
22
  implementation rather than a newer docs list. Demand legacy helpers commonly
23
23
  expose getters, `get()`, `subscribe()`, and `stop()`. Their getters are not
24
24
  automatically signal-tracked template values.
25
25
 
26
+ STX 0.2.628 adds demand-delivered `useAnimationFrame` for canvas and simulations.
27
+ Imported TypeScript controllers use an explicit
28
+ `import { useAnimationFrame } from '@stacksjs/stx/composables'` and declare
29
+ `@stacksjs/stx` as a runtime dependency. This is a STX export, separate from
30
+ the `@stacksjs/composables` Ref API.
31
+
32
+ STX 0.2.631 keeps top-level mutable bindings live in template expressions,
33
+ including controllers assigned in `onMount` by imported TypeScript code. Use
34
+ signals for values whose changes should schedule rendering.
35
+
26
36
  ## Browser and module contracts differ
27
37
 
28
38
  | Name | STX client runtime | Explicit @stacksjs/composables |
@@ -35,6 +45,14 @@ automatically signal-tracked template values.
35
45
 
36
46
  ## Motion and observers
37
47
 
48
+ `useAnimationFrame((delta, timestamp) => ...)` supplies milliseconds and returns
49
+ `active`, `resume()`, `pause()` and permanent `stop()` controls. Hidden documents
50
+ suspend the clock and resume with zero delta; subsequent deltas default to a
51
+ 100 ms ceiling. Use fixed simulation steps rather than tying production to
52
+ frame count. Honor reduced motion when drawing decorative animation. Component
53
+ destruction registers cleanup when available; controllers with their own
54
+ disposal method call `stop()` there.
55
+
38
56
  Prefer CSS transitions or scroll-driven animation. Use the eager reduced-motion
39
57
  signal for anything beyond hover. Attach native browser observation in a mount
40
58
  hook and clean it up at component destruction:
@@ -21,9 +21,9 @@ Browser runtime bindings are documented separately in `stacks-auto-imports`.
21
21
  | `@stacksjs/auth` | [`stacks-auth`](../stacks-auth/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/auth/src/index.ts) | 119 |
22
22
  | `@stacksjs/browser` | [`stacks-browser`](../stacks-browser/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/browser/src/index.ts) | 8 |
23
23
  | `@stacksjs/browser-extension` | [`stacks-browser-extension`](../stacks-browser-extension/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/browser-extension/src/index.ts) | 7 |
24
- | `@stacksjs/buddy` | [`stacks-buddy`](../stacks-buddy/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/buddy/src/index.ts) | 153 |
24
+ | `@stacksjs/buddy` | [`stacks-buddy`](../stacks-buddy/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/buddy/src/index.ts) | 154 |
25
25
  | `@stacksjs/build` | [`stacks-build`](../stacks-build/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/build/src/index.ts) | 2 |
26
- | `@stacksjs/cache` | [`stacks-cache`](../stacks-cache/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/cache/src/index.ts) | 11 |
26
+ | `@stacksjs/cache` | [`stacks-cache`](../stacks-cache/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/cache/src/index.ts) | 13 |
27
27
  | `@stacksjs/calendar-api` | [`stacks-calendar`](../stacks-calendar/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/calendar-api/src/index.ts) | 2 |
28
28
  | `@stacksjs/charts` | [`stacks-charts`](../stacks-charts/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/charts/src/index.ts) | 3 |
29
29
  | `@stacksjs/chat` | [`stacks-chat`](../stacks-chat/SKILL.md) | [entrypoint](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/chat/src/index.ts) | 5 |
@@ -215,7 +215,7 @@ Read the entrypoint and package export map for re-exported or type-only surfaces
215
215
 
216
216
  Local source modules: [src/commands/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/buddy/src/commands/index.ts).
217
217
 
218
- Evidence directory: [153 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/buddy/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
218
+ Evidence directory: [154 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/buddy/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
219
219
 
220
220
  ### @stacksjs/build
221
221
 
@@ -233,7 +233,7 @@ Read the entrypoint and package export map for re-exported or type-only surfaces
233
233
 
234
234
  Local source modules: [src/drivers/index.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/cache/src/drivers/index.ts), [src/key.ts](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/cache/src/key.ts).
235
235
 
236
- Evidence directory: [11 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/cache/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
236
+ Evidence directory: [13 retained tests](https://github.com/stacksjs/stacks/blob/main/storage/framework/core/cache/tests). These files are evidence pointers, not a claim that all tests were run for this catalog.
237
237
 
238
238
  ### @stacksjs/calendar-api
239
239
 
@@ -2,7 +2,7 @@
2
2
  "publisher": "Stacks",
3
3
  "name": "vscode-stacks",
4
4
  "displayName": "Stacks",
5
- "version": "0.75.250",
5
+ "version": "0.75.253",
6
6
  "description": "Stacks, built into VS Code: stx templates, pickier linting and formatting, encrypted env files, the dev server preview and every buddy command. No other extensions required.",
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.250",
5
+ "version": "0.75.253",
6
6
  "repository": {
7
7
  "type": "git",
8
8
  "url": "git+https://github.com/stacksjs/stacks.git",
@@ -44,7 +44,7 @@
44
44
  "dependencies": {
45
45
  "@iconify-json/f7": "^1.2.2",
46
46
  "@iconify-json/hugeicons": "^1.2.35",
47
- "@stacksjs/mobile": "0.75.250",
47
+ "@stacksjs/mobile": "0.75.253",
48
48
  "@stacksjs/sanitizer": "^0.2.534",
49
49
  "@xterm/addon-fit": "^0.11.0",
50
50
  "@xterm/xterm": "^6.0.0",
@@ -1,230 +0,0 @@
1
- import { Request } from '../core/router/src/request'
2
-
3
- interface ValidationRule {
4
- validate: (value: unknown) => { valid: boolean, errors?: Array<{ message: string }> }
5
- }
6
-
7
- interface ValidationField {
8
- rule: ValidationRule
9
- message: Record<string, string>
10
- }
11
-
12
- interface CustomAttributes {
13
- [key: string]: ValidationField
14
- }
15
-
16
- interface RequestDataMigrations {
17
- name: string
18
- timestamp: string
19
-
20
- }
21
- export interface MigrationsRequestType extends Request {
22
- validate(attributes?: CustomAttributes): void
23
- get: <T = string>(element: string, defaultValue?: T) => T
24
- all(): RequestDataMigrations
25
- name: string
26
- timestamp: string
27
-
28
- }
29
-
30
- interface RequestDataPasswordResets {
31
- email: string
32
- token: string
33
- created_at: string
34
-
35
- }
36
- export interface PasswordResetsRequestType extends Request {
37
- validate(attributes?: CustomAttributes): void
38
- get: <T = string>(element: string, defaultValue?: T) => T
39
- all(): RequestDataPasswordResets
40
- email: string
41
- token: string
42
- created_at: string
43
-
44
- }
45
-
46
- interface RequestDataPasskeys {
47
- id: number
48
- cred_public_key: string
49
- user_id: number
50
- webauthn_user_id: string
51
- counter: number
52
- credential_type: string
53
- device_type: string
54
- backup_eligible: boolean
55
- backup_status: boolean
56
- transports: string
57
- created_at: string
58
- updated_at: string
59
- last_used_at: string
60
-
61
- }
62
- export interface PasskeysRequestType extends Request {
63
- validate(attributes?: CustomAttributes): void
64
- get: <T = string>(element: string, defaultValue?: T) => T
65
- all(): RequestDataPasskeys
66
- id: number
67
- cred_public_key: string
68
- user_id: number
69
- webauthn_user_id: string
70
- counter: number
71
- credential_type: string
72
- device_type: string
73
- backup_eligible: boolean
74
- backup_status: boolean
75
- transports: string
76
- created_at: string
77
- updated_at: string
78
- last_used_at: string
79
-
80
- }
81
-
82
- interface RequestDataCommentables {
83
- id: number
84
- title: string
85
- body: string
86
- status: string
87
- approved_at: number | null
88
- rejected_at: number | null
89
- commentables_id: number
90
- commentables_type: string
91
- user_id: number | null
92
- created_at: string
93
- updated_at: string | null
94
-
95
- }
96
- export interface CommentablesRequestType extends Request {
97
- validate(attributes?: CustomAttributes): void
98
- get: <T = string>(element: string, defaultValue?: T) => T
99
- all(): RequestDataCommentables
100
- id: number
101
- title: string
102
- body: string
103
- status: string
104
- approved_at: number | null
105
- rejected_at: number | null
106
- commentables_id: number
107
- commentables_type: string
108
- user_id: number | null
109
- created_at: string
110
- updated_at: string | null
111
-
112
- }
113
-
114
- interface RequestDataCommentableUpvotes {
115
- id: number
116
- user_id: number
117
- upvoteable_id: number
118
- upvoteable_type: string
119
- created_at: string
120
-
121
- }
122
- export interface CommentableUpvotesRequestType extends Request {
123
- validate(attributes?: CustomAttributes): void
124
- get: <T = string>(element: string, defaultValue?: T) => T
125
- all(): RequestDataCommentableUpvotes
126
- id: number
127
- user_id: number
128
- upvoteable_id: number
129
- upvoteable_type: string
130
- created_at: string
131
-
132
- }
133
-
134
- interface RequestDataCategorizable {
135
- id: number
136
- name: string
137
- slug: string
138
- description: string
139
- is_active: boolean
140
- categorizable_type: string
141
- created_at: string
142
- updated_at: string
143
-
144
- }
145
- export interface CategorizableRequestType extends Request {
146
- validate(attributes?: CustomAttributes): void
147
- get: <T = string>(element: string, defaultValue?: T) => T
148
- all(): RequestDataCategorizable
149
- id: number
150
- name: string
151
- slug: string
152
- description: string
153
- is_active: boolean
154
- categorizable_type: string
155
- created_at: string
156
- updated_at: string
157
-
158
- }
159
-
160
- interface RequestDataTaggable {
161
- id: number
162
- name: string
163
- slug: string
164
- description: string
165
- is_active: boolean
166
- taggable_type: string
167
- created_at: string
168
- updated_at: string
169
-
170
- }
171
- export interface TaggableRequestType extends Request {
172
- validate(attributes?: CustomAttributes): void
173
- get: <T = string>(element: string, defaultValue?: T) => T
174
- all(): RequestDataTaggable
175
- id: number
176
- name: string
177
- slug: string
178
- description: string
179
- is_active: boolean
180
- taggable_type: string
181
- created_at: string
182
- updated_at: string
183
-
184
- }
185
-
186
- interface RequestDataTaggableModels {
187
- id: number
188
- tag_id: number
189
- taggable_id: number
190
- taggable_type: string
191
- created_at: string
192
- updated_at: string | null
193
-
194
- }
195
- export interface TaggableModelsRequestType extends Request {
196
- validate(attributes?: CustomAttributes): void
197
- get: <T = string>(element: string, defaultValue?: T) => T
198
- all(): RequestDataTaggableModels
199
- id: number
200
- tag_id: number
201
- taggable_id: number
202
- taggable_type: string
203
- created_at: string
204
- updated_at: string | null
205
-
206
- }
207
-
208
- interface RequestDataCategorizableModels {
209
- id: number
210
- category_id: number
211
- categorizable_id: number
212
- categorizable_type: string
213
- created_at: string
214
- updated_at: string | null
215
-
216
- }
217
- export interface CategorizableModelsRequestType extends Request {
218
- validate(attributes?: CustomAttributes): void
219
- get: <T = string>(element: string, defaultValue?: T) => T
220
- all(): RequestDataCategorizableModels
221
- id: number
222
- category_id: number
223
- categorizable_id: number
224
- categorizable_type: string
225
- created_at: string
226
- updated_at: string | null
227
-
228
- }
229
-
230
- export type TraitRequest = MigrationsRequestType | PasswordResetsRequestType | PasskeysRequestType | CommentablesRequestType | CommentableUpvotesRequestType | CategorizableRequestType | TaggableRequestType | TaggableModelsRequestType | CategorizableModelsRequestType