@owlmeans/context 0.1.18-rc.9 → 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 +248 -64
- package/agent-meta/manifest.json +6 -6
- package/agent-meta/skills/owlmeans-context/SKILL.md +25 -0
- package/build/consts.local.d.ts +5 -0
- package/build/consts.local.d.ts.map +1 -0
- package/build/consts.local.js +6 -0
- package/build/consts.local.js.map +1 -0
- package/build/context.d.ts.map +1 -1
- package/build/context.js +7 -7
- package/build/context.js.map +1 -1
- package/build/index.d.ts +2 -0
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -0
- package/build/index.js.map +1 -1
- package/build/memo/types.d.ts +14 -0
- package/build/memo/types.d.ts.map +1 -0
- package/build/memo/types.js +2 -0
- package/build/memo/types.js.map +1 -0
- package/build/memo.d.ts +4 -0
- package/build/memo.d.ts.map +1 -0
- package/build/memo.js +25 -0
- package/build/memo.js.map +1 -0
- package/build/service.d.ts +1 -4
- package/build/service.d.ts.map +1 -1
- package/build/service.js +1 -5
- package/build/service.js.map +1 -1
- package/build/types.d.ts +3 -0
- package/build/types.d.ts.map +1 -1
- package/build/types.local.d.ts +6 -0
- package/build/types.local.d.ts.map +1 -0
- package/build/types.local.js +2 -0
- package/build/types.local.js.map +1 -0
- package/build/utils/context.d.ts +7 -2
- package/build/utils/context.d.ts.map +1 -1
- package/build/utils/context.js +11 -0
- package/build/utils/context.js.map +1 -1
- package/build/utils/index.d.ts +2 -1
- package/build/utils/index.d.ts.map +1 -1
- package/build/utils/index.js +1 -1
- package/build/utils/index.js.map +1 -1
- package/build/utils/layer.d.ts +6 -0
- package/build/utils/layer.d.ts.map +1 -0
- package/build/utils/layer.js +12 -0
- package/build/utils/layer.js.map +1 -0
- package/build/utils/middleware/types.d.ts +12 -0
- package/build/utils/middleware/types.d.ts.map +1 -0
- package/build/utils/middleware/types.js +2 -0
- package/build/utils/middleware/types.js.map +1 -0
- package/build/utils/middleware.d.ts +4 -0
- package/build/utils/middleware.d.ts.map +1 -0
- package/build/utils/middleware.js +8 -0
- package/build/utils/middleware.js.map +1 -0
- package/package.json +2 -2
- package/src/consts.local.ts +4 -0
- package/src/context.ts +9 -12
- package/src/index.ts +2 -0
- package/src/memo/types.ts +13 -0
- package/src/memo.ts +33 -0
- package/src/service.ts +3 -14
- package/src/types.local.ts +7 -0
- package/src/types.ts +4 -0
- package/src/utils/index.ts +2 -1
- package/src/utils/middleware/types.ts +18 -0
- package/src/utils/middleware.ts +23 -0
- package/tests/memo.spec.ts +27 -0
- package/agent-meta/skills/context/SKILL.md +0 -163
- package/src/utils/context.ts +0 -16
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: context
|
|
3
|
-
description: How to use @owlmeans/context — the DI container behind every OwlMeans app, its service/resource/entrypoint registries, the configure/init lifecycle, createService and createLazyService, middlewares, and the shared route-alias constants. Auto-invoked when importing context primitives, registering a service, or building a makeContext factory.
|
|
4
|
-
user-invocable: false
|
|
5
|
-
---
|
|
6
|
-
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
|
|
7
|
-
|
|
8
|
-
# @owlmeans/context
|
|
9
|
-
|
|
10
|
-
**Layer:** Core
|
|
11
|
-
**Install:** `"@owlmeans/context": "^0.1.18-rc.9"` in `dependencies`
|
|
12
|
-
|
|
13
|
-
## Key Exports
|
|
14
|
-
|
|
15
|
-
| Export | Description |
|
|
16
|
-
|--------|-------------|
|
|
17
|
-
| `makeBasicContext(cfg)` | Low-level factory — extend a layer-specific factory instead |
|
|
18
|
-
| `BasicContext<C>` | The container interface, typed by its config |
|
|
19
|
-
| `BasicConfig` | `{ ready, service, alias?, type, services?, records?, debug? }` — what every config extends |
|
|
20
|
-
| `makeBasicConfig(type, service, cfg?)` | Build the base config object a layer factory then fills in |
|
|
21
|
-
| `createService(alias, impl, init?)` | Build a service initialized during `context.init()` |
|
|
22
|
-
| `createLazyService(alias, impl, init?)` | Build a service initialized on first `context.service()` |
|
|
23
|
-
| `appendContextual(alias, obj)` | Give any object `alias` / `registerContext` / `assertCtx` |
|
|
24
|
-
| `assertContext(ctx, location?)` | Return the context or throw `SyntaxError` when it is absent |
|
|
25
|
-
| `Service` / `InitializedService` / `LazyService` | The three service shapes |
|
|
26
|
-
| `BasicResource` / `BasicEntrypoint` / `Contextual` | The other registrable shapes |
|
|
27
|
-
| `Middleware`, `MiddlewareType`, `MiddlewareStage` | Hooks that run inside `configure()` / `init()` |
|
|
28
|
-
| `AppType` | `Backend` / `Frontend` |
|
|
29
|
-
| `ContextStage` | `Configuration` → `Loading` → `Ready` |
|
|
30
|
-
| `CONFIG_RECORD` (`'records'`), `ConfigRecord` | The config-record array key, and a record in it |
|
|
31
|
-
| `ROOT`, `HOME`, `GUEST`, `BASE`, `CRASH` | Route-alias idioms every layer reuses |
|
|
32
|
-
|
|
33
|
-
## One context per process
|
|
34
|
-
|
|
35
|
-
A context is created ONCE by ONE factory. Extend a layer-specific factory
|
|
36
|
-
(`@owlmeans/server-context`, `@owlmeans/web-panel`, …) rather than calling the basic factory
|
|
37
|
-
directly: your factory calls the factory below it, applies its own idempotent `append*(context)`
|
|
38
|
-
mixins and service registrations, and returns that same context. There are no layered or child
|
|
39
|
-
contexts and nothing is stored for re-creation — a service, a resource and an entrypoint each bind
|
|
40
|
-
to exactly one context, the first that registers them.
|
|
41
|
-
|
|
42
|
-
```typescript
|
|
43
|
-
import { makeServerContext } from '@owlmeans/server-context'
|
|
44
|
-
|
|
45
|
-
export const makeContext = <C extends Config, T extends Context<C>>(cfg: C): T => {
|
|
46
|
-
const context = makeServerContext<C, T>(cfg)
|
|
47
|
-
context.registerService(makeMyService())
|
|
48
|
-
return context
|
|
49
|
-
}
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
## Registries
|
|
53
|
-
|
|
54
|
-
Three flat maps keyed by alias. Registering the same alias twice **replaces** the earlier entry —
|
|
55
|
-
entrypoint lists are routinely spread together and the later declaration is the one the app means.
|
|
56
|
-
|
|
57
|
-
```typescript
|
|
58
|
-
context.registerService(service) // service(alias), hasService(alias)
|
|
59
|
-
context.registerResource(resource) // resource(alias), hasResource(alias)
|
|
60
|
-
context.registerEntrypoints(entrypoints) // entrypoint(alias), entrypoints(), hasEntrypoint(alias)
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Every lookup throws `SyntaxError` when the alias is unknown. Resolve a service and call another
|
|
64
|
-
service's entrypoint from a handler:
|
|
65
|
-
|
|
66
|
-
```typescript
|
|
67
|
-
const someService = ctx.service<MyService>(MY_SERVICE_ALIAS)
|
|
68
|
-
|
|
69
|
-
const response = await ctx.entrypoint<ClientEntrypoint<ResponseType>>(
|
|
70
|
-
externalService.action.alias
|
|
71
|
-
).call({ body: { ... } }) // call() resolves to the value; invoke() gives { value, outcome }
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Lifecycle
|
|
75
|
-
|
|
76
|
-
`configure()` runs the `Config` + `Configuration` middlewares and moves the context to `Loading`;
|
|
77
|
-
`init()` awaits that, then initializes every service, then the resources, then flips to `Ready` and
|
|
78
|
-
sets `cfg.ready`. `waitForConfigured()` and `waitForInitialized()` resolve at those two points, and
|
|
79
|
-
`await ctx.config` yields the config once configuration is done. Both calls are safe to repeat — a
|
|
80
|
-
context already past the stage returns itself unchanged.
|
|
81
|
-
|
|
82
|
-
`configure()` is **not** async: it returns the context straight away and its middlewares run
|
|
83
|
-
detached, so the stage flips to `Loading` only when they settle. Anything that must see a configured
|
|
84
|
-
context awaits `waitForConfigured()` or `init()`, never the return of `configure()`.
|
|
85
|
-
|
|
86
|
-
## Services
|
|
87
|
-
|
|
88
|
-
`createService` and `createLazyService` differ only in **when** the init function runs.
|
|
89
|
-
|
|
90
|
-
- `createService` — `init()` is awaited during `context.init()`, in registration order. Asking for
|
|
91
|
-
an uninitialized one throws `SyntaxError`.
|
|
92
|
-
- `createLazyService` — `lazyInit()` fires on the first `context.service(alias)` and the service is
|
|
93
|
-
returned immediately, before that promise settles. Choose lazy when the service must be reachable
|
|
94
|
-
while the context is still `Loading` — from an app's `makeContext`, or from another package's
|
|
95
|
-
`append*` helper — **not** because it has no async work; most lazy services do plenty of it.
|
|
96
|
-
|
|
97
|
-
```typescript
|
|
98
|
-
import { createService } from '@owlmeans/context'
|
|
99
|
-
|
|
100
|
-
export const makeMyService = (alias = MY_SERVICE) => createService<MyService>(alias, {
|
|
101
|
-
doWork: async () => { /* ... */ }
|
|
102
|
-
}, service => async () => {
|
|
103
|
-
await connect()
|
|
104
|
-
service.initialized = true
|
|
105
|
-
})
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
The init function is a factory: it receives the service and returns the actual initializer, which
|
|
109
|
-
must set `service.initialized = true`. Omit it and the service is simply marked initialized. Inside
|
|
110
|
-
any method use `service.assertCtx<Config, Context>()` to reach the context it was registered on.
|
|
111
|
-
|
|
112
|
-
### `ready()`
|
|
113
|
-
|
|
114
|
-
Both factories give the service a `ready(): Promise<boolean>` that resolves once its init function
|
|
115
|
-
has finished, and both `InitializedService` and `LazyService` declare it. It is how you wait for a
|
|
116
|
-
lazy service: the container hands the service back before `lazyInit()` settles, so anything the init
|
|
117
|
-
prepared — a database client, a loaded config, a socket — is only safe to touch after `ready()`.
|
|
118
|
-
|
|
119
|
-
```typescript
|
|
120
|
-
const mongo = ctx.service<MongoService>(MONGO_ALIAS) // this call is what triggers lazyInit
|
|
121
|
-
await mongo.ready()
|
|
122
|
-
```
|
|
123
|
-
|
|
124
|
-
A lazy service's init runs only when someone resolves it through `context.service(alias)`, so
|
|
125
|
-
`ready()` on a reference obtained any other way never settles.
|
|
126
|
-
|
|
127
|
-
## Middlewares
|
|
128
|
-
|
|
129
|
-
A middleware declares a `type` (`Config` or `Context`) and a `stage` (`Configuration`, `Loading` or
|
|
130
|
-
`Ready`), and that pair — not the stage alone — decides where it runs. Exactly five pairs are ever
|
|
131
|
-
applied, in this order:
|
|
132
|
-
|
|
133
|
-
| Type + stage | Where it runs |
|
|
134
|
-
|--------------|---------------|
|
|
135
|
-
| `Config` + `Configuration` | inside `configure()`, before the stage becomes `Loading` — the only hook that sees `cfg` before anything else does |
|
|
136
|
-
| `Context` + `Configuration` | first thing inside `init()` |
|
|
137
|
-
| `Config` + `Loading` | inside `init()`, **after every service has been initialized** and before the resources |
|
|
138
|
-
| `Context` + `Loading` | inside `init()`, after the resources |
|
|
139
|
-
| `Context` + `Ready` | after the stage flips to `Ready`; started but **not awaited**, so `init()` resolves without waiting for it |
|
|
140
|
-
|
|
141
|
-
`Config` + `Ready` is never applied at all — a middleware registered under that pair silently never
|
|
142
|
-
runs. All middlewares sharing a pair are applied with `Promise.all`, so they run concurrently and
|
|
143
|
-
registration order does not sequence them.
|
|
144
|
-
|
|
145
|
-
Pick the pair by what the work needs. `Config` + `Configuration` is for config that stands on its
|
|
146
|
-
own — mounted secrets, hosts read from the environment. `Config` + `Loading` is for config that has
|
|
147
|
-
to be resolved *through a running service*, because services are already initialized by then; that
|
|
148
|
-
is the stage a cluster- or vault-backed value resolver registers at, and it can `await
|
|
149
|
-
service.ready()` on the service it depends on. `Context` middlewares register or adjust what the
|
|
150
|
-
container holds.
|
|
151
|
-
|
|
152
|
-
```typescript
|
|
153
|
-
context.registerMiddleware({
|
|
154
|
-
type: MiddlewareType.Config,
|
|
155
|
-
stage: MiddlewareStage.Loading, // services are up — resolve cfg values through one of them
|
|
156
|
-
apply: async ctx => { /* mutate ctx.cfg */ }
|
|
157
|
-
})
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
## Depends On
|
|
161
|
-
|
|
162
|
-
- Nothing. This is the root package — `@owlmeans/config` layers the application config on top of
|
|
163
|
-
`BasicConfig`, and `@owlmeans/entrypoint` layers URL units on top of `BasicEntrypoint`.
|
package/src/utils/context.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { MiddlewareStage, MiddlewareType } from '../consts.js'
|
|
2
|
-
import type { BasicConfig, BasicContext, Middleware } from '../types.js'
|
|
3
|
-
|
|
4
|
-
export const getMiddlerwareKey = (middleware: Middleware) => createMiddlewareKey(middleware.type, middleware.stage)
|
|
5
|
-
|
|
6
|
-
export const createMiddlewareKey = (type: MiddlewareType, stage: MiddlewareStage) => `${type}:${stage}`
|
|
7
|
-
|
|
8
|
-
export const applyMiddlewares = <C extends BasicConfig, T extends BasicContext<C>>(
|
|
9
|
-
context: T,
|
|
10
|
-
middlewares: Record<string, Middleware[]>,
|
|
11
|
-
type: MiddlewareType,
|
|
12
|
-
stage: MiddlewareStage,
|
|
13
|
-
args?: Record<string, string | undefined>
|
|
14
|
-
) => Promise.all(
|
|
15
|
-
middlewares[createMiddlewareKey(type, stage)]?.map(async middleware => middleware.apply<C, T>(context, args)) ?? []
|
|
16
|
-
)
|