@owlmeans/server-config 0.1.18-rc.8 → 0.1.18

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
@@ -11,7 +11,7 @@ Server-specific configuration utilities: `sservice()` helper and config-file rea
11
11
  ## Installation
12
12
 
13
13
  ```bash
14
- bun add @owlmeans/server-config
14
+ bun add @owlmeans/server-config@^0.1.18
15
15
  ```
16
16
 
17
17
  ## Usage
@@ -65,7 +65,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
65
65
  your project's skill store (`.agents/skills/`):
66
66
 
67
67
  ```sh
68
- npx @owlmeans/agent-skills
68
+ npx @owlmeans/agent-skills@^0.1.18
69
69
  ```
70
70
 
71
71
  The embedded files are version-matched to this package release. Do not edit them
@@ -1,8 +1,8 @@
1
1
  {
2
- "schemaVersion": 2,
2
+ "schemaVersion": 3,
3
3
  "package": "@owlmeans/server-config",
4
- "version": "0.1.18-rc.7",
5
- "generatedAt": "2026-08-24T21:14:00.132Z",
4
+ "version": "0.1.18",
5
+ "generatedAt": "2026-10-28T00:31:34.745Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: server-config
3
- description: How to use @owlmeans/server-config — server-side config helpers and validation building on @owlmeans/config. Auto-invoked when importing server config helpers.
3
+ description: How to use @owlmeans/server-config — sservice() to declare a backend service route in the config, readConfigValue() to read a value out of a mounted file, and the BasicServerConfig shape that adds secrets. Auto-invoked when building a server config, declaring a backend service, or feeding a mounted secret into config.
4
4
  user-invocable: false
5
5
  ---
6
6
  <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
@@ -8,25 +8,85 @@ user-invocable: false
8
8
  # @owlmeans/server-config
9
9
 
10
10
  **Layer:** Server
11
- **Install:** `"@owlmeans/server-config": "^0.1.18-rc.7"` in `dependencies`
11
+ **Install:** `"@owlmeans/server-config": "^0.1.18"` in `dependencies`
12
+
13
+ The server-side half of `@owlmeans/config`. Small on purpose: it declares backend services and it
14
+ reads file-backed values. Everything else about config lives in `@owlmeans/config`, and the context
15
+ that applies these is `@owlmeans/server-context`.
12
16
 
13
17
  ## Key Exports
14
18
 
15
19
  | Export | Description |
16
20
  |--------|-------------|
17
- | `Config` (server) types | Server-side Config interface (extends core Config) |
18
- | `serverConfig(...)` helpers | Build a typed server config |
19
- | Helpers | Resolve trusted entities, secret paths |
21
+ | `sservice(service, cfg?)` | Declare a backend service route into `cfg.services` and return the config |
22
+ | `readConfigValue(value, def?)` | A value starting with `/` or `file://` becomes the trimmed contents of that path; `undefined` falls back to `def`, and any other string is returned as is |
23
+ | `BasicServerConfig` | `CommonConfig` plus `secrets: Record<string, string>` |
24
+
25
+ ## Declaring services
26
+
27
+ `sservice` takes a `ServiceRoute` without `type` — `service` (the alias other routes name), `host`
28
+ / `port` for how the world reaches it, `internalHost` / `internalPort` for how the cluster does,
29
+ `base`, and `opened` (bind on all interfaces rather than loopback). It writes the entry under
30
+ `service.service` and defaults `type` to `AppType.Backend` — a default only, because the entry
31
+ already stored under that alias is spread over it: an alias first declared by `service()` from
32
+ `@owlmeans/config` as `AppType.Frontend` keeps that type through a later `sservice` call. Declare a
33
+ frontend service with `service()`.
34
+
35
+ ```typescript
36
+ import { sservice } from '@owlmeans/server-config'
37
+
38
+ let cfg = sservice({ service: MY_SERVICE, internalHost: 'my-api', internalPort: 8080, opened: true })
39
+ cfg = sservice({ service: AGENT, internalHost: 'agent', internalPort: 8081 }, cfg)
40
+ ```
41
+
42
+ **One call per service, and it carries the whole address.** The write merges over whatever the key
43
+ already held, but `host` and `port` are then set last and unconditionally from the incoming argument
44
+ alone — `host: service.host ?? service.internalHost`, `port: service.port ?? service.internalPort`.
45
+ So a second `sservice` for the same alias that names no address at all overwrites the stored `host`
46
+ and `port` with `undefined`, and the service becomes unaddressable. Amend an existing entry by
47
+ assigning the field instead:
48
+
49
+ ```typescript
50
+ cfg.services[MY_SERVICE].opened = true
51
+ ```
52
+
53
+ That last-write rule is also the mirroring rule: whenever `host` / `port` are unset, the internal
54
+ ones become them. An entry declared with `internalHost` / `internalPort` only therefore carries the
55
+ cluster address in `host` / `port` as well — which is what a client sees wherever the config is
56
+ advertised (`@owlmeans/api-config-server`), so an internal address is not a private one.
57
+
58
+ The service the process **is** — `cfg.services[cfg.service]` — is the one the API server binds:
59
+ `internalPort ?? port` is the port, and `opened` decides between `0.0.0.0` and `127.0.0.1`. A peer
60
+ service is declared the same way and is never bound, only addressed.
61
+
62
+ `@owlmeans/server-app` re-exports `sservice`, so an app on it needs no direct dependency here.
20
63
 
21
- ## Usage
64
+ ## File-backed values
65
+
66
+ `readConfigValue` is how a mounted secret becomes a config value: a string starting with `/` or
67
+ `file://` is handed to `readFileSync` and its contents trimmed, `undefined` falls back to `def`, and
68
+ every other string is returned unchanged. That makes a config literal and a mounted path
69
+ interchangeable at the same key, which is what lets a deployment inject a credential without a code
70
+ path of its own.
71
+
72
+ **Mount the secret at an absolute path.** A `file://` prefix passes the same test but is handed to
73
+ `readFileSync` as a literal string, and that does not resolve a URL: the read fails with `ENOENT`
74
+ on the URL text itself rather than returning the file. `/` is the form that works, and the only one
75
+ anything in the framework produces.
22
76
 
23
77
  ```typescript
24
- import { serverConfig } from '@owlmeans/server-config'
25
- import { AppType } from '@owlmeans/config'
78
+ import { readConfigValue } from '@owlmeans/server-config'
26
79
 
27
- const cfg = serverConfig({ service: 'my-api', type: AppType.Backend, port: 8080 })
80
+ const secret = readConfigValue(process.env.MY_SECRET, 'dev-secret')
28
81
  ```
29
82
 
83
+ Reading is synchronous and unguarded — a missing file throws where it is called. A whole config tree
84
+ is converted at once by the `fileConfigReader` middleware from `@owlmeans/server-context`, so an app
85
+ rarely calls this itself; reach for it when a value is produced outside the config tree.
86
+
87
+ `secrets` on `BasicServerConfig` is the conventional home for those values — a flat map, so every
88
+ entry can be either a literal or a path and the reader treats them alike.
89
+
30
90
  ## Depends On
31
91
 
32
- - `@owlmeans/config`, `@owlmeans/auth`, `@owlmeans/server-context`
92
+ - `@owlmeans/config`, `@owlmeans/server-route`
package/build/config.d.ts CHANGED
@@ -1,4 +1,4 @@
1
1
  import type { BasicServerConfig } from './types.js';
2
2
  import type { ServiceRoute } from '@owlmeans/server-route';
3
- export declare const sservice: <C extends BasicServerConfig>(service: Omit<ServiceRoute, "resolved" | "type">, cfg?: Partial<C>) => C;
3
+ export declare const sservice: <C extends BasicServerConfig>(service: Omit<ServiceRoute, "type">, cfg?: Partial<C>) => C;
4
4
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAC,MAAO,YAAY,CAAA;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAE1D,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS,iBAAiB,WAAW,IAAI,CAAC,YAAY,EAAE,UAAU,GAAG,MAAM,CAAC,QAAQ,OAAO,CAAC,CAAC,CAAC,KAAG,CAe1H,CAAA"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAC,MAAO,YAAY,CAAA;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA;AAE1D,eAAO,MAAM,QAAQ,GAAI,CAAC,SAAS,iBAAiB,WAAW,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,QAAQ,OAAO,CAAC,CAAC,CAAC,KAAG,CAc7G,CAAA"}
package/build/config.js CHANGED
@@ -8,7 +8,6 @@ export const sservice = (service, cfg) => {
8
8
  type: AppType.Backend,
9
9
  ..._cfg.services[service.service],
10
10
  ...service,
11
- resolved: service.host != null || service.internalHost != null,
12
11
  host: service.host ?? service.internalHost,
13
12
  port: service.port ?? service.internalPort,
14
13
  };
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAI1C,MAAM,CAAC,MAAM,QAAQ,GAAG,CAA8B,OAAgD,EAAE,GAAgB,EAAK,EAAE;IAC7H,MAAM,IAAI,GAAM,CAAC,GAAG,IAAI,EAAE,CAAM,CAAA;IAChC,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;QAC1B,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAA;IACpB,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG;QAC/B,IAAI,EAAE,OAAO,CAAC,OAAO;QACrB,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC;QACjC,GAAG,OAAO;QACV,QAAQ,EAAE,OAAO,CAAC,IAAI,IAAI,IAAI,IAAI,OAAO,CAAC,YAAY,IAAI,IAAI;QAC9D,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,YAAY;QAC1C,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,YAAY;KAC3C,CAAA;IAED,OAAO,IAAI,CAAA;AACb,CAAC,CAAA"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AAI1C,MAAM,CAAC,MAAM,QAAQ,GAAG,CAA8B,OAAmC,EAAE,GAAgB,EAAK,EAAE;IAChH,MAAM,IAAI,GAAM,CAAC,GAAG,IAAI,EAAE,CAAM,CAAA;IAChC,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,EAAE,CAAC;QAC1B,IAAI,CAAC,QAAQ,GAAG,EAAE,CAAA;IACpB,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG;QAC/B,IAAI,EAAE,OAAO,CAAC,OAAO;QACrB,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC;QACjC,GAAG,OAAO;QACV,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,YAAY;QAC1C,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,YAAY;KAC3C,CAAA;IAED,OAAO,IAAI,CAAA;AACb,CAAC,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/server-config",
3
- "version": "0.1.18-rc.8",
3
+ "version": "0.1.18",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -21,12 +21,12 @@
21
21
  }
