@owlmeans/server-app 0.1.18-rc.20 → 0.1.18-rc.22

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
@@ -6,7 +6,6 @@ The main entry point for OwlMeans backend services — aggregates server package
6
6
 
7
7
  - `makeContext(cfg)` creates a fully initialized server context with Fastify, auth, WebSocket, and static resource support
8
8
  - `main(ctx, entrypoints)` registers entrypoints, initializes the context, and starts the HTTP server
9
- - `holdApiPort` + the boot-state module give a bind-first boot: the port answers for the app before it initializes
10
9
  - Re-exports the most commonly used symbols from lower-level packages so backend code has a single import target
11
10
  - Used by every service in the viable monorepo
12
11
 
@@ -34,56 +33,19 @@ const context = makeContext(appConfig)
34
33
  await main(context, [...entrypoints, ...appEntrypoints])
35
34
  ```
36
35
 
37
- Elevate an entrypoint with a handler:
36
+ Bind a shared protocol with a handler:
38
37
 
39
38
  ```typescript
40
- import { elevate, handleBody, guard, GUARD_ED25519 } from '@owlmeans/server-app'
41
- import { appEntrypoints } from './entrypoints'
42
-
43
- elevate(appEntrypoints, 'project-create', handleBody<CreateProject>(async (payload, ctx) => {
44
- return await (ctx as Context).project().create(payload)
45
- }), guard(GUARD_ED25519))
46
- ```
47
-
48
- ### Bind-first boot
49
-
50
- `main()` is the short path. An app that must explain a **failed** boot binds the port first instead,
51
- so a startup failure has somewhere to be reported from — without a listener the edge answers a bare
52
- connect error that names neither the app nor the cause:
53
-
54
- ```typescript
55
- import { holdApiPort, bootHold, setBootPhase, bootHealthPayload } from '@owlmeans/server-app'
56
-
57
- const hold = await holdApiPort(ctx.cfg, bootHold(HEALTH_PATH)).catch((error: Error) => {
58
- // A failure to BIND is fatal: carried past, the boot ends with nothing listening and exits 0
59
- // while a predecessor keeps serving stale code. Exit non-zero so a supervisor reclaims the port.
60
- console.error(`[boot] STARTUP FAILED — ${error.message}`)
61
- process.exit(1)
62
- })
63
-
64
- try {
65
- await ctx.configure().init()
66
- } catch (error) {
67
- // Stay alive: the hold is the only thing that can explain why nothing is serving.
68
- setBootPhase('failed', (error as Error).message)
69
- return
70
- }
71
-
72
- await hold.release() // awaited — `listen()` throws while a predecessor holds the socket
73
- setBootPhase('ready')
74
- await ctx.getApiServer().listen()
75
- ```
76
-
77
- The hold answers `HEALTH_PATH` with `bootHealthPayload()` and everything else with **503** (not 404
78
- — the real routes do not exist yet). Once the app's own server takes the socket, its health handler
79
- spreads the same `bootHealthPayload()` into its answer, so a consumer polling across the handover
80
- never sees the body change under it:
81
-
82
- ```typescript
83
- export const handleHealtz = handleRequest(async (_req, ctx) => ({
84
- ...bootHealthPayload(),
85
- db: await pingDb(ctx)
86
- }))
39
+ import { bind } from '@owlmeans/server-entrypoint'
40
+ import { handlers } from '@owlmeans/server-api'
41
+ import { appEntrypoints as protocols } from 'my-app-common'
42
+ import type { Context } from 'my-app-backend'
43
+
44
+ const api = handlers<Context>()
45
+ const appEntrypoints = [
46
+ bind(protocols.api.projectCreate, api.request(protocols.api.projectCreate, async (req, ctx) =>
47
+ (ctx as Context).project().create(req.body))),
48
+ ]
87
49
  ```
88
50
 
89
51
  ## API
@@ -96,30 +58,12 @@ Creates a server context with Fastify HTTP, WebSocket, static resources, and aut
96
58
 
97
59
  Registers entrypoints, calls `configure().init()`, then starts the Fastify server.
98
60
 
99
- ### Boot state
100
-
101
- Process-wide boot phase, shared by the port hold and the app's own health handler.
102
-
103
- | Symbol | Description |
104
- |---|---|
105
- | `setBootPhase(phase, detail?)` | Record the phase; `detail` is free text kept for every phase |
106
- | `getBootPhase(): BootPhase` / `getBootDetail()` | Current phase and its detail |
107
- | `bootHealthPayload(): BootHealth` | `{ status, phase, ok, reason?, bootId, pid }` — the health body |
108
- | `bootHold(okPath?): ApiPortHoldOptions` | `holdApiPort` options wired to this module |
109
- | `BootPhase` | `'initializing' \| 'ready' \| 'failed'` |
110
- | `BOOT_ID_ENV` | `'OWLMEANS_BOOT_ID'` — a supervisor stamps the child, `bootId` echoes it back |
111
-
112
- `bootId` is identity, not health: an answer carrying an id other than the one the supervisor spawned
113
- means a leftover process still owns the port and the health it reports describes code nobody asked
114
- for.
115
-
116
61
  ### Re-exported symbols (for convenience)
117
62
 
118
63
  | Symbol | Source |
119
64
  |---|---|
120
- | `handleBody`, `handleParams`, `handleRequest` | `@owlmeans/server-api` |
121
- | `elevate`, `entrypoint`, `guard` | `@owlmeans/server-entrypoint` |
122
- | `celevate` | `@owlmeans/client-entrypoint` |
65
+ | `handlers` | `@owlmeans/server-api` |
66
+ | `bind`, `bindAll`, `guard` | `@owlmeans/server-entrypoint` |
123
67
  | `route` | `@owlmeans/route` |
124
68
  | `broute` | `@owlmeans/server-route` |
125
69
  | `filter`, `body`, `params`, `EntrypointOutcome` | `@owlmeans/entrypoint` |
@@ -129,7 +73,7 @@ for.
129
73
  | `GUARD_ED25519`, `BED255_CASHE_RESOURCE` | `@owlmeans/auth-common` |
130
74
  | `klusterize` | `@owlmeans/kluster` |
131
75
  | `createListSchema`, `filterObject` | `@owlmeans/resource` |
132
- | `Request`, `Response`, `ClientEntrypoint`, `RefedEntrypointHandler` | type re-exports |
76
+ | `Request`, `Response`, `RefedEntrypointHandler` | type re-exports |
133
77
  | `Criteria`, `ListOptions`, `ListQuery`, `ListResult`, `Sort` | type re-exports from `@owlmeans/resource` |
134
78
 
135
79
  ### `entrypoints`
@@ -142,8 +86,8 @@ await main(context, [...entrypoints, ...myEntrypoints])
142
86
  ## Related Packages
143
87
 
144
88
  - [`@owlmeans/server-context`](../server-context) — `makeServerContext` called internally by `makeContext`
145
- - [`@owlmeans/server-api`](../server-api) — handler wrappers re-exported here
146
- - [`@owlmeans/server-entrypoint`](../server-entrypoint) — `elevate` re-exported here
89
+ - [`@owlmeans/server-api`](../server-api) — typed handler factories re-exported here
90
+ - [`@owlmeans/server-entrypoint`](../server-entrypoint) — protocol binding helpers
147
91
 
148
92
  <!-- owlmeans:agent-guidance:start -->
149
93
  ## Agent guidance
@@ -153,7 +97,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
153
97
  your project's skill store (`.agents/skills/`):
154
98
 
155
99
  ```sh
