@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.
Files changed (114) hide show
  1. package/README.md +231 -54
  2. package/agent-meta/manifest.json +2 -2
  3. package/agent-meta/skills/client/SKILL.md +282 -19
  4. package/build/consts.d.ts +8 -0
  5. package/build/consts.d.ts.map +1 -1
  6. package/build/consts.js +8 -0
  7. package/build/consts.js.map +1 -1
  8. package/build/consts.local.d.ts +10 -0
  9. package/build/consts.local.d.ts.map +1 -0
  10. package/build/consts.local.js +19 -0
  11. package/build/consts.local.js.map +1 -0
  12. package/build/context.d.ts +2 -2
  13. package/build/context.d.ts.map +1 -1
  14. package/build/context.js +1 -13
  15. package/build/context.js.map +1 -1
  16. package/build/entrypoint.d.ts +3 -0
  17. package/build/entrypoint.d.ts.map +1 -0
  18. package/build/entrypoint.js +4 -0
  19. package/build/entrypoint.js.map +1 -0
  20. package/build/helper.d.ts +1 -1
  21. package/build/helper.d.ts.map +1 -1
  22. package/build/helper.js +3 -3
  23. package/build/helper.js.map +1 -1
  24. package/build/index.d.ts +3 -1
  25. package/build/index.d.ts.map +1 -1
  26. package/build/index.js +3 -1
  27. package/build/index.js.map +1 -1
  28. package/build/lazy-retry.d.ts +47 -0
  29. package/build/lazy-retry.d.ts.map +1 -0
  30. package/build/lazy-retry.js +122 -0
  31. package/build/lazy-retry.js.map +1 -0
  32. package/build/lazy.d.ts +32 -0
  33. package/build/lazy.d.ts.map +1 -0
  34. package/build/lazy.js +114 -0
  35. package/build/lazy.js.map +1 -0
  36. package/build/navigate.d.ts.map +1 -1
  37. package/build/navigate.js +15 -18
  38. package/build/navigate.js.map +1 -1
  39. package/build/router.d.ts +1 -1
  40. package/build/router.d.ts.map +1 -1
  41. package/build/router.js +12 -6
  42. package/build/router.js.map +1 -1
  43. package/build/services/debug.js.map +1 -1
  44. package/build/store.d.ts +19 -3
  45. package/build/store.d.ts.map +1 -1
  46. package/build/store.js +57 -50
  47. package/build/store.js.map +1 -1
  48. package/build/types.d.ts +85 -7
  49. package/build/types.d.ts.map +1 -1
  50. package/build/types.local.d.ts +29 -0
  51. package/build/types.local.d.ts.map +1 -0
  52. package/build/types.local.js +2 -0
  53. package/build/types.local.js.map +1 -0
  54. package/build/utils/entrypoint.d.ts +3 -0
  55. package/build/utils/entrypoint.d.ts.map +1 -0
  56. package/build/utils/{module.js → entrypoint.js} +2 -2
  57. package/build/utils/entrypoint.js.map +1 -0
  58. package/build/utils/index.d.ts +2 -1
  59. package/build/utils/index.d.ts.map +1 -1
  60. package/build/utils/index.js +1 -1
  61. package/build/utils/index.js.map +1 -1
  62. package/build/utils/route.d.ts +2 -14
  63. package/build/utils/route.d.ts.map +1 -1
  64. package/build/utils/route.js +12 -6
  65. package/build/utils/route.js.map +1 -1
  66. package/build/utils/router.d.ts +4 -14
  67. package/build/utils/router.d.ts.map +1 -1
  68. package/build/utils/router.js +8 -8
  69. package/build/utils/router.js.map +1 -1
  70. package/build/utils/types.d.ts +15 -0
  71. package/build/utils/types.d.ts.map +1 -0
  72. package/build/utils/types.js +2 -0
  73. package/build/utils/types.js.map +1 -0
  74. package/build/utils/types.local.d.ts +6 -0
  75. package/build/utils/types.local.d.ts.map +1 -0
  76. package/build/utils/types.local.js +2 -0
  77. package/build/utils/types.local.js.map +1 -0
  78. package/package.json +22 -15
  79. package/src/consts.local.ts +22 -0
  80. package/src/consts.ts +10 -0
  81. package/src/context.ts +4 -21
  82. package/src/entrypoint.ts +6 -0
  83. package/src/helper.tsx +7 -11
  84. package/src/index.ts +3 -1
  85. package/src/lazy-retry.ts +133 -0
  86. package/src/lazy.tsx +141 -0
  87. package/src/navigate.ts +16 -19
  88. package/src/router.ts +16 -16
  89. package/src/services/debug.ts +2 -2
  90. package/src/store.ts +71 -54
  91. package/src/types.local.ts +32 -0
  92. package/src/types.ts +95 -7
  93. package/src/utils/entrypoint.ts +12 -0
  94. package/src/utils/index.ts +2 -1
  95. package/src/utils/route.tsx +18 -24
  96. package/src/utils/router.ts +11 -19
  97. package/src/utils/types.local.ts +6 -0
  98. package/src/utils/types.ts +18 -0
  99. package/tests/context.ts +33 -0
  100. package/tests/harness/index.html +11 -0
  101. package/tests/harness/mount.tsx +86 -0
  102. package/tests/harness/piece.tsx +4 -0
  103. package/tests/lazy-retry.spec.ts +199 -0
  104. package/tests/lazy.spec.ts +145 -0
  105. package/tsconfig.json +1 -1
  106. package/build/module.d.ts +0 -3
  107. package/build/module.d.ts.map +0 -1
  108. package/build/module.js +0 -4
  109. package/build/module.js.map +0 -1
  110. package/build/utils/module.d.ts +0 -3
  111. package/build/utils/module.d.ts.map +0 -1
  112. package/build/utils/module.js.map +0 -1
  113. package/src/module.ts +0 -6
  114. package/src/utils/module.ts +0 -14