22
22
  },
23
23
  "dependencies": {
24
- "@owlmeans/config": "^0.1.18-rc.8",
25
- "@owlmeans/server-route": "^0.1.18-rc.6"
24
+ "@owlmeans/config": "^0.1.18",
25
+ "@owlmeans/server-route": "^0.1.18"
26
26
  },
27
27
  "devDependencies": {
28
- "@owlmeans/dep-config": "workspace:*",
29
- "@types/node": "^26.1.0",
28
+ "@owlmeans/dep-config": "^0.1.18",
29
+ "@types/node": "^26.6.4",
30
30
  "nodemon": "^3.1.14",
31
31
  "typescript": "^7.0.2"
32
32
  },
package/src/config.ts CHANGED
@@ -3,16 +3,15 @@ import { AppType } from '@owlmeans/config'
3
3
  import type { BasicServerConfig} from './types.js'
4
4
  import type { ServiceRoute } from '@owlmeans/server-route'
5
5
 
6
- export const sservice = <C extends BasicServerConfig>(service: Omit<ServiceRoute, "resolved" | "type">, cfg?: Partial<C>): C => {
6
+ export const sservice = <C extends BasicServerConfig>(service: Omit<ServiceRoute, "type">, cfg?: Partial<C>): C => {
7
7
  const _cfg: C = (cfg ?? {}) as C
8
8
  if (_cfg.services == null) {
9
9
  _cfg.services = {}
10
10
  }
11
- _cfg.services[service.service] = {
12
- type: AppType.Backend,
13
- ..._cfg.services[service.service],
14
- ...service,
15
- resolved: service.host != null || service.internalHost != null,
11
+ _cfg.services[service.service] = {
12
+ type: AppType.Backend,
13
+ ..._cfg.services[service.service],
14
+ ...service,
16
15
  host: service.host ?? service.internalHost,
17
16
  port: service.port ?? service.internalPort,
18
17
  }
package/build/.gitkeep DELETED
File without changes