@owlmeans/client 0.1.18-rc.5 → 0.1.18-rc.50
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 +231 -54
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/client/SKILL.md +282 -19
- package/build/consts.d.ts +8 -0
- package/build/consts.d.ts.map +1 -1
- package/build/consts.js +8 -0
- package/build/consts.js.map +1 -1
- package/build/consts.local.d.ts +10 -0
- package/build/consts.local.d.ts.map +1 -0
- package/build/consts.local.js +19 -0
- package/build/consts.local.js.map +1 -0
- package/build/context.d.ts +2 -2
- package/build/context.d.ts.map +1 -1
- package/build/context.js +1 -13
- package/build/context.js.map +1 -1
- package/build/entrypoint.d.ts +3 -0
- package/build/entrypoint.d.ts.map +1 -0
- package/build/entrypoint.js +4 -0
- package/build/entrypoint.js.map +1 -0
- package/build/helper.d.ts +1 -1
- package/build/helper.d.ts.map +1 -1
- package/build/helper.js +3 -3
- package/build/helper.js.map +1 -1
- package/build/index.d.ts +3 -1
- package/build/index.d.ts.map +1 -1
- package/build/index.js +3 -1
- package/build/index.js.map +1 -1
- package/build/lazy-retry.d.ts +47 -0
- package/build/lazy-retry.d.ts.map +1 -0
- package/build/lazy-retry.js +122 -0
- package/build/lazy-retry.js.map +1 -0
- package/build/lazy.d.ts +32 -0
- package/build/lazy.d.ts.map +1 -0
- package/build/lazy.js +114 -0
- package/build/lazy.js.map +1 -0
- package/build/navigate.d.ts.map +1 -1
- package/build/navigate.js +15 -18
- package/build/navigate.js.map +1 -1
- package/build/router.d.ts +1 -1
- package/build/router.d.ts.map +1 -1
- package/build/router.js +12 -6
- package/build/router.js.map +1 -1
- package/build/services/debug.js.map +1 -1
- package/build/store.d.ts +19 -3
- package/build/store.d.ts.map +1 -1
- package/build/store.js +57 -50
- package/build/store.js.map +1 -1
- package/build/types.d.ts +85 -7
- package/build/types.d.ts.map +1 -1
- package/build/types.local.d.ts +29 -0
- package/build/types.local.d.ts.map +1 -0
- package/build/types.local.js +2 -0
- package/build/types.local.js.map +1 -0
- package/build/utils/entrypoint.d.ts +3 -0
- package/build/utils/entrypoint.d.ts.map +1 -0
- package/build/utils/{module.js → entrypoint.js} +2 -2
- package/build/utils/entrypoint.js.map +1 -0
- package/build/utils/index.d.ts +2 -1
- package/build/utils/index.d.ts.map +1 -1
- package/build/utils/index.js +1 -1
- package/build/utils/index.js.map +1 -1
- package/build/utils/route.d.ts +2 -14
- package/build/utils/route.d.ts.map +1 -1
- package/build/utils/route.js +12 -6
- package/build/utils/route.js.map +1 -1
- package/build/utils/router.d.ts +4 -14
- package/build/utils/router.d.ts.map +1 -1
- package/build/utils/router.js +8 -8
- package/build/utils/router.js.map +1 -1
- package/build/utils/types.d.ts +15 -0
- package/build/utils/types.d.ts.map +1 -0
- package/build/utils/types.js +2 -0
- package/build/utils/types.js.map +1 -0
- package/build/utils/types.local.d.ts +6 -0
- package/build/utils/types.local.d.ts.map +1 -0
- package/build/utils/types.local.js +2 -0
- package/build/utils/types.local.js.map +1 -0
- package/package.json +22 -15
- package/src/consts.local.ts +22 -0
- package/src/consts.ts +10 -0
- package/src/context.ts +4 -21
- package/src/entrypoint.ts +6 -0
- package/src/helper.tsx +7 -11
- package/src/index.ts +3 -1
- package/src/lazy-retry.ts +133 -0
- package/src/lazy.tsx +141 -0
- package/src/navigate.ts +16 -19
- package/src/router.ts +16 -16
- package/src/services/debug.ts +2 -2
- package/src/store.ts +71 -54
- package/src/types.local.ts +32 -0
- package/src/types.ts +95 -7
- package/src/utils/entrypoint.ts +12 -0
- package/src/utils/index.ts +2 -1
- package/src/utils/route.tsx +18 -24
- package/src/utils/router.ts +11 -19
- package/src/utils/types.local.ts +6 -0
- package/src/utils/types.ts +18 -0
- package/tests/context.ts +33 -0
- package/tests/harness/index.html +11 -0
- package/tests/harness/mount.tsx +86 -0
- package/tests/harness/piece.tsx +4 -0
- package/tests/lazy-retry.spec.ts +199 -0
- package/tests/lazy.spec.ts +145 -0
- package/tsconfig.json +1 -1
- package/build/module.d.ts +0 -3
- package/build/module.d.ts.map +0 -1
- package/build/module.js +0 -4
- package/build/module.js.map +0 -1
- package/build/utils/module.d.ts +0 -3
- package/build/utils/module.d.ts.map +0 -1
- package/build/utils/module.js.map +0 -1
- package/src/module.ts +0 -6
- package/src/utils/module.ts +0 -14
package/README.md
CHANGED
|
@@ -1,92 +1,269 @@
|
|
|
1
1
|
# @owlmeans/client
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
The platform-agnostic React client framework that [`@owlmeans/web-client`](../web-client) (browser)
|
|
4
|
+
and the native client are built on. It provides the client context factory, the `App`/`Router`
|
|
5
|
+
mounts, alias-free navigation, the screen hooks (`useEntrypoint`, `useStoreModel`, `useStoreList`,
|
|
6
|
+
`useValue`, `useToggle`), and the modal and debug services. A browser application normally builds
|
|
7
|
+
its context with `makeContext` from [`@owlmeans/web-panel`](../web-panel) and mounts it with
|
|
8
|
+
`renderApp` from `@owlmeans/web-client`. `@owlmeans/web-client` does not re-export the hooks
|
|
9
|
+
listed here. `web-panel` re-exports `useNavigate`, `useValue` and `useEntrypoint`, while
|
|
10
|
+
`useStoreModel` and `useStoreList` are available only from this package. A cross-platform package
|
|
11
|
+
imports everything from here. Server code never uses this package; its equivalent is
|
|
12
|
+
[`@owlmeans/server-context`](../server-context).
|
|
12
13
|
|
|
13
14
|
## Installation
|
|
14
15
|
|
|
15
16
|
```bash
|
|
16
|
-
bun add @owlmeans/client
|
|
17
|
+
bun add @owlmeans/client@^0.1.18-rc.50
|
|
17
18
|
```
|
|
18
19
|
|
|
20
|
+
`react` and `@remix-run/router` are peer dependencies.
|
|
21
|
+
|
|
22
|
+
## Concepts
|
|
23
|
+
|
|
24
|
+
- **Client context**: `makeClientContext(cfg)` builds on `@owlmeans/client-context` and adds the
|
|
25
|
+
default state resource, the config and plugin resources, the modal and debug services, the
|
|
26
|
+
rerender hook and `context.router()`. Platform factories (`web-client`, `web-panel`) compose it,
|
|
27
|
+
and an app's own `makeContext` composes theirs.
|
|
28
|
+
- **Screen**: a frontend entrypoint protocol (`route(alias, path, frontend(...))`) bound to a
|
|
29
|
+
component with `bindScreen(protocol, handler(Component))`. The router mounts only frontend
|
|
30
|
+
entrypoints, and each nests under its `parent`.
|
|
31
|
+
- **Routed component**: a `RoutedComponent` receives `{ alias, path, params, context }`, and
|
|
32
|
+
`useEntrypoint()` reads the same values anywhere below it.
|
|
33
|
+
- **Navigator**: `useNavigate()` addresses entrypoints, not URLs. The target entrypoint builds its
|
|
34
|
+
own `url(request)`, and the active router plugin performs the navigation.
|
|
35
|
+
- **Store hooks**: `useStoreModel` and `useStoreList` subscribe to a [`@owlmeans/state`](../state)
|
|
36
|
+
resource through `useSyncExternalStore`. `useValue` renders an async result.
|
|
37
|
+
- **Modal stack**: `context.modal().request(Body)` pushes a body onto a stack rendered by a surface
|
|
38
|
+
the app mounts once, and resolves when the body answers.
|
|
39
|
+
|
|
19
40
|
## Usage
|
|
20
41
|
|
|
21
|
-
|
|
42
|
+
### Declare screens, bind them, mount the app
|
|
22
43
|
|
|
23
|
-
|
|
24
|
-
import { useStoreModel, useStoreList } from '@owlmeans/client'
|
|
44
|
+
Screen protocols are declared in the shared `common` package and bound in the web app:
|
|
25
45
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
46
|
+
```ts
|
|
47
|
+
// common: entrypoints.ts
|
|
48
|
+
import { openProtocol } from '@owlmeans/entrypoint'
|
|
49
|
+
import { DEFAULT_GUARD } from '@owlmeans/auth-common'
|
|
50
|
+
import { frontend, route } from '@owlmeans/route'
|
|
51
|
+
|
|
52
|
+
const projectBase = openProtocol(route('app:project', '/project/:projectId', frontend()), { guards: DEFAULT_GUARD })
|
|
31
53
|
|
|
32
|
-
|
|
54
|
+
export const appScreens = {
|
|
55
|
+
project: {
|
|
56
|
+
base: projectBase,
|
|
57
|
+
dashboard: openProtocol(route('app:project:dashboard', '/dashboard', frontend({ parent: projectBase }))),
|
|
58
|
+
settings: openProtocol(route('app:project:settings', '/settings', frontend({ parent: projectBase }))),
|
|
59
|
+
},
|
|
60
|
+
} as const
|
|
61
|
+
```
|
|
33
62
|
|
|
34
|
-
```
|
|
35
|
-
|
|
63
|
+
```tsx
|
|
64
|
+
// web: entrypoints.ts and main.tsx
|
|
65
|
+
import { bindAll, bindScreen, handler, renderApp } from '@owlmeans/web-client'
|
|
36
66
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
67
|
+
export const entrypoints = [
|
|
68
|
+
...bindAll({ project: appProtocols.project }), // backend calls
|
|
69
|
+
bindScreen(appScreens.project.base, handler(ProjectLayout)),
|
|
70
|
+
bindScreen(appScreens.project.dashboard, handler(DashboardScreen)),
|
|
71
|
+
bindScreen(appScreens.project.settings, handler(SettingsScreen)),
|
|
72
|
+
]
|
|
41
73
|
|
|
42
|
-
|
|
43
|
-
|
|
74
|
+
const context = makeContext(config) // the app's single factory
|
|
75
|
+
context.registerEntrypoints(entrypoints)
|
|
76
|
+
renderApp(context, undefined, <ModalSurface />) // children render before the router
|
|
44
77
|
```
|
|
45
78
|
|
|
46
|
-
|
|
79
|
+
Outside the browser (a native shell, a test harness) the platform-agnostic mount is
|
|
80
|
+
`<App context={context} />`. `noRouter` skips the router, and `provide` overrides how routes are
|
|
81
|
+
compiled.
|
|
47
82
|
|
|
48
|
-
|
|
49
|
-
|
|
83
|
+
### A routed screen that loads, stores and renders
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
import { useEntrypoint, useStoreModel, useValue } from '@owlmeans/client'
|
|
87
|
+
import type { RoutedComponent } from '@owlmeans/client'
|
|
88
|
+
|
|
89
|
+
export const DashboardScreen: RoutedComponent = () => {
|
|
90
|
+
const context = useContext() // the app's typed wrapper
|
|
91
|
+
const { params } = useEntrypoint<{ projectId?: string }>()
|
|
92
|
+
const projectId = params.projectId
|
|
50
93
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
94
|
+
// Load once per id, write the answer into the store, render from the store.
|
|
95
|
+
useValue(async cancel => {
|
|
96
|
+
if (projectId == null) {
|
|
97
|
+
return null
|
|
98
|
+
}
|
|
99
|
+
const project = await context.entrypoint(appProtocols.project.get).call({ params: { id: projectId } })
|
|
100
|
+
if (cancel?.current !== true) {
|
|
101
|
+
await context.getStateResource(PROJECTS).save(project)
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return project
|
|
105
|
+
}, [projectId])
|
|
106
|
+
|
|
107
|
+
const project = useStoreModel<Project>(projectId, PROJECTS)
|
|
108
|
+
if (project.empty) {
|
|
109
|
+
return <Spinner />
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
return <ProjectBoard project={project.record} onRename={title => project.update({ title })} />
|
|
54
113
|
}
|
|
55
114
|
```
|
|
56
115
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
### `useStoreModel<T>(id?, opts?): StateModel<T>`
|
|
116
|
+
The app's `useContext` is typically `() => useBasicContext<Config, Context>()` over the one exported
|
|
117
|
+
here (or re-exported by `web-panel`), so app-level accessors are typed.
|
|
60
118
|
|
|
61
|
-
|
|
119
|
+
### Navigate by protocol
|
|
62
120
|
|
|
63
|
-
|
|
121
|
+
```tsx
|
|
122
|
+
import { useNavigate } from '@owlmeans/client'
|
|
64
123
|
|
|
65
|
-
|
|
124
|
+
export const ProjectTabs: FC<{ projectId: string }> = ({ projectId }) => {
|
|
125
|
+
const nav = useNavigate()
|
|
66
126
|
|
|
67
|
-
|
|
127
|
+
return <nav>
|
|
128
|
+
<button onClick={nav.press(appScreens.project.dashboard, { params: { projectId } })}>Dashboard</button>
|
|
129
|
+
<button onClick={nav.press(appScreens.project.settings, { params: { projectId }, query: { tab: 'members' } })}>
|
|
130
|
+
Members
|
|
131
|
+
</button>
|
|
132
|
+
<button onClick={nav.pressBack()}>Back</button>
|
|
133
|
+
</nav>
|
|
134
|
+
}
|
|
68
135
|
|
|
69
|
-
|
|
136
|
+
// imperatively, replacing the history entry
|
|
137
|
+
await nav.go(appScreens.project.dashboard, { params: { projectId }, replace: true })
|
|
138
|
+
```
|
|
70
139
|
|
|
71
|
-
|
|
140
|
+
A URL that resolves to another service (`http…`) is assigned to `location.href` instead of being
|
|
141
|
+
pushed onto the history.
|
|
72
142
|
|
|
73
|
-
|
|
74
|
-
- `navigate(module, request?)` — navigate to a `ClientModule`
|
|
75
|
-
- `go(alias, request?)` — navigate by module alias
|
|
143
|
+
### A modal request
|
|
76
144
|
|
|
77
|
-
|
|
145
|
+
```tsx
|
|
146
|
+
import type { ModalBodyProps } from '@owlmeans/client'
|
|
147
|
+
import { createElement } from 'react'
|
|
78
148
|
|
|
79
|
-
|
|
149
|
+
const ConfirmDelete: FC<ModalBodyProps & { storyId: string }> = ({ modal, storyId }) =>
|
|
150
|
+
<Dialog.Body>
|
|
151
|
+
<Button onClick={() => modal?.response(true)}>Delete {storyId}</Button>
|
|
152
|
+
<Button onClick={() => modal?.cancel()}>Cancel</Button>
|
|
153
|
+
</Dialog.Body>
|
|
80
154
|
|
|
81
|
-
|
|
155
|
+
const onDelete = async () => {
|
|
156
|
+
const confirmed = await context.modal().request<boolean>(
|
|
157
|
+
({ modal }) => createElement(ConfirmDelete, { modal, storyId })
|
|
158
|
+
)
|
|
159
|
+
if (confirmed === true) { // null when cancelled
|
|
160
|
+
await context.entrypoint(appProtocols.story.delete).call({ params: { id: storyId } })
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
```
|
|
82
164
|
|
|
83
|
-
|
|
165
|
+
The surface is mounted once. It calls `useSetupModalNavigator()`, links a `useToggle()` to
|
|
166
|
+
`context.modal().link(toggle)` after `waitForInitialized()`, and renders
|
|
167
|
+
`context.modal().layer()?.Com` with `modal={context.modal()}`.
|
|
84
168
|
|
|
85
|
-
##
|
|
169
|
+
## API
|
|
86
170
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
171
|
+
### Context and mounting
|
|
172
|
+
|
|
173
|
+
| Symbol | Kind | Purpose |
|
|
174
|
+
|---|---|---|
|
|
175
|
+
| `makeClientContext<C, T>(cfg)` | function | Build the React client context (state, config/plugin resources, modal, debug, router accessor) |
|
|
176
|
+
| `ClientContext<C>` | type | Adds `router()`, `registerRerenderer(fn)`, `rerender()`, `modal()`, `debug()`, `getStateResource` |
|
|
177
|
+
| `App` / `AppProps` | component / type | Provide the context and, unless `noRouter`, mount the router; `children` render first |
|
|
178
|
+
| `Context`, `ClientContextContainer` | React context | The provider and the container behind it |
|
|
179
|
+
| `useContext<C, T>()` | hook | Read the current client context |
|
|
180
|
+
| `Router` / `RouterProps` | component / type | Resolve frontend entrypoints into routes; `provide` is optional |
|
|
181
|
+
| `makeRouterModel()`, `RouterModel`, `RouterProvider` | function / type | The route model and the router-provider signature |
|
|
182
|
+
| `handler(Component, preprender?)` | function | Wrap a component as an entrypoint handler for `bindScreen` |
|
|
183
|
+
|
|
184
|
+
### Screens and navigation
|
|
185
|
+
|
|
186
|
+
| Symbol | Kind | Purpose |
|
|
187
|
+
|---|---|---|
|
|
188
|
+
| `RoutedComponent<Extra>` | type | A component bound to a frontend protocol |
|
|
189
|
+
| `EntrypointContextParams<T>` | type | `{ alias, params, path, context }` |
|
|
190
|
+
| `useEntrypoint<T>()` | hook | The params of the screen currently rendering |
|
|
191
|
+
| `useNavigate()` | hook | The `Navigator` |
|
|
192
|
+
| `Navigator` | type | `navigate(entrypoint, req?)`, `go(target, req?)`, `press(target, req?)`, `back()`, `pressBack()`, `location()` |
|
|
193
|
+
| `NavRequest<T>` | type | A partial `AbstractRequest` plus `replace` and `silent` |
|
|
194
|
+
| `EntrypointTarget` | type | `EntrypointReference \| string`; application code passes protocol objects |
|
|
195
|
+
|
|
196
|
+
### State and values
|
|
197
|
+
|
|
198
|
+
| Symbol | Kind | Purpose |
|
|
199
|
+
|---|---|---|
|
|
200
|
+
| `useStoreModel<T>(id?, alias?)` | hook | One record from a state resource, live; never throws for missing data |
|
|
201
|
+
| `useStoreList<T>(opts?)` | hook | A live query `{ query?, sort?, resource? }` returning `StateModel<T>[]` |
|
|
202
|
+
| `UseStoreListOptions<T>` | type | The `useStoreList` options |
|
|
203
|
+
| `useValue<T>(loader, deps?, forceDefault?)` | hook | Render an async result; `null` (or the default) until it resolves |
|
|
204
|
+
| `UseValueParams<T>` | type | `{ default?, deps? }` |
|
|
205
|
+
| `useToggle(opened?)`, `Toggleable` | hook / type | `{ opened, open, close, set, toggle }` |
|
|
206
|
+
|
|
207
|
+
### Modal and debug services
|
|
208
|
+
|
|
209
|
+
| Symbol | Kind | Purpose |
|
|
210
|
+
|---|---|---|
|
|
211
|
+
| `appendModalService(ctx, alias?)`, `createModalService(alias?)` | function | Register or create the modal stack (`context.modal()`) |
|
|
212
|
+
| `ModalService`, `ModalStackLayer`, `ModalBodyProps`, `ModalServiceAppend` | type | `request`, `response`, `cancel`, `error`, `layer`, `link`, `stack`, `toggle` |
|
|
213
|
+
| `useSetupModalNavigator()` | hook | Give modal bodies a navigator; call once in the surface |
|
|
214
|
+
| `appendDebugService(ctx, alias?)`, `createDebugService(alias?)` | function | The debug menu, registered only when `cfg.debug.all` or `cfg.debug.debugger` is set |
|
|
215
|
+
| `appendStateDebug(ctx, alias)` | function | List a client resource under "Reset states" in the debug menu |
|
|
216
|
+
| `DebugService`, `DebugMenuItem`, `DebugServiceAppend`, `DebugConfigRecord` | type | Debug menu contracts; `context.debug()` may be `undefined` |
|
|
217
|
+
|
|
218
|
+
### Errors and constants
|
|
219
|
+
|
|
220
|
+
| Symbol | Kind | Purpose |
|
|
221
|
+
|---|---|---|
|
|
222
|
+
| `ClientError`, `ComponentError`, `ComponentPropError`, `ComponentPropUndefined` | class | The client error family, registered with `ResilientError` |
|
|
223
|
+
| `DEF_MODAL_ALIAS`, `DEF_DEBUG_ALIAS` | const | `'modal'`, `'debug'` |
|
|
224
|
+
| `DEBUGGER_FLAG`, `DEBUG_CONFIG_KEY` | const | `'debugger'` |
|
|
225
|
+
|
|
226
|
+
### Subpath `@owlmeans/client/utils`
|
|
227
|
+
|
|
228
|
+
| Symbol | Kind | Purpose |
|
|
229
|
+
|---|---|---|
|
|
230
|
+
| `buildEntrypointTree`, `visitEntrypointTree`, `EntrypointTreeVisitor` | function / type | Build and walk the frontend entrypoint tree |
|
|
231
|
+
| `initializeRouter(context)` | function | Initialize the router for a context |
|
|
232
|
+
| `createRouteRenderer`, `HandledRenderer` | function / type | Render one route with guards applied |
|
|
233
|
+
| `EntrypointContext` | React context | What `useEntrypoint` reads |
|
|
234
|
+
|
|
235
|
+
These are the pieces the router is assembled from. A package building its own routing surface
|
|
236
|
+
uses them; an application does not.
|
|
237
|
+
|
|
238
|
+
## Common pitfalls
|
|
239
|
+
|
|
240
|
+
- **Building URLs or passing alias strings in components.** Navigate with protocol objects
|
|
241
|
+
(`nav.go(protocol, { params })`) and let the entrypoint build the URL.
|
|
242
|
+
- **Resolving route params in nested components.** Read `params` from the screen props or
|
|
243
|
+
`useEntrypoint()` and pass them down.
|
|
244
|
+
- **Reading `useValue`'s second argument as a default.** An array is the dependency list, and an
|
|
245
|
+
object uses `{ default, deps }`. A bare non-array value is the default and gives no deps.
|
|
246
|
+
- **Committing after unmount in a multi-await loader.** Check `cancel.current` before writing.
|
|
247
|
+
- **Assigning into `model.record`.** Nothing re-renders. Use `model.update({ ... })`.
|
|
248
|
+
- **Importing `useNavigate`, `useEntrypoint`, `useStoreModel`, `useStoreList` or `useValue` from
|
|
249
|
+
`@owlmeans/web-client`.** It does not re-export them; import them from this package.
|
|
250
|
+
- **Requesting a modal from inside another modal body.** Closing the child also pops the parent,
|
|
251
|
+
and the parent's request never resolves. Await the first request, then issue the next.
|
|
252
|
+
- **Mounting global overlays inside a route.** They are torn down on every navigation. Pass them
|
|
253
|
+
as `App`/`renderApp` children.
|
|
254
|
+
- **Assuming `context.debug()` exists.** It is `undefined` unless the debug flags are set.
|
|
255
|
+
- **A screen whose guards all fail.** The renderer throws `AuthorizationError('frontend-guard')`, so
|
|
256
|
+
bind a login flow for guarded screens.
|
|
257
|
+
|
|
258
|
+
## Related packages
|
|
259
|
+
|
|
260
|
+
- [`@owlmeans/web-client`](../web-client): the browser layer (`renderApp`, `WebApp`, `makeContext`)
|
|
261
|
+
- [`@owlmeans/web-panel`](../web-panel): the shadcn UI context factory and navigation shell most web apps start from
|
|
262
|
+
- [`@owlmeans/state`](../state): the store `useStoreModel` / `useStoreList` read
|
|
263
|
+
- [`@owlmeans/client-entrypoint`](../client-entrypoint): `bind`, `bindAll`, `bindScreen`, typed `call`/`invoke`/`url`
|
|
264
|
+
- [`@owlmeans/client-context`](../client-context): the base client context and config
|
|
265
|
+
- [`@owlmeans/router`](../router): the router plugin `context.router()` resolves
|
|
266
|
+
- [`@owlmeans/route`](../route): `route()` and `frontend()` for screen declarations
|
|
90
267
|
|
|
91
268
|
<!-- owlmeans:agent-guidance:start -->
|
|
92
269
|
## Agent guidance
|
|
@@ -96,7 +273,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
|
|
|
96
273
|
your project's skill store (`.agents/skills/`):
|
|
97
274
|
|
|
98
275
|
```sh
|
|
99
|
-
npx @owlmeans/agent-skills
|
|
276
|
+
npx @owlmeans/agent-skills@^0.1.18-rc.48
|
|
100
277
|
```
|
|
101
278
|
|
|
102
279
|
The embedded files are version-matched to this package release. Do not edit them
|
package/agent-meta/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"package": "@owlmeans/client",
|
|
4
|
-
"version": "0.1.18-rc.
|
|
5
|
-
"generatedAt": "2026-
|
|
4
|
+
"version": "0.1.18-rc.50",
|
|
5
|
+
"generatedAt": "2026-10-05T08:32:19.112Z",
|
|
6
6
|
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|