156
- npx @owlmeans/agent-skills@^0.1.18-rc.14
100
+ npx @owlmeans/agent-skills@^0.1.18-rc.16
157
101
  ```
158
102
 
159
103
  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/server-app",
4
- "version": "0.1.18-rc.20",
5
- "generatedAt": "2026-09-10T23:12:07.512Z",
4
+ "version": "0.1.18-rc.22",
5
+ "generatedAt": "2026-09-12T12:32:46.374Z",
6
6
  "canonicalRepo": "https://github.com/owlmeans/common",
7
7
  "entries": [
8
8
  {
@@ -1,213 +1,43 @@
1
1
  ---
2
2
  name: server-app
3
- description: How to use @owlmeans/server-app — main() entry point, makeContext(), the bind-first boot (holdApiPort + boot state), handleRequest()/handleBody() handler wrappers, elevate()/celevate() to attach handlers to entrypoint declarations, and the config and entrypoint builders it re-exports. Auto-invoked when working with the server entry point, the server context factory, or request handlers.
4
- user-invocable: false
3
+ description: Build OwlMeans server applications from immutable entrypoint protocol declarations. Use when starting a server, binding endpoint implementations, configuring services, or registering server entrypoints.
5
4
  ---
6
5
  <!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
7
6
 
8
- # @owlmeans/server-app
7
+ # Server application entrypoints
9
8
 
10
- **Layer:** Server
11
- **Install:** `"@owlmeans/server-app": "^0.1.18-rc.20"` in `dependencies`
9
+ Declare routes and request/response contracts in a shared package with `protocol()` or
10
+ `openProtocol()`. A server package supplies local implementations with `bind()` and `handlers()`;
11
+ it never changes a shared declaration by alias.
12
12
 
13
- The one package a backend application depends on directly. It assembles the server context, owns the
14
- process entry point, and re-exports everything an app needs to declare its config, its entrypoints
15
- and its handlers — so an app on it rarely imports the server layer packages by name.
13
+ ```ts
14
+ import { bind, entrypoints, handlers } from '@owlmeans/server-app'
15
+ import { projectEntrypoints } from 'project-common'
16
+ import { createProject } from './app/project.js'
16
17
 
17
- ## Key Exports
18
+ const api = handlers<Context>()
18
19
 
