@owlmeans/api-config-client 0.1.18-rc.45 → 0.1.18-rc.47

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,44 +1,111 @@
1
1
  # @owlmeans/api-config-client
2
2
 
3
- Client-side middleware that fetches server config from `GET /assets/config.json` and merges it into the client context.
4
-
5
- ## Overview
6
-
7
- - `apiConfigMiddleware` — context middleware that calls the config endpoint on startup
8
- - Binds the `@owlmeans/api-config` `advertise` protocol into the client entrypoint system
9
- - Merges the server `ApiConfig` into the client's `CommonConfig` at initialization time
3
+ Client-side middleware that fetches server config from `GET /assets/config.json` and merges it into
4
+ the client context. It is the browser half of the runtime config flow: `@owlmeans/api-config`
5
+ declares the `advertise` protocol and the public-field allowlist, `@owlmeans/api-config-server`
6
+ answers it, and this package binds and calls it during `init()`. An app built on
7
+ `@owlmeans/web-panel` or `@owlmeans/mui-panel` already has both halves wired and does not touch
8
+ this package; a client context built from a lower layer registers it itself. Config that is fixed at
9
+ build time needs no runtime fetch — use `@owlmeans/client-config` for that. The package's skill is
10
+ `api-config-client`.
10
11
 
11
12
  ## Installation
12
13
 
13
14
  ```bash
14
- bun add @owlmeans/api-config-client@^0.1.18-rc.45
15
+ bun add @owlmeans/api-config-client@^0.1.18-rc.47
15
16
  ```
16
17
 
18
+ The middleware imports `mergeConfig` from `@owlmeans/config`, which this package's manifest does not
19
+ declare; a standalone install adds `@owlmeans/config` to its own dependencies.
20
+
21
+ ## Concepts
22
+
23
+ - **Advertise protocol** — `advertise` from `@owlmeans/api-config`, alias `API_CONFIG`
24
+ (`'api-config:advertise'`), an open sticky route at `/assets/config.json`.
25
+ - **Binding** — `entrypoints`, this package's `[bind(advertise)]`: the client entrypoint the
26
+ middleware resolves by alias.
27
+ - **Middleware** — `apiConfigMiddleware`, a `Context` / `Loading` middleware: it runs once during
28
+ `init()`, after every service and resource has initialized and before the context becomes ready.
29
+ - **Primary host** — `cfg.primaryHost` / `cfg.primaryPort`: where the config is fetched from. The
30
+ fetch happens only when `primaryHost` is set; `@owlmeans/web-client` fills both from
31
+ `window.location`.
32
+ - **Merge** — the answer is merged into `context.cfg` in place with `configHelper.mergeConfig`.
33
+
17
34
  ## Usage
18
35
 
19
- Register the middleware in your client context setup:
36
+ ### Wire both halves in a lower-layer client context
37
+
38
+ The middleware does the work; the binding is what it calls. Registering one without the other fails
39
+ the boot.
40
+
41
+ ```typescript
42
+ import { makeClientContext } from '@owlmeans/client-context'
43
+ import { apiConfigMiddleware, entrypoints as apiConfigBindings } from '@owlmeans/api-config-client'
44
+
45
+ export const makeContext = <C extends AppConfig, T extends AppContext<C>>(cfg: C): T => {
46
+ const context = makeClientContext<C, T>(cfg)
47
+ context.registerMiddleware(apiConfigMiddleware)
48
+
49
+ return context
50
+ }
51
+
52
+ export const clientBindings = [...apiConfigBindings, ...myClientBindings]
53
+ ```
54
+
55
+ ### Point the fetch at a backend
20
56
 
21
57
  ```typescript
22
- import { apiConfigMiddleware } from '@owlmeans/api-config-client'
58
+ const context = makeContext({
59
+ ...config,
60
+ primaryHost: 'app.example.com',
61
+ primaryPort: 8443,
62
+ })
63
+
64
+ await context.configure().init() // fetches /assets/config.json from app.example.com:8443 and merges it
65
+ ```
23
66
 
24
- context.registerMiddleware(apiConfigMiddleware)
67
+ ### Read merged values at render or request time
68
+
69
+ ```typescript
70
+ const brand = context.cfg.brand // the server's value once init() has resolved
25
71
  ```
26
72
 
27
- On initialization, the middleware calls the bound `advertise` protocol and merges the response into
28
- the context config. If this package's local `entrypoints` bindings are not registered, initialization
29
- fails rather than silently falling back to alias-based calls.
73
+ A service that copied a config value during its own `init()` keeps the bundled value — the merge
74
+ happens after service initialization.
30
75
 
31
76
  ## API
32
77
 
