@owlmeans/api-config-server 0.1.18-rc.51 → 0.1.18-rc.53

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,38 +1,122 @@
1
1
  # @owlmeans/api-config-server
2
2
 
3
- Server-side entrypoint that serves safe configuration values at `GET /assets/config.json`.
4
-
5
- ## Overview
6
-
7
- - Registers the `API_CONFIG` handler that returns non-sensitive config fields to clients
8
- - Used alongside `@owlmeans/api-config-client` to push runtime config from server to browser
9
- - Include this package's local bindings in your server entrypoint registration
3
+ The backend half of the runtime config flow: one server binding that answers the shared `advertise`
4
+ protocol of `@owlmeans/api-config` at `GET /assets/config.json` with the public subset of the
5
+ server's config. A server app uses it so its browser clients can read service routes, branding,
6
+ login settings and frontend plugins at startup instead of baking them into the bundle. An app built
7
+ on `@owlmeans/server-app` already receives it through that package's `entrypoints` and never
8
+ imports it directly. It does not decide **what** is public — packages register that with
9
+ `apiConfigPlugin()` in `@owlmeans/api-config` — and it does not fetch anything; the browser side is
10
+ `@owlmeans/api-config-client`.
10
11
 
11
12
  ## Installation
12
13
 
13
14
  ```bash
14
- bun add @owlmeans/api-config-server@^0.1.18-rc.51
15
+ bun add @owlmeans/api-config-server@^0.1.18-rc.53
15
16
  ```
16
17
 
18
+ ## Concepts
19
+
20
+ - **Advertise protocol** — `advertise` from `@owlmeans/api-config`, an open (unguarded) protocol on
21
+ route `API_CONFIG` (`'api-config:advertise'`), path `/assets/config.json`. This package only binds
22
+ it on the server.
23
+ - **Binding** — `entrypoints` is a local list of `bind(advertise, handler)` results
24
+ (`@owlmeans/server-entrypoint`), spread into the list the app registers; it is not a shared
25
+ declaration tree.
26
+ - **Advertised config** — the handler returns `advertisedConfig(ctx.cfg)`: the merge of every
27
+ `apiConfigPlugin()` registration applied to the server config. Nothing is copied generically.
28
+ - **Allowlist plugin** — an `ApiConfigPlugin` (`{ allow, deny? }`) registered at module import by a
29
+ package that owns config fields. Only packages the server process actually imports contribute.
30
+
17
31
  ## Usage
18
32
 
33
+ ### Register the binding
34
+
35
+ With `@owlmeans/server-app`, spread its `entrypoints` — they already contain this list:
36
+
37
+ ```typescript
38
+ import { entrypoints as frameworkBindings, main } from '@owlmeans/server-app'
39
+
40
+ await main(context, [...frameworkBindings, ...appBindings])
41
+ ```
42
+
43
+ A server assembled from the lower layers registers the list itself:
44
+
19
45
  ```typescript
20
46
  import { entrypoints as apiConfigBindings } from '@owlmeans/api-config-server'
21
47
 
22
- // In your server context setup: this is a local binding list, not a shared declaration tree.
23
- context.registerEntrypoints([...serverBindings, ...apiConfigBindings])
48
+ context.registerEntrypoints([...apiConfigBindings, ...serverBindings])
24
49
  ```
25
50
 
51
+ ### Make a package field public
52
+
53
+ The answer is controlled by plugins in `@owlmeans/api-config`, not by this package. A package that
54
+ owns client-relevant config registers its fields at import time; `deny` removes nested values even
55
+ under an allowed ancestor, and `every(selection, where?)` selects items of a list or map.
56
+
57
+ ```typescript
58
+ import { CONFIG_RECORD } from '@owlmeans/context'
59
+ import { apiConfigPlugin, every } from '@owlmeans/api-config'
60
+
61
+ // A whole section, minus its credential
62
+ apiConfigPlugin({
63
+ allow: { reports: true },
64
+ deny: { reports: { apiKey: true } },
65
+ })
66
+
67
+ // Only some items of a list (the pattern @owlmeans/payment uses for its config records)
68
+ apiConfigPlugin({
69
+ allow: {
70
+ [CONFIG_RECORD]: every(true, value =>
71
+ value != null && typeof value === 'object' && (value as { recordType?: string }).recordType === 'report-plan'
72
+ ),
73
+ },
74
+ })
75
+ ```
76
+
77
+ `selectApiConfig(config, plugin)` from `@owlmeans/api-config` applies one plugin without registering
78
+ it, which is how a package tests its contract.
79
+
26
80
  ## API
27
81
 