19
- | Export | Description |
20
- |--------|-------------|
21
- | `main<R, C, T>(ctx, entrypoints)` | Entry point — registers all entrypoints, configures/inits the context, then boots the Fastify API server (`@owlmeans/server-api`) |
22
- | `makeContext(cfg, customize?)` | Build the server context with API server, API client, sockets, static resource and auth appended |
23
- | `AppConfig`, `AppContext<C>` | The config and context types an app extends |
24
- | `entrypoints` | Built-in system entrypoints — the auth endpoints plus the api-config advertise endpoint; spread into `appEntrypoints` |
25
-
26
- ### Building the config
27
-
28
- | Export | Description |
29
- |--------|-------------|
30
- | `config(service, cfg?)` | Start a server config for this service |
31
- | `sservice(service, cfg?)` | Declare a backend service route into `cfg.services` |
32
- | `addWebService(service, alias?, cfg?)` | Declare a frontend service the app addresses |
33
- | `service(route, cfg?)`, `toConfigRecord(obj)`, `PLUGINS` | Generic service declaration and config records |
34
- | `AppType`, `BASE` | The app-type enum, and `base` — the alias of the intermediate area whose children require authentication |
35
- | `PluginConfig` | Plugin config record shape |
36
-
37
- ### Declaring and elevating entrypoints
38
-
39
- | Export | Description |
40
- |--------|-------------|
41
- | `entrypoint(...)`, `route(...)`, `broute(...)` | Declaration builders — `entrypoint` from server-entrypoint (it builds a `ServerEntrypoint`), `route` from route, `broute` from server-route |
42
- | `elevate(entrypoints, alias, handler?, opts?)` | Attach a handler to an entrypoint declaration |
43
- | `celevate(entrypoints, alias, handler?, opts?)` | Make a declaration client-callable from the server side |
44
- | `guard(alias, opts?)` | Options requiring a guard |
45
- | `DAUTH_GUARD` | Alias of the default auth guard (`auth`) |
46
- | `GUARD_ED25519`, `BED255_CASHE_RESOURCE` | The service-to-service signature guard and its nonce cache |
47
- | `filter`, `body`, `params`, `EntrypointOutcome` | Validators and the outcome enum |
48
-
49
- ### Writing handlers
50
-
51
- | Export | Description |
52
- |--------|-------------|
53
- | `handleRequest(fn)` | Wrap an async function as a server handler `(req, context) => result` |
54
- | `handleBody<T>(fn)` | Wrap an async function with validated body — `(payload, context, req) => result` |
55
- | `handleParams<T>(fn)` | The same, over validated URL params |
56
- | `Request`, `Response`, `Module`, `RefedEntrypointHandler`, `ClientEntrypoint` | Handler and entrypoint types |
57
- | `createListSchema(schema)`, `filterObject(obj, keep?)` | List-result schema and object whitelisting |
58
- | `Criteria`, `ListOptions`, `ListQuery`, `ListResult`, `Sort` | Resource query types |
59
- | `assertContext(ctx, location?)` | Narrow a possibly-undefined context, throwing where it is missing |
60
-
61
- ### Booting
62
-
63
- | Export | Description |
64
- |--------|-------------|
65
- | `holdApiPort(cfg, opts?)` | Own the app's port during boot |
66
- | `ApiPortHold`, `ApiPortHoldOptions` | The hold handle and its options |
67
- | `setBootPhase(phase, detail?)` | Record the process boot phase — `'initializing' \| 'ready' \| 'failed'` |
68
- | `getBootPhase()` / `getBootDetail()` | Read it back |
69
- | `bootHealthPayload()` | The health body: `{ status, phase, ok, reason?, bootId, pid }` |
70
- | `bootHold(okPath?)` | `holdApiPort` options wired to the boot state |
71
- | `BootPhase`, `BootHealth`, `BOOT_ID_ENV` | Boot-state types and the supervisor's boot-id env var |
72
- | `klusterize(ctx, alias?)` | Register the cluster client and its config-directive middleware |
73
-
74
- ## Usage
75
-
76
- ### Entry point
77
- ```typescript
78
- // index.ts
79
- import { main } from '@owlmeans/server-app'
80
- import config from './config.js'
81
- import { makeContext } from './context.js'
82
- import { appEntrypoints } from './entrypoints.js'
83
-
84
- const context = makeContext(config)
85
- main<{}, Config, Context>(context, appEntrypoints)
86
- ```
87
-
88
- `makeContext(cfg, customize)` appends the API server, the API client, the socket service and its
89
- middleware, and the static resource. Passing `customize: true` — or having already registered the
90
- auth cache resource — leaves the auth service and its cache out, which is what an app that supplies
91
- its own authentication does.
92
-
93
- ### Bind-first boot
94
-
95
- An app that must be able to explain a *failed* boot does not call `main()`; it binds the port
96
- first, so the failure has somewhere to be reported from. Never hand-roll the phase module —
97
- `boot-state` is it.
98
-
99
- ```typescript
100
- import { holdApiPort, bootHold, setBootPhase, bootHealthPayload } from '@owlmeans/server-app'
101
-
102
- const hold = await holdApiPort(ctx.cfg, bootHold(HEALTH_PATH)).catch((error: Error) => {
103
- console.error(`[boot] STARTUP FAILED — ${error.message}`)
104
- process.exit(1) // a bind failure is fatal — see below
105
- })
106
-
107
- try {
108
- await ctx.configure().init()
109
- } catch (error) {
110
- setBootPhase('failed', (error as Error).message)
111
- return // stay alive: the hold is the only thing that can explain the failure
112
- }
113
-
114
- await hold.release()
115
- setBootPhase('ready')
116
- await ctx.getApiServer().listen()
20
+ export const appEntrypoints = [
21
+ ...entrypoints,
22
+ bind(projectEntrypoints.base),
23
+ bind(projectEntrypoints.create, api.body(projectEntrypoints.create, createProject)),
24
+ ]
117
25
  ```
118
26
 
119
- Rules this encodes:
120
-
121
- - **Bind before you initialize.** Everything after the bind can fail, and a failure before it is
122
- invisible — the edge answers a bare connect error naming neither the app nor the reason.
123
- - **A bind failure exits non-zero.** Carried past, the boot ends with nothing listening and nothing
124
- holding the event loop: a clean exit 0 while a predecessor keeps serving stale code.
125
- - **A failed init returns rather than exits.** The hold keeps answering `HEALTH_PATH` with
126
- `phase: 'failed'` and the reason; everything else gets 503.
127
- - **`hold.release()` is awaited** — `listen()` throws while a predecessor still owns the socket.
128
- - **The app's own health handler spreads `bootHealthPayload()`**, so the body does not change shape
129
- under a consumer polling across the handover:
130
-
131
- ```typescript
132
- export const handleHealtz = handleRequest(async (_req, ctx) => ({
133
- ...bootHealthPayload(), db: await pingDb(ctx)
134
- }))
135
- ```
136
-
137
- `bootId` is identity, not health: a supervisor stamps the child it spawns via `BOOT_ID_ENV`
138
- (`OWLMEANS_BOOT_ID`) and compares it here — another id means a leftover process holds the port.
139
-
140
- ### Handlers
141
- ```typescript
142
- import { handleRequest, handleBody } from '@owlmeans/server-app'
143
- import { requireEntityKey } from '@owlmeans/auth-common'
144
- import type { ClientEntrypoint } from '@owlmeans/server-app'
145
-
146
- export const list = handleRequest(async (req, context) => {
147
- const ctx = context as Context
148
- const { items } = await ctx.project().list({ entityId: requireEntityKey(req) })
149
- return items
150
- })
151
-
152
- export const create = handleBody<CreateProject>(async (payload, context) => {
153
- const ctx = context as Context
154
- return await ctx.entrypoint<ClientEntrypoint<Project>>(agent.project.create).call({
155
- body: { prompt: payload.prompt }
156
- })
157
- })
158
- ```
159
-
160
- **Key organization-scoped records by `requireEntityKey(req)` / `entityKeyOf(req)` from
161
- `@owlmeans/auth-common`.** The token carries only `entitySlug`, which is renameable — there is no id
162
- on it. The guard resolves that slug once, at the boundary, and hands the result to the handler as
163
- `req.entity` (`{ id, slug, iamKey }`); those two helpers return `req.entity.id` and fall back to the
164
- slug for a deployment that registers no entity resolver, and `requireEntityKey` throws
165
- `AuthorizationError` when the request names no organization at all. `requireEntity(req)` gives the
166
- whole record when the slug or the frozen `iamKey` is wanted too.
167
-
168
- The id stays inside the process: it is what records, grants and permission checks key on, and it
169
- never goes onto the wire. A cross-service call carries the caller's token, so the peer resolves the
170
- organization for itself; anything that must name one in a payload names it by `entitySlug`.
171
-
172
- A cross-service call from a handler uses `call()` — it resolves to the value and throws whatever the
173
- peer replied. Reach for `invoke()` only where the outcome decides what happens next.
174
-
175
- ### Entrypoint elevation
176
- ```typescript
177
- // entrypoints.ts
178
- import { elevate, entrypoints as systemEntrypoints } from '@owlmeans/server-app'
179
- import { managerEntrypoints } from 'my-common'
180
- import { create, list } from './app/project/index.js'
181
-
182
- elevate(managerEntrypoints, manager.back.project.create, create)
183
- elevate(managerEntrypoints, manager.back.project.list, list)
184
-
185
- export const appEntrypoints = [...systemEntrypoints, ...paymentEntrypoints, ...managerEntrypoints]
186
- ```
187
-
188
- Elevating is idempotent, so a later `elevate` of the same alias is legal and simply replaces the
189
- element again; the guards it brings are added to the declared ones rather than replacing them.
190
-
191
- A parent alias needs no elevation for its `guard()` to reach its children — `getGuards()` walks the
192
- registered declarations whether or not they were elevated. A **bare** `elevate(entrypoints, alias)`
193
- only turns the declaration into a server entrypoint; with no handler it is never bound as a route,
194
- and it runs in the intermediate chain only when the same call passes `true` (or
195
- `{ intermediate: true }`) along with a `handleIntermediate` handler from `@owlmeans/server-api`.
196
- `guard()` is re-exported here; `gate()` is not — take it from `@owlmeans/entrypoint`.
197
-
198
- ## Depends On
199
-
200
- Declared:
27
+ `handlers<Context>().body`, `.params` and `.request` infer request sections and response values
28
+ from the declaration. Use `.request` for a transport-level handler that needs the complete request
29
+ boundary.
201
30
 