33
- ### `apiConfigMiddleware: Middleware`
78
+ | Symbol | Kind | Purpose |
79
+ |---|---|---|
80
+ | `apiConfigMiddleware` | `Middleware` | `Context` / `Loading`; resolves `API_CONFIG`, sets the route's `host`/`port` from `cfg.primaryHost`/`cfg.primaryPort`, calls it and merges the `ApiConfig` answer into `context.cfg` |
81
+ | `entrypoints` | `ClientEntrypoint[]` | `[bind(advertise)]` — the browser-local binding of the shared runtime-config protocol |
82
+
83
+ ### Merge behaviour
84
+
85
+ `configHelper.mergeConfig` merges objects key by key and appends arrays. A server value replaces the
86
+ bundled one only where the bundled value is a scalar, `null` or absent; a scalar sent for a bundled
87
+ object or array is dropped silently, and a bundled array grows on every merge.
88
+
89
+ ## Common pitfalls
34
90
 
35
- A context initialization middleware. Calls the `advertise` protocol, receives `ApiConfig`, and
36
- applies it to the context via `mergeConfig`.
91
+ - Registering `apiConfigMiddleware` without the `entrypoints` bindings — `init()` throws
92
+ `SyntaxError: Entrypoint api-config:advertise not found` rather than silently falling back.
93
+ - No `cfg.primaryHost` — the middleware does nothing and the app runs on the bundled config.
94
+ - A failed fetch is logged (`API config not loaded`) and swallowed; an unreachable backend shows up
95
+ as missing values later, never as a boot error.
96
+ - Registering the pair again on a `web-panel` / `mui-panel` context — those factories already do it.
97
+ - Expecting the server to empty or replace a bundled array — the merge only appends.
98
+ - Only fields an `apiConfigPlugin` allows are advertised; a value missing on the client may simply
99
+ not be exposed by the server.
37
100
 
38
- ## Related Packages
101
+ ## Related packages
39
102
 
40
- - [`@owlmeans/api-config`](../api-config) — `API_CONFIG` alias and `ApiConfig` type
103
+ - [`@owlmeans/api-config`](../api-config) — `API_CONFIG`, the `advertise` protocol, `ApiConfig` and the field allowlist
41
104
  - [`@owlmeans/api-config-server`](../api-config-server) — server that serves the config endpoint
105
+ - [`@owlmeans/config`](../config) — `configHelper.mergeConfig`
106
+ - [`@owlmeans/client-entrypoint`](../client-entrypoint) — `bind`, the client entrypoint binding
107
+ - [`@owlmeans/client-context`](../client-context) — the client context and `primaryHost` / `primaryPort`
108
+ - [`@owlmeans/web-panel`](../web-panel) — a panel factory that already wires this package
42
109
 
43
110
  <!-- owlmeans:agent-guidance:start -->
44
111
  ## Agent guidance
@@ -48,7 +115,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
48
115
  your project's skill store (`.agents/skills/`):
49
116
 
50
117
  ```sh
51
- npx @owlmeans/agent-skills@^0.1.18-rc.49
118
+ npx @owlmeans/agent-skills@^0.1.18-rc.52
52
119
  ```
53
120
 
54
121
  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/api-config-client",
4
- "version": "0.1.18-rc.45",
5
- "generatedAt": "2026-10-05T21:03:06.399Z",
4
+ "version": "0.1.18-rc.47",
5
+ "generatedAt": "2026-10-08T21:27:54.305Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -8,7 +8,7 @@ user-invocable: false
8
8
  # @owlmeans/api-config-client
9
9
 
10
10
  **Layer:** Client
11
- **Install:** `"@owlmeans/api-config-client": "^0.1.18-rc.45"` in `dependencies`
11
+ **Install:** `"@owlmeans/api-config-client": "^0.1.18-rc.47"` in `dependencies`
12
12
 
13
13
  Consumes the declaration shared by `@owlmeans/api-config` and answered by
14
14
  `@owlmeans/api-config-server`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/api-config-client",
3
- "version": "0.1.18-rc.45",
3
+ "version": "0.1.18-rc.47",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -22,10 +22,10 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "@owlmeans/api-config": "^0.1.18-rc.43",
25
- "@owlmeans/client-context": "^0.1.18-rc.48",
26
- "@owlmeans/client-entrypoint": "^0.1.18-rc.47",
25
+ "@owlmeans/client-context": "^0.1.18-rc.50",
26
+ "@owlmeans/client-entrypoint": "^0.1.18-rc.49",
27
27
  "@owlmeans/context": "^0.1.18-rc.34",
28
- "@owlmeans/log": "^0.1.18-rc.2"
28
+ "@owlmeans/log": "^0.1.18-rc.3"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@owlmeans/dep-config": "workspace:*",