28
- ### `entrypoints`
82
+ | Export | Kind | Purpose |
83
+ |---|---|---|
84
+ | `entrypoints` | `ServerEntrypoint[]` | `[bind(advertise, handler)]` — the server binding of the runtime-config endpoint |
85
+
86
+ The handler is built with `handlers<ServerContext<ServerConfig>>().request(...)` from
87
+ `@owlmeans/server-api` and returns `advertisedConfig(context.cfg)`.
88
+
89
+ ## What is advertised
90
+
91
+ - The base registration in `@owlmeans/api-config` keeps `debug` flags (`all`, `i18n`, `supervisor`),
92
+ `brand`, `security.unsecure`, `security.auth` (`flow`, `enter`, `login`), public `services`
93
+ entries (`service`, `type`, `host`, `port`, `base`, `home`, `default`) and frontend `PLUGINS`.
94
+ - An `sservice()` route that has only `internalHost`/`internalPort` is omitted rather than exposed
95
+ through its derived `host`/`port`.
96
+ - `@owlmeans/oidc`, `@owlmeans/flow`, `@owlmeans/i18n` and `@owlmeans/payment` register their own
97
+ client settings and record types.
98
+ - SMTP, queues, databases, storage, trusted keys, secrets and every unregistered field are absent.
99
+
100
+ The `api-config-server` skill keeps this list current.
101
+
102
+ ## Common pitfalls
29
103
 
30
- Local server bindings for the shared `advertise` protocol (`GET /assets/config.json`).
104
+ - The endpoint carries no guard — it is fetched before the client has a credential — so nothing
105
+ that requires authorization to read belongs in a plugin's `allow` selection.
106
+ - Adding `apiConfigBindings` next to `@owlmeans/server-app`'s `entrypoints` is redundant — the
107
+ second registration only replaces the first under the same alias.
108
+ - A plugin registers only when its module is imported in the server process; a field the server
109
+ never imports the owning package for is not advertised.
110
+ - The package imports `@owlmeans/config` and `@owlmeans/context` without declaring them; a
111
+ standalone install must list them in its own dependencies.
31
112
 
32
- ## Related Packages
113
+ ## Related packages
33
114
 
34
- - [`@owlmeans/api-config`](../api-config) — shared types and entrypoint alias
35
- - [`@owlmeans/api-config-client`](../api-config-client) — client that fetches this endpoint
115
+ - [`@owlmeans/api-config`](../api-config) — the `advertise` protocol, `API_CONFIG`, `apiConfigPlugin`, `every`, `advertisedConfig`
116
+ - [`@owlmeans/api-config-client`](../api-config-client) — client middleware that fetches this endpoint and merges it into the client config
117
+ - [`@owlmeans/server-app`](../server-app) — server layer whose `entrypoints` already include this binding
118
+ - [`@owlmeans/server-entrypoint`](../server-entrypoint) — `bind()` and the server entrypoint type
119
+ - [`@owlmeans/server-api`](../server-api) — `handlers()` used to build the request handler
36
120
 
37
121
  <!-- owlmeans:agent-guidance:start -->
38
122
  ## Agent guidance
@@ -42,7 +126,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
42
126
  your project's skill store (`.agents/skills/`):
43
127
 
44
128
  ```sh
45
- npx @owlmeans/agent-skills@^0.1.18-rc.49
129
+ npx @owlmeans/agent-skills@^0.1.18-rc.52
46
130
  ```
47
131
 
48
132
  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-server",
4
- "version": "0.1.18-rc.51",
5
- "generatedAt": "2026-10-05T21:03:06.381Z",
4
+ "version": "0.1.18-rc.53",
5
+ "generatedAt": "2026-10-08T21:27:54.293Z",
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-server
9
9
 
10
10
  **Layer:** Server
11
- **Install:** `"@owlmeans/api-config-server": "^0.1.18-rc.51"` in `dependencies`
11
+ **Install:** `"@owlmeans/api-config-server": "^0.1.18-rc.53"` in `dependencies`
12
12
 
13
13
  Answers the declaration shared by `@owlmeans/api-config`; the browser side that consumes it is
14
14
  `@owlmeans/api-config-client`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/api-config-server",
3
- "version": "0.1.18-rc.51",
3
+ "version": "0.1.18-rc.53",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -22,8 +22,8 @@
22
22
  },
23
23
  "dependencies": {
24
24
  "@owlmeans/api-config": "^0.1.18-rc.43",
25
- "@owlmeans/server-api": "^0.1.18-rc.51",
26
- "@owlmeans/server-context": "^0.1.18-rc.43",
25
+ "@owlmeans/server-api": "^0.1.18-rc.53",
26
+ "@owlmeans/server-context": "^0.1.18-rc.44",
27
27
  "@owlmeans/server-entrypoint": "^0.1.18-rc.40"
28
28
  },
29
29
  "devDependencies": {