package/README.md CHANGED
@@ -1,92 +1,269 @@
1
1
  # @owlmeans/client
2
2
 
3
- Core React client framework providing hooks, context, navigation, and state management for OwlMeans frontends.
4
-
5
- ## Overview
6
-
7
- - React hooks for subscribing to state stores (`useStoreModel`, `useStoreList`) and async data (`useValue`)
8
- - `useNavigate()` — module-aware navigation that resolves URLs and calls the router
9
- - `useContext()` — access the application's `ClientContext` from any React component
10
- - `useToggle()` — boolean state toggle hook
11
- - Used by every React frontend in the OwlMeans ecosystem
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
- Subscribe to a state store record:
42
+ ### Declare screens, bind them, mount the app
22
43
 
23
- ```typescript
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
- function ProjectView({ projectId }: { projectId: string }) {
27
- const model = useStoreModel<ProjectState>(projectId, 'project-state')
28
- return <div>{model.record.title}</div>
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
- Load async data:
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
- ```typescript
35
- import { useValue } from '@owlmeans/client'
63
+ ```tsx
64
+ // web: entrypoints.ts and main.tsx
65
+ import { bindAll, bindScreen, handler, renderApp } from '@owlmeans/web-client'
36
66
 
37
- function StoryList({ projectId }: { projectId: string }) {
38
- const stories = useValue(async () => {
39
- return await ctx.story().list({ criteria: { projectId } })
40
- }, [projectId])
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
- return stories ? <List items={stories.items} /> : <Loading />
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
- Navigate to a module:
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
- ```typescript
49
- import { useNavigate } from '@owlmeans/client'
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
- function CreateButton() {
52
- const navigate = useNavigate()
53
- return <button onClick={() => navigate.go('project-create')}>Create</button>
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
- ## API
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
- Returns a single `StateModel` from a state resource. Creates the record if it doesn't exist.
119
+ ### Navigate by protocol
62
120
 
63
- ### `useStoreList<T>(ids?, opts?): StateModel<T>[]`
121
+ ```tsx
122
+ import { useNavigate } from '@owlmeans/client'
64
123
 
65
- Returns multiple `StateModel` instances from a state resource.
124
+ export const ProjectTabs: FC<{ projectId: string }> = ({ projectId }) => {
125
+ const nav = useNavigate()
66
126
 
67
- ### `useValue<T>(loader, deps?, forceDefault?): T | null`
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
- Async data loader hook. Re-runs when `deps` change. Returns `null` while loading.
136
+ // imperatively, replacing the history entry
137
+ await nav.go(appScreens.project.dashboard, { params: { projectId }, replace: true })
138
+ ```
70
139
 
71
- ### `useNavigate(): Navigator`
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
- Returns a navigator with:
74
- - `navigate(module, request?)` — navigate to a `ClientModule`
75
- - `go(alias, request?)` — navigate by module alias
143
+ ### A modal request
76
144
 
77
- ### `useContext<T>(): T`
145
+ ```tsx
146
+ import type { ModalBodyProps } from '@owlmeans/client'
147
+ import { createElement } from 'react'
78
148
 
79
- Returns the current `ClientContext` cast to `T`.
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
- ### `useToggle(initial?): [boolean, () => void]`
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
- Simple boolean toggle hook.
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
- ## Related Packages
169
+ ## API
86
170
 
87
- - [`@owlmeans/state`](../state) — `StateModel`, `StateResource` used by `useStoreModel`
88
- - [`@owlmeans/client-module`](../client-module) — `ClientModule` used by `useNavigate`
89
- - [`@owlmeans/client-context`](../client-context) — `ClientContext` returned by `useContext`
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
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "package": "@owlmeans/client",
4
- "version": "0.1.18-rc.0",
5
- "generatedAt": "2026-08-16T22:20:50.506Z",
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
  {