202
- - `@owlmeans/server-context`, `@owlmeans/server-entrypoint`, `@owlmeans/server-route`, `@owlmeans/server-api`, `@owlmeans/server-auth`, `@owlmeans/server-socket`
203
- - `@owlmeans/api`, `@owlmeans/static-resource`, `@owlmeans/kluster`
204
- - `@owlmeans/entrypoint`, `@owlmeans/route`, `@owlmeans/config`, `@owlmeans/client-config`, `@owlmeans/client-entrypoint`, `@owlmeans/context`
31
+ ## Rules
205
32
 
206
- Imported but **not** declared in this package's manifest: `@owlmeans/api-config-server` (its
207
- advertise endpoint is in `entrypoints`), `@owlmeans/auth-common` (`GUARD_ED25519`),
208
- `@owlmeans/resource` (the list schema and the query types) and `@owlmeans/server-config`
209
- (`sservice`). A workspace resolves them anyway; a standalone install has to name them in its own
210
- dependencies.
33
+ - Keep `protocol()` declarations in the common package shared by callers and servers.
34
+ - Bind parent/group declarations as well as leaves; parents establish inherited paths and access.
35
+ - Use direct protocol references in `context.entrypoint(protocol)`; do not supply a caller-side
36
+ response generic.
37
+ - Model validation belongs in `contract()` with `typed()` or `schema()`, not in a wrapper around a
38
+ handler.
39
+ - `entrypoints` contains framework registrations. Add local entrypoints to a new array and register
40
+ that array during context initialization.
211
41
 
212
- The HTTP server is Fastify, built by `@owlmeans/server-api` — this package neither depends on
213
- `fastify` nor exposes it. There is no Express anywhere in this layer.
42
+ `holdApiPort`, `config`, `sservice`, `service`, `AppType` and the context bootstrap exports remain
43
+ available from this package for process wiring.
@@ -1,2 +1,3 @@
1
- export declare const entrypoints: import("@owlmeans/server-entrypoint").ServerEntrypoint<unknown>[];
1
+ /** Framework server entrypoints every application receives. */
2
+ export declare const entrypoints: import("@owlmeans/server-entrypoint").ServerProtocolEntrypoint<import("@owlmeans/entrypoint").EntrypointProtocolDeclaration>[];
2
3
  //# sourceMappingURL=entrypoints.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"entrypoints.d.ts","sourceRoot":"","sources":["../src/entrypoints.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,WAAW,mEAA0B,CAAA"}
1
+ {"version":3,"file":"entrypoints.d.ts","sourceRoot":"","sources":["../src/entrypoints.ts"],"names":[],"mappings":"AAGA,+DAA+D;AAC/D,eAAO,MAAM,WAAW,gIAA0C,CAAA"}
@@ -1,4 +1,5 @@
1
- import { entrypoints as apiConfig } from '@owlmeans/api-config-server';
2
- import { entrypoints as list } from '@owlmeans/server-auth';
3
- export const entrypoints = [...list, ...apiConfig];
1
+ import { entrypoints as apiConfigBindings } from '@owlmeans/api-config-server';
2
+ import { entrypoints as authBindings } from '@owlmeans/server-auth';
3
+ /** Framework server entrypoints every application receives. */
4
+ export const entrypoints = [...authBindings, ...apiConfigBindings];
4
5
  //# sourceMappingURL=entrypoints.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"entrypoints.js","sourceRoot":"","sources":["../src/entrypoints.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,IAAI,SAAS,EAAE,MAAM,6BAA6B,CAAA;AACtE,OAAO,EAAE,WAAW,IAAI,IAAI,EAAE,MAAM,uBAAuB,CAAA;AAE3D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,GAAG,IAAI,EAAE,GAAG,SAAS,CAAC,CAAA"}
1
+ {"version":3,"file":"entrypoints.js","sourceRoot":"","sources":["../src/entrypoints.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,IAAI,iBAAiB,EAAE,MAAM,6BAA6B,CAAA;AAC9E,OAAO,EAAE,WAAW,IAAI,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAEnE,+DAA+D;AAC/D,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,GAAG,YAAY,EAAE,GAAG,iBAAiB,CAAC,CAAA"}
@@ -1,22 +1,25 @@
1
1
  export { config } from '@owlmeans/server-context';
2
+ export { makeContext } from './context.js';
3
+ export { main } from './main.js';
4
+ export type { AppConfig, AppContext } from './types.js';
2
5
  export { sservice } from '@owlmeans/server-config';
3
6
  export { addWebService } from '@owlmeans/client-config';
4
7
  export { service, toConfigRecord, PLUGINS } from '@owlmeans/config';
5
- export { contract, filter, body, params, EntrypointOutcome, protocol, typed } from '@owlmeans/entrypoint';
8
+ export { contract, protocol, typed, EntrypointOutcome } from '@owlmeans/entrypoint';
6
9
  export type { AbstractRequest as Request, AbstractResponse as Response } from '@owlmeans/entrypoint';
7
10
  export { createListSchema, filterObject } from '@owlmeans/resource';
8
11
  export type { Criteria, ListOptions, ListQuery, ListResult, Sort } from '@owlmeans/resource';
9
12
  export { AppType, BASE, assertContext } from '@owlmeans/context';
10
- export { elevate, entrypoint, guard } from '@owlmeans/server-entrypoint';
11
- export { elevate as celevate } from '@owlmeans/client-entrypoint';
12
- export type { ServerEntrypoint as Module, RefedEntrypointHandler } from '@owlmeans/server-entrypoint';
13
- export type { ClientEntrypoint } from '@owlmeans/client-entrypoint';
13
+ export { bind, bindAll } from '@owlmeans/server-entrypoint';
14
14
  export { route as broute } from '@owlmeans/server-route';
15
- export { handlers, handleRequest, handleBody, handleParams, holdApiPort } from '@owlmeans/server-api';
15
+ export { handlers, holdApiPort } from '@owlmeans/server-api';
16
+ export { handleIntermediate, handleBody, handleRequest, handleParams } from '@owlmeans/server-api';
16
17
  export type { ApiPortHold, ApiPortHoldOptions } from '@owlmeans/server-api';
18
+ export type { ClientEntrypoint } from '@owlmeans/client-entrypoint';
17
19
  export { route } from '@owlmeans/route';
18
20
  export { DEFAULT_ALIAS as DAUTH_GUARD } from '@owlmeans/server-auth';
19
21
  export { klusterize } from '@owlmeans/kluster';
20
22
  export type { PluginConfig } from '@owlmeans/config';
21
23
  export { GUARD_ED25519, BED255_CASHE_RESOURCE } from '@owlmeans/auth-common';
24
+ export { entrypoints } from './entrypoints.js';
22
25
  //# sourceMappingURL=exports.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"exports.d.ts","sourceRoot":"","sources":["../src/exports.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AACzG,YAAY,EAAE,eAAe,IAAI,OAAO,EAAE,gBAAgB,IAAI,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpG,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACnE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAA;AAC5F,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAA;AACxE,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AACjE,YAAY,EAAE,gBAAgB,IAAI,MAAM,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AACrG,YAAY,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AACnE,OAAO,EAAE,KAAK,IAAI,MAAM,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACrG,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAC3E,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AACvC,OAAO,EAAE,aAAa,IAAI,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA"}
1
+ {"version":3,"file":"exports.d.ts","sourceRoot":"","sources":["../src/exports.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,YAAY,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACnE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AACnF,YAAY,EAAE,eAAe,IAAI,OAAO,EAAE,gBAAgB,IAAI,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpG,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACnE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,oBAAoB,CAAA;AAC5F,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,KAAK,IAAI,MAAM,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAClG,YAAY,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAC3E,YAAY,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AACnE,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AACvC,OAAO,EAAE,aAAa,IAAI,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAC9C,YAAY,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA"}
package/build/exports.js CHANGED
@@ -1,16 +1,19 @@
1
1
  export { config } from '@owlmeans/server-context';
2
+ export { makeContext } from './context.js';
3
+ export { main } from './main.js';
2
4
  export { sservice } from '@owlmeans/server-config';
3
5
  export { addWebService } from '@owlmeans/client-config';
4
6
  export { service, toConfigRecord, PLUGINS } from '@owlmeans/config';
5
- export { contract, filter, body, params, EntrypointOutcome, protocol, typed } from '@owlmeans/entrypoint';
7
+ export { contract, protocol, typed, EntrypointOutcome } from '@owlmeans/entrypoint';
6
8
  export { createListSchema, filterObject } from '@owlmeans/resource';
7
9
  export { AppType, BASE, assertContext } from '@owlmeans/context';
8
- export { elevate, entrypoint, guard } from '@owlmeans/server-entrypoint';
9
- export { elevate as celevate } from '@owlmeans/client-entrypoint';
10
+ export { bind, bindAll } from '@owlmeans/server-entrypoint';
10
11
  export { route as broute } from '@owlmeans/server-route';
11
- export { handlers, handleRequest, handleBody, handleParams, holdApiPort } from '@owlmeans/server-api';
12
+ export { handlers, holdApiPort } from '@owlmeans/server-api';
13
+ export { handleIntermediate, handleBody, handleRequest, handleParams } from '@owlmeans/server-api';
12
14
  export { route } from '@owlmeans/route';
13
15
  export { DEFAULT_ALIAS as DAUTH_GUARD } from '@owlmeans/server-auth';
14
16
  export { klusterize } from '@owlmeans/kluster';
15
17
  export { GUARD_ED25519, BED255_CASHE_RESOURCE } from '@owlmeans/auth-common';
18
+ export { entrypoints } from './entrypoints.js';
16
19
  //# sourceMappingURL=exports.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"exports.js","sourceRoot":"","sources":["../src/exports.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAA;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACnE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,iBAAiB,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAEzG,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEnE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAA;AACxE,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,6BAA6B,CAAA;AAGjE,OAAO,EAAE,KAAK,IAAI,MAAM,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAErG,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AACvC,OAAO,EAAE,aAAa,IAAI,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA"}
1
+ {"version":3,"file":"exports.js","sourceRoot":"","sources":["../src/exports.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAC1C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAEhC,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACnE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAA;AAEnF,OAAO,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEnE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,KAAK,IAAI,MAAM,EAAE,MAAM,wBAAwB,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,EAAE,kBAAkB,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAGlG,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAA;AACvC,OAAO,EAAE,aAAa,IAAI,WAAW,EAAE,MAAM,uBAAuB,CAAA;AACpE,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAA;AAE9C,OAAO,EAAE,aAAa,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAC5E,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAA"}
package/build/index.d.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  export * from './exports.js';
2
2
  export * from './main.js';
3
- export * from './boot-state.js';
4
3
  export type * from './types.js';
5
4
  export * from './context.js';
6
5
  export * from './entrypoints.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,cAAc,iBAAiB,CAAA;AAC/B,mBAAmB,YAAY,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,mBAAmB,YAAY,CAAA;AAC/B,cAAc,cAAc,CAAA;AAC5B,cAAc,kBAAkB,CAAA"}
package/build/index.js CHANGED
@@ -1,6 +1,5 @@
1
1
  export * from './exports.js';
2
2
  export * from './main.js';
3
- export * from './boot-state.js';
4
3
  export * from './context.js';
5
4
  export * from './entrypoints.js';
6
5
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AACzB,cAAc,iBAAiB,CAAA;AAE/B,cAAc,cAAc,CAAA;AAC5B,cAAc,kBAAkB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,cAAc,CAAA;AAC5B,cAAc,WAAW,CAAA;AAEzB,cAAc,cAAc,CAAA;AAC5B,cAAc,kBAAkB,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@owlmeans/server-app",
3
- "version": "0.1.18-rc.20",
3
+ "version": "0.1.18-rc.22",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -21,21 +21,21 @@
21
21
  }
22
22
  },
23
23
  "dependencies": {
24
- "@owlmeans/api": "^0.1.18-rc.15",
25
- "@owlmeans/client-config": "^0.1.18-rc.14",
26
- "@owlmeans/client-entrypoint": "^0.1.18-rc.15",
27
- "@owlmeans/config": "^0.1.18-rc.14",
28
- "@owlmeans/context": "^0.1.18-rc.10",
29
- "@owlmeans/kluster": "^0.1.18-rc.14",
30
- "@owlmeans/entrypoint": "^0.1.18-rc.13",
31
- "@owlmeans/route": "^0.1.18-rc.11",
32
- "@owlmeans/server-api": "^0.1.18-rc.19",
33
- "@owlmeans/server-auth": "^0.1.18-rc.20",
34
- "@owlmeans/server-context": "^0.1.18-rc.14",
35
- "@owlmeans/server-entrypoint": "^0.1.18-rc.13",
36
- "@owlmeans/server-route": "^0.1.18-rc.11",
37
- "@owlmeans/server-socket": "^0.1.18-rc.20",
38
- "@owlmeans/static-resource": "^0.1.18-rc.11"
24
+ "@owlmeans/api": "^0.1.18-rc.17",
25
+ "@owlmeans/client-config": "^0.1.18-rc.16",
26
+ "@owlmeans/client-entrypoint": "^0.1.18-rc.17",
27
+ "@owlmeans/config": "^0.1.18-rc.16",
28
+ "@owlmeans/context": "^0.1.18-rc.12",
29
+ "@owlmeans/kluster": "^0.1.18-rc.16",
30
+ "@owlmeans/entrypoint": "^0.1.18-rc.15",
31
+ "@owlmeans/route": "^0.1.18-rc.13",
32
+ "@owlmeans/server-api": "^0.1.18-rc.21",
33
+ "@owlmeans/server-auth": "^0.1.18-rc.22",
34
+ "@owlmeans/server-context": "^0.1.18-rc.16",
35
+ "@owlmeans/server-entrypoint": "^0.1.18-rc.15",
36
+ "@owlmeans/server-route": "^0.1.18-rc.13",
37
+ "@owlmeans/server-socket": "^0.1.18-rc.22",
38
+ "@owlmeans/static-resource": "^0.1.18-rc.13"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@owlmeans/dep-config": "workspace:*",
@@ -1,4 +1,5 @@
1
- import { entrypoints as apiConfig } from '@owlmeans/api-config-server'
2
- import { entrypoints as list } from '@owlmeans/server-auth'
1
+ import { entrypoints as apiConfigBindings } from '@owlmeans/api-config-server'
2
+ import { entrypoints as authBindings } from '@owlmeans/server-auth'
3
3
 
4
- export const entrypoints = [...list, ...apiConfig]
4
+ /** Framework server entrypoints every application receives. */
5
+ export const entrypoints = [...authBindings, ...apiConfigBindings]
package/src/exports.ts CHANGED
@@ -1,22 +1,25 @@
1
1
 
2
2
  export { config } from '@owlmeans/server-context'
3
+ export { makeContext } from './context.js'
4
+ export { main } from './main.js'
5
+ export type { AppConfig, AppContext } from './types.js'
3
6
  export { sservice } from '@owlmeans/server-config'
4
7
  export { addWebService } from '@owlmeans/client-config'
5
8
  export { service, toConfigRecord, PLUGINS } from '@owlmeans/config'
6
- export { contract, filter, body, params, EntrypointOutcome, protocol, typed } from '@owlmeans/entrypoint'
9
+ export { contract, protocol, typed, EntrypointOutcome } from '@owlmeans/entrypoint'
7
10
  export type { AbstractRequest as Request, AbstractResponse as Response } from '@owlmeans/entrypoint'
8
11
  export { createListSchema, filterObject } from '@owlmeans/resource'
9
12
  export type { Criteria, ListOptions, ListQuery, ListResult, Sort } from '@owlmeans/resource'
10
13
  export { AppType, BASE, assertContext } from '@owlmeans/context'
11
- export { elevate, entrypoint, guard } from '@owlmeans/server-entrypoint'
12
- export { elevate as celevate } from '@owlmeans/client-entrypoint'
13
- export type { ServerEntrypoint as Module, RefedEntrypointHandler } from '@owlmeans/server-entrypoint'
14
- export type { ClientEntrypoint } from '@owlmeans/client-entrypoint'
14
+ export { bind, bindAll } from '@owlmeans/server-entrypoint'
15
15
  export { route as broute } from '@owlmeans/server-route'
16
- export { handlers, handleRequest, handleBody, handleParams, holdApiPort } from '@owlmeans/server-api'
16
+ export { handlers, holdApiPort } from '@owlmeans/server-api'
17
+ export { handleIntermediate, handleBody, handleRequest, handleParams } from '@owlmeans/server-api'
17
18
  export type { ApiPortHold, ApiPortHoldOptions } from '@owlmeans/server-api'
19
+ export type { ClientEntrypoint } from '@owlmeans/client-entrypoint'
18
20
  export { route } from '@owlmeans/route'
19
21
  export { DEFAULT_ALIAS as DAUTH_GUARD } from '@owlmeans/server-auth'
20
22
  export { klusterize } from '@owlmeans/kluster'
21
23
  export type { PluginConfig } from '@owlmeans/config'
22
24
  export { GUARD_ED25519, BED255_CASHE_RESOURCE } from '@owlmeans/auth-common'
25
+ export { entrypoints } from './entrypoints.js'
package/src/index.ts CHANGED
@@ -1,7 +1,6 @@
1
1
 
2
2
  export * from './exports.js'
3
3
  export * from './main.js'
4
- export * from './boot-state.js'
5
4
  export type * from './types.js'
6
5
  export * from './context.js'
7
6
  export * from './entrypoints.js'
@@ -1,55 +0,0 @@
1
- import type { ApiPortHoldOptions } from '@owlmeans/server-api';
2
- /**
3
- * Boot phase of the process.
4
- *
5
- * An app binds its port before it initializes, so that a failure has somewhere to be reported
6
- * from. Without a listener the only thing anyone sees is a connection refused at the edge — an
7
- * opaque 503 that names neither the app nor the cause. This phase is what the health path answers
8
- * with, and what the platform reads to tell "still starting" from "gave up, and here is why".
9
- */
10
- export type BootPhase = 'initializing' | 'ready' | 'failed';
11
- export interface BootHealth extends Record<string, unknown> {
12
- status: 'OK' | 'FAILED';
13
- phase: BootPhase;
14
- ok: boolean;
15
- /** Whatever `setBootPhase` was given — the failure message, or the step being waited on. */
16
- reason?: string;
17
- /**
18
- * Identity, not health: a supervisor passes the id to the child it spawns and compares it
19
- * here, so an answer carrying another id means the port is held by a leftover process and the
20
- * health it reports describes code nobody asked for. Empty when nothing supplied one.
21
- */
22
- bootId: string;
23
- pid: number;
24
- }
25
- /** Env var a supervisor stamps the spawned process with; surfaced as `bootId`. */
26
- export declare const BOOT_ID_ENV = "OWLMEANS_BOOT_ID";
27
- export declare const getBootPhase: () => BootPhase;
28
- export declare const getBootDetail: () => string | undefined;
29
- /**
30
- * `detail` is free text, and is kept for every phase — a boot that is merely slow is as worth
31
- * explaining as one that failed.
32
- */
33
- export declare const setBootPhase: (phase: BootPhase, detail?: string) => void;
34
- /**
35
- * The body the health path answers with, from either server.
36
- *
37
- * The port hold and the app's own handler both build it here, so a consumer polling through the
38
- * handover never sees the shape change under it — which is why the keys are unconditional and
39
- * only `reason` comes and goes with the state it describes.
40
- */
41
- export declare const bootHealthPayload: () => BootHealth;
42
- /**
43
- * Hold options wired to this module — the bind-first boot in one line:
44
- *
45
- * const hold = await holdApiPort(ctx.cfg, bootHold(HEALTH_PATH))
46
- * try { await init() } catch (e) { setBootPhase('failed', message); return }
47
- * await hold.release()
48
- * setBootPhase('ready')
49
- * await ctx.getApiServer().listen()
50
- *
51
- * The hold evaluates `payload` per request, so the phase set after a failure is reported live by
52
- * the listener that is already bound rather than needing a server that will never start.
53
- */
54
- export declare const bootHold: (okPath?: string) => ApiPortHoldOptions;
55
- //# sourceMappingURL=boot-state.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"boot-state.d.ts","sourceRoot":"","sources":["../src/boot-state.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AAE9D;;;;;;;GAOG;AACH,MAAM,MAAM,SAAS,GAAG,cAAc,GAAG,OAAO,GAAG,QAAQ,CAAA;AAE3D,MAAM,WAAW,UAAW,SAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IACzD,MAAM,EAAE,IAAI,GAAG,QAAQ,CAAA;IACvB,KAAK,EAAE,SAAS,CAAA;IAChB,EAAE,EAAE,OAAO,CAAA;IACX,4FAA4F;IAC5F,MAAM,CAAC,EAAE,MAAM,CAAA;IACf;;;;OAIG;IACH,MAAM,EAAE,MAAM,CAAA;IACd,GAAG,EAAE,MAAM,CAAA;CACZ;AAED,kFAAkF;AAClF,eAAO,MAAM,WAAW,qBAAqB,CAAA;AAK7C,eAAO,MAAM,YAAY,QAAO,SAAmB,CAAA;AAEnD,eAAO,MAAM,aAAa,QAAO,MAAM,GAAG,SAAoB,CAAA;AAE9D;;;GAGG;AACH,eAAO,MAAM,YAAY,UAAW,SAAS,WAAW,MAAM,KAAG,IAGhE,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,QAAO,UAOnC,CAAA;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,QAAQ,YAAa,MAAM,KAAG,kBAGzC,CAAA"}
@@ -1,46 +0,0 @@
1
- /** Env var a supervisor stamps the spawned process with; surfaced as `bootId`. */
2
- export const BOOT_ID_ENV = 'OWLMEANS_BOOT_ID';
3
- let _phase = 'initializing';
4
- let _detail;
5
- export const getBootPhase = () => _phase;
6
- export const getBootDetail = () => _detail;
7
- /**
8
- * `detail` is free text, and is kept for every phase — a boot that is merely slow is as worth
9
- * explaining as one that failed.
10
- */
11
- export const setBootPhase = (phase, detail) => {
12
- _phase = phase;
13
- _detail = detail;
14
- };
15
- /**
16
- * The body the health path answers with, from either server.
17
- *
18
- * The port hold and the app's own handler both build it here, so a consumer polling through the
19
- * handover never sees the shape change under it — which is why the keys are unconditional and
20
- * only `reason` comes and goes with the state it describes.
21
- */
22
- export const bootHealthPayload = () => ({
23
- status: _phase === 'failed' ? 'FAILED' : 'OK',
24
- phase: _phase,
25
- ok: _phase === 'ready',
26
- ...(_detail != null ? { reason: _detail } : {}),
27
- bootId: process.env[BOOT_ID_ENV] ?? '',
28
- pid: process.pid
29
- });
30
- /**
31
- * Hold options wired to this module — the bind-first boot in one line:
32
- *
33
- * const hold = await holdApiPort(ctx.cfg, bootHold(HEALTH_PATH))
34
- * try { await init() } catch (e) { setBootPhase('failed', message); return }
35
- * await hold.release()
36
- * setBootPhase('ready')
37
- * await ctx.getApiServer().listen()
38
- *
39
- * The hold evaluates `payload` per request, so the phase set after a failure is reported live by
40
- * the listener that is already bound rather than needing a server that will never start.
41
- */
42
- export const bootHold = (okPath) => ({
43
- ...(okPath != null ? { okPath } : {}),
44
- payload: bootHealthPayload
45
- });
46
- //# sourceMappingURL=boot-state.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"boot-state.js","sourceRoot":"","sources":["../src/boot-state.ts"],"names":[],"mappings":"AA2BA,kFAAkF;AAClF,MAAM,CAAC,MAAM,WAAW,GAAG,kBAAkB,CAAA;AAE7C,IAAI,MAAM,GAAc,cAAc,CAAA;AACtC,IAAI,OAA2B,CAAA;AAE/B,MAAM,CAAC,MAAM,YAAY,GAAG,GAAc,EAAE,CAAC,MAAM,CAAA;AAEnD,MAAM,CAAC,MAAM,aAAa,GAAG,GAAuB,EAAE,CAAC,OAAO,CAAA;AAE9D;;;GAGG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAgB,EAAE,MAAe,EAAQ,EAAE;IACtE,MAAM,GAAG,KAAK,CAAA;IACd,OAAO,GAAG,MAAM,CAAA;AAClB,CAAC,CAAA;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAe,EAAE,CAAC,CAAC;IAClD,MAAM,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI;IAC7C,KAAK,EAAE,MAAM;IACb,EAAE,EAAE,MAAM,KAAK,OAAO;IACtB,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAC/C,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE;IACtC,GAAG,EAAE,OAAO,CAAC,GAAG;CACjB,CAAC,CAAA;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,MAAe,EAAsB,EAAE,CAAC,CAAC;IAChE,GAAG,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IACrC,OAAO,EAAE,iBAAiB;CAC3B,CAAC,CAAA"}
package/src/boot-state.ts DELETED
@@ -1,78 +0,0 @@
1
- import type { ApiPortHoldOptions } from '@owlmeans/server-api'
2
-
3
- /**
4
- * Boot phase of the process.
5
- *
6
- * An app binds its port before it initializes, so that a failure has somewhere to be reported
7
- * from. Without a listener the only thing anyone sees is a connection refused at the edge — an
8
- * opaque 503 that names neither the app nor the cause. This phase is what the health path answers
9
- * with, and what the platform reads to tell "still starting" from "gave up, and here is why".
10
- */
11
- export type BootPhase = 'initializing' | 'ready' | 'failed'
12
-
13
- export interface BootHealth extends Record<string, unknown> {
14
- status: 'OK' | 'FAILED'
15
- phase: BootPhase
16
- ok: boolean
17
- /** Whatever `setBootPhase` was given — the failure message, or the step being waited on. */
18
- reason?: string
19
- /**
20
- * Identity, not health: a supervisor passes the id to the child it spawns and compares it
21
- * here, so an answer carrying another id means the port is held by a leftover process and the
22
- * health it reports describes code nobody asked for. Empty when nothing supplied one.
23
- */
24
- bootId: string
25
- pid: number
26
- }
27
-
28
- /** Env var a supervisor stamps the spawned process with; surfaced as `bootId`. */
29
- export const BOOT_ID_ENV = 'OWLMEANS_BOOT_ID'
30
-
31
- let _phase: BootPhase = 'initializing'
32
- let _detail: string | undefined
33
-
34
- export const getBootPhase = (): BootPhase => _phase
35
-
36
- export const getBootDetail = (): string | undefined => _detail
37
-
38
- /**
39
- * `detail` is free text, and is kept for every phase — a boot that is merely slow is as worth
40
- * explaining as one that failed.
41
- */
42
- export const setBootPhase = (phase: BootPhase, detail?: string): void => {
43
- _phase = phase
44
- _detail = detail
45
- }
46
-
47
- /**
48
- * The body the health path answers with, from either server.
49
- *
50
- * The port hold and the app's own handler both build it here, so a consumer polling through the
51
- * handover never sees the shape change under it — which is why the keys are unconditional and
52
- * only `reason` comes and goes with the state it describes.
53
- */
54
- export const bootHealthPayload = (): BootHealth => ({
55
- status: _phase === 'failed' ? 'FAILED' : 'OK',
56
- phase: _phase,
57
- ok: _phase === 'ready',
58
- ...(_detail != null ? { reason: _detail } : {}),
59
- bootId: process.env[BOOT_ID_ENV] ?? '',
60
- pid: process.pid
61
- })
62
-
63
- /**
64
- * Hold options wired to this module — the bind-first boot in one line:
65
- *
66
- * const hold = await holdApiPort(ctx.cfg, bootHold(HEALTH_PATH))
67
- * try { await init() } catch (e) { setBootPhase('failed', message); return }
68
- * await hold.release()
69
- * setBootPhase('ready')
70
- * await ctx.getApiServer().listen()
71
- *
72
- * The hold evaluates `payload` per request, so the phase set after a failure is reported live by
73
- * the listener that is already bound rather than needing a server that will never start.
74
- */
75
- export const bootHold = (okPath?: string): ApiPortHoldOptions => ({
76
- ...(okPath != null ? { okPath } : {}),
77
- payload: bootHealthPayload
78
- })