@warlock.js/context 5.34.1 → 5.34.3

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/CHANGELOG.md CHANGED
@@ -4,6 +4,18 @@ All notable changes to `@warlock.js/context` are documented in this file.
4
4
 
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). `@warlock.js/*` packages are released in lockstep — every package shares the same version number, so a version below may list only the changes that affected this package.
6
6
 
7
+ ## 5.34.3 - 2026-10-20
8
+
9
+ ### Changed
10
+
11
+ - Condensed the package agent skill description to at most 450 characters, with API names and package routing guidance.
12
+
13
+ ## 5.34.2 - 2026-10-19
14
+
15
+ ### Fixed
16
+
17
+ - Merge package orientation into the grouped skill index and remove the duplicate overview topic; preserve that orientation in generated LLM projections.
18
+
7
19
  ## 5.32.0 - 2026-10-18
8
20
 
9
21
  ### Changed
package/llms-full.txt CHANGED
@@ -4,7 +4,66 @@
4
4
 
5
5
  > Generated artifact. Concatenates every SKILL.md and reference file under `@warlock.js/context/skills/`. Re-run `node scripts/generate-llms.mjs` after any change.
6
6
 
7
- ## define-context `@warlock.js/context/define-context/SKILL.md`
7
+ ## Package orientation
8
+
9
+ ---
10
+ description: 'Typed async context propagation with `Context` and `ContextManager`, built on AsyncLocalStorage. Use for "avoid passing the tenant everywhere", request-scoped users, trace IDs, `run`, `enter`, `get`, `set` or coordinating several contexts. Not this package → @warlock.js/core for the framework request context; @warlock.js/cache for state shared across requests; @warlock.js/cascade for database transactions.'
11
+ ---
12
+
13
+ # @warlock.js/context
14
+
15
+ A thin typed wrapper over `AsyncLocalStorage`. Each `Context<TStore>` subclass declares its store shape and how `buildStore` creates it; the store lives for the scope and propagates through every `await` inside. `contextManager` runs several contexts together. Zero dependencies; the framework uses it internally for request, user and tenant.
16
+
17
+ ## The 80% path
18
+
19
+ 1. Use this index for orientation and choose a task below.
20
+ 2. Subclass `Context`, implement `buildStore`, read with `get` / `set` anywhere down the call tree: `define-context.md`.
21
+ 3. Wrap work with `run(store, callback)`, or `enter(store)` for middleware that cannot wrap a callback: `define-context.md`.
22
+ 4. With two or more active contexts, register them on `contextManager` and use `runAll` / `enterAll`: `orchestrate-contexts.md`.
23
+
24
+ ## Conventions and pitfalls
25
+
26
+ - Outside a `run`/`enter` scope there is no store; guard with `hasContext` when code may run unscoped.
27
+ - `enter` leaks until cleared; pair `enterAll` with `clearAll` at the end of the request.
28
+ - Worker threads do not share the store; serialize data across and re-enter.
29
+ - Context is not shared state: it vanishes with the scope.
30
+ - One context in a cooperative framework needs no manager; use plain `run`.
31
+
32
+ ## When to reach for it
33
+
34
+ - You have request-scoped data (user, tenant, trace id, db transaction) that you'd otherwise thread through every function as a parameter. One `userContext.get("userId")` anywhere down the call tree replaces five layers of plumbing.
35
+ - You're inside a `@warlock.js/*` project and want consistent context handling across modules. The framework already uses this package internally for request + user + tenant contexts.
36
+ - You'd reach for **cls-hooked**, **nest-context**, or a bare `AsyncLocalStorage<T>` and want a typed wrapper with `run` / `enter` / `update` / `get` / `set` semantics out of the box.
37
+
38
+ Skip if your call chain is a single function with no `await` boundaries — just pass the data as a parameter. Skip if you need cross-request shared state — that's a cache or database, not a context.
39
+
40
+ ## What it is in one sentence
41
+
42
+ Each `Context<TStore>` subclass declares a typed store shape and what payload builds it; the framework uses Node's `AsyncLocalStorage` under the hood so the store propagates through every `await` inside the scope and disappears when the scope ends.
43
+
44
+ ## Two operating modes — when to pick which
45
+
46
+ | Situation | Reach for |
47
+ | ----------------------------------------------------------------------- | ---------------------------------------------------------- |
48
+ | Framework gives you a callback to wrap | `context.run(store, callback)` |
49
+ | Framework expects middleware that returns synchronously (Express, etc.) | `context.enter(store)` |
50
+ | You have 2+ contexts active for the same request | `contextManager.runAll(stores, callback)` |
51
+ | Middleware-style with 2+ contexts | `contextManager.enterAll(stores)` then `clearAll()` at end |
52
+ | You only have one context and the framework cooperates | Single `context.run(...)`. Skip the manager. |
53
+
54
+ ## What this package deliberately doesn't do
55
+
56
+ - **Persist data across requests.** AsyncLocalStorage dies with the scope. For cross-request state, reach for `@warlock.js/cache` or a database.
57
+ - **Cross-thread context.** Worker threads don't share AsyncLocalStorage with the main thread. Serialize the data you need across the boundary and re-enter on the other side.
58
+ - **Browser context.** Server-side only. The browser equivalent is React Context or a state library.
59
+ - **Implicit context for non-async code.** If your call stack has no `await`, the storage works but there's no propagation benefit — just pass the value as a parameter.
60
+
61
+ ## See also
62
+
63
+ - The `warlock-js-core` skill index — the parent framework; `context` is one of its foundation packages.
64
+
65
+
66
+ ## define-context `@warlock.js/context/skills/define-context/SKILL.md`
8
67
 
9
68
  ---
10
69
  name: define-context
@@ -165,7 +224,7 @@ Now `tenantContext.tenantId` reads better than `tenantContext.get("tenantId")` a
165
224
  - Don't share one context instance across unrelated concerns. One typed context per domain concept reads better than one fat `globalContext`.
166
225
 
167
226
 
168
- ## orchestrate-contexts `@warlock.js/context/orchestrate-contexts/SKILL.md`
227
+ ## orchestrate-contexts `@warlock.js/context/skills/orchestrate-contexts/SKILL.md`
169
228
 
170
229
  ---
171
230
  name: orchestrate-contexts
@@ -328,75 +387,3 @@ async function handleRequest(req: any, res: any) {
328
387
  - Don't expect `enterAll()` to auto-clean. It's a one-way setup — pair with `clearAll()` at the end of the request, or just use `runAll` when you can.
329
388
 
330
389
 
331
- ## overview `@warlock.js/context/overview/SKILL.md`
332
-
333
- ---
334
- name: overview
335
- description: "@warlock.js/context overview for orientation and choosing the focused skill for the task."
336
- ---
337
-
338
- # `@warlock.js/context` — overview
339
-
340
- Two-file package: a typed wrapper over Node's `AsyncLocalStorage` and a singleton that runs several of them together. That's it. The entire surface fits in two skills below — most callers only need the first one.
341
-
342
- ## When to reach for it
343
-
344
- - You have request-scoped data (user, tenant, trace id, db transaction) that you'd otherwise thread through every function as a parameter. One `userContext.get("userId")` anywhere down the call tree replaces five layers of plumbing.
345
- - You're inside a `@warlock.js/*` project and want consistent context handling across modules. The framework already uses this package internally for request + user + tenant contexts.
346
- - You'd reach for `cls-hooked`, `nest-context`, or a bare `AsyncLocalStorage<T>` and want a typed wrapper with `run` / `enter` / `update` / `get` / `set` semantics out of the box.
347
-
348
- Skip if your call chain is a single function with no `await` boundaries — just pass the data as a parameter. Skip if you need cross-request shared state — that's a cache or database, not a context.
349
-
350
- ## What it is in one sentence
351
-
352
- Each `Context<TStore>` subclass declares a typed store shape and what payload builds it; the framework uses Node's `AsyncLocalStorage` under the hood so the store propagates through every `await` inside the scope and disappears when the scope ends.
353
-
354
- ## Skills index
355
-
356
- Two task skills cover everything. The first one is the daily-use one; the second is for when you have multiple contexts active at the same time.
357
-
358
- ### `define-context`
359
-
360
- Extend `Context<TStore>` to declare what your context stores and how it's
361
- built. Implement `buildStore(payload?)`; use `run` / `enter` / `update` /
362
- `get` / `set` / `getStore` / `clear` / `hasContext` to interact with the
363
- store from anywhere in the async scope.
364
-
365
- Load when sharing data (user, tenant, trace id) across async calls
366
- without threading it through every function — i.e. ~90% of the time you
367
- use this package.
368
-
369
- ### `orchestrate-contexts`
370
-
371
- Register multiple `Context<TStore>` instances on the `contextManager`
372
- singleton and run them all together with a single call. Covers
373
- `register` / `unregister`, `buildStores`, `runAll` / `enterAll`,
374
- `clearAll`, `getContext` / `hasContext`.
375
-
376
- Load when several contexts apply to the same scope (request + database
377
-
378
- - trace + tenant) and you'd otherwise nest `run()` calls by hand.
379
-
380
- ## Two operating modes — when to pick which
381
-
382
- | Situation | Reach for |
383
- | ----------------------------------------------------------------------- | ---------------------------------------------------------- |
384
- | Framework gives you a callback to wrap | `context.run(store, callback)` |
385
- | Framework expects middleware that returns synchronously (Express, etc.) | `context.enter(store)` |
386
- | You have 2+ contexts active for the same request | `contextManager.runAll(stores, callback)` |
387
- | Middleware-style with 2+ contexts | `contextManager.enterAll(stores)` then `clearAll()` at end |
388
- | You only have one context and the framework cooperates | Single `context.run(...)`. Skip the manager. |
389
-
390
- ## What this package deliberately doesn't do
391
-
392
- - **Persist data across requests.** AsyncLocalStorage dies with the scope. For cross-request state, reach for `@warlock.js/cache` or a database.
393
- - **Cross-thread context.** Worker threads don't share AsyncLocalStorage with the main thread. Serialize the data you need across the boundary and re-enter on the other side.
394
- - **Browser context.** Server-side only. The browser equivalent is React Context or a state library.
395
- - **Implicit context for non-async code.** If your call stack has no `await`, the storage works but there's no propagation benefit — just pass the value as a parameter.
396
-
397
- ## See also
398
-
399
- - The `overview` topic of the `warlock-js-core` skill — the parent framework; `context` is one of its foundation packages.
400
- - `mongez-agent-kit-authoring-skills` (load via agent-kit sync) — how this `overview` topic becomes the front-door skill in `.claude/skills/warlock-js-context-overview/`.
401
-
402
-
package/llms.txt CHANGED
@@ -6,6 +6,6 @@
6
6
 
7
7
  ## Skills
8
8
 
9
- - [define-context](@warlock.js/context/define-context/SKILL.md): Extend Context<TStore> to define an AsyncLocalStorage-backed typed context — implement buildStore, use run / enter / update / get / set / getStore / clear / hasContext. Triggers: `Context`, `Context<TStore>`, `buildStore`, `run`, `enter`, `update`, `get`, `set`, `getStore`, `clear`, `hasContext`; "share user/tenant/trace id across async calls", "AsyncLocalStorage typed wrapper", "request-scoped store without thread-through"; typical import `import { Context } from "@warlock.js/context"`. Skip: orchestrating multiple contexts — the `orchestrate-contexts` topic; native `AsyncLocalStorage`, `cls-hooked`, `nest-context`, React Context.
10
- - [orchestrate-contexts](@warlock.js/context/orchestrate-contexts/SKILL.md): Orchestrate multiple Context<TStore> instances via the contextManager singleton — register, buildStores, runAll, enterAll, clearAll. Triggers: `contextManager`, `register`, `buildStores`, `runAll`, `enterAll`, `clearAll`, `unregister`, `getContext`, `hasContext`; "run multiple contexts active for the same scope", "register contexts at boot", "avoid nested run() calls for request + database + tenant"; typical import `import { contextManager } from "@warlock.js/context"`. Skip: defining a single context class — the `define-context` topic; native `AsyncLocalStorage` nesting, `cls-hooked` namespaces.
11
- - [overview](@warlock.js/context/overview/SKILL.md): @warlock.js/context overview for orientation and choosing the focused skill for the task.
9
+ - [Package orientation](@warlock.js/context/skills/index.md): Typed async context propagation with `Context` and `ContextManager`, built on AsyncLocalStorage. Use for "avoid passing the tenant everywhere", request-scoped users, trace IDs, `run`, `enter`, `get`, `set` or coordinating several contexts. Not this package → @warlock.js/core for the framework request context; @warlock.js/cache for state shared across requests; @warlock.js/cascade for database transactions.
10
+ - [define-context](@warlock.js/context/skills/define-context/SKILL.md): Extend Context<TStore> to define an AsyncLocalStorage-backed typed context — implement buildStore, use run / enter / update / get / set / getStore / clear / hasContext. Triggers: `Context`, `Context<TStore>`, `buildStore`, `run`, `enter`, `update`, `get`, `set`, `getStore`, `clear`, `hasContext`; "share user/tenant/trace id across async calls", "AsyncLocalStorage typed wrapper", "request-scoped store without thread-through"; typical import `import { Context } from "@warlock.js/context"`. Skip: orchestrating multiple contexts — the `orchestrate-contexts` topic; native `AsyncLocalStorage`, `cls-hooked`, `nest-context`, React Context.
11
+ - [orchestrate-contexts](@warlock.js/context/skills/orchestrate-contexts/SKILL.md): Orchestrate multiple Context<TStore> instances via the contextManager singleton — register, buildStores, runAll, enterAll, clearAll. Triggers: `contextManager`, `register`, `buildStores`, `runAll`, `enterAll`, `clearAll`, `unregister`, `getContext`, `hasContext`; "run multiple contexts active for the same scope", "register contexts at boot", "avoid nested run() calls for request + database + tenant"; typical import `import { contextManager } from "@warlock.js/context"`. Skip: defining a single context class — the `define-context` topic; native `AsyncLocalStorage` nesting, `cls-hooked` namespaces.
package/package.json CHANGED
@@ -25,7 +25,7 @@
25
25
  "engines": {
26
26
  "node": ">=18.0.0"
27
27
  },
28
- "version": "5.34.1",
28
+ "version": "5.34.3",
29
29
  "main": "./cjs/index.cjs",
30
30
  "module": "./esm/index.mjs",
31
31
  "types": "./esm/index.d.mts",
package/skills/index.md CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: 'Typed request-scoped context on Node AsyncLocalStorage, so data (user, tenant, trace id, transaction) flows through awaits without parameter threading. Exports `Context`, `contextManager`, `ContextManager`. Use for: "share the current user or tenant across async calls", "request-scoped storage", "AsyncLocalStorage wrapper", "run several contexts together", "avoid passing data through every function". Not this package: cross-request state → @warlock.js/cache or a database; HTTP request/response objects → @warlock.js/core.'
2
+ description: 'Typed async context propagation with `Context` and `ContextManager`, built on AsyncLocalStorage. Use for "avoid passing the tenant everywhere", request-scoped users, trace IDs, `run`, `enter`, `get`, `set` or coordinating several contexts. Not this package → @warlock.js/core for the framework request context; @warlock.js/cache for state shared across requests; @warlock.js/cascade for database transactions.'
3
3
  ---
4
4
 
5
5
  # @warlock.js/context
@@ -8,7 +8,7 @@ A thin typed wrapper over `AsyncLocalStorage`. Each `Context<TStore>` subclass d
8
8
 
9
9
  ## The 80% path
10
10
 
11
- 1. Orient with `overview.md`.
11
+ 1. Use this index for orientation and choose a task below.
12
12
  2. Subclass `Context`, implement `buildStore`, read with `get` / `set` anywhere down the call tree: `define-context.md`.
13
13
  3. Wrap work with `run(store, callback)`, or `enter(store)` for middleware that cannot wrap a callback: `define-context.md`.
14
14
  4. With two or more active contexts, register them on `contextManager` and use `runAll` / `enterAll`: `orchestrate-contexts.md`.
@@ -20,3 +20,36 @@ A thin typed wrapper over `AsyncLocalStorage`. Each `Context<TStore>` subclass d
20
20
  - Worker threads do not share the store; serialize data across and re-enter.
21
21
  - Context is not shared state: it vanishes with the scope.
22
22
  - One context in a cooperative framework needs no manager; use plain `run`.
23
+
24
+ ## When to reach for it
25
+
26
+ - You have request-scoped data (user, tenant, trace id, db transaction) that you'd otherwise thread through every function as a parameter. One `userContext.get("userId")` anywhere down the call tree replaces five layers of plumbing.
27
+ - You're inside a `@warlock.js/*` project and want consistent context handling across modules. The framework already uses this package internally for request + user + tenant contexts.
28
+ - You'd reach for **cls-hooked**, **nest-context**, or a bare `AsyncLocalStorage<T>` and want a typed wrapper with `run` / `enter` / `update` / `get` / `set` semantics out of the box.
29
+
30
+ Skip if your call chain is a single function with no `await` boundaries — just pass the data as a parameter. Skip if you need cross-request shared state — that's a cache or database, not a context.
31
+
32
+ ## What it is in one sentence
33
+
34
+ Each `Context<TStore>` subclass declares a typed store shape and what payload builds it; the framework uses Node's `AsyncLocalStorage` under the hood so the store propagates through every `await` inside the scope and disappears when the scope ends.
35
+
36
+ ## Two operating modes — when to pick which
37
+
38
+ | Situation | Reach for |
39
+ | ----------------------------------------------------------------------- | ---------------------------------------------------------- |
40
+ | Framework gives you a callback to wrap | `context.run(store, callback)` |
41
+ | Framework expects middleware that returns synchronously (Express, etc.) | `context.enter(store)` |
42
+ | You have 2+ contexts active for the same request | `contextManager.runAll(stores, callback)` |
43
+ | Middleware-style with 2+ contexts | `contextManager.enterAll(stores)` then `clearAll()` at end |
44
+ | You only have one context and the framework cooperates | Single `context.run(...)`. Skip the manager. |
45
+
46
+ ## What this package deliberately doesn't do
47
+
48
+ - **Persist data across requests.** AsyncLocalStorage dies with the scope. For cross-request state, reach for `@warlock.js/cache` or a database.
49
+ - **Cross-thread context.** Worker threads don't share AsyncLocalStorage with the main thread. Serialize the data you need across the boundary and re-enter on the other side.
50
+ - **Browser context.** Server-side only. The browser equivalent is React Context or a state library.
51
+ - **Implicit context for non-async code.** If your call stack has no `await`, the storage works but there's no propagation benefit — just pass the value as a parameter.
52
+
53
+ ## See also
54
+
55
+ - The `warlock-js-core` skill index — the parent framework; `context` is one of its foundation packages.
@@ -1,68 +0,0 @@
1
- ---
2
- name: overview
3
- description: "@warlock.js/context overview for orientation and choosing the focused skill for the task."
4
- ---
5
-
6
- # `@warlock.js/context` — overview
7
-
8
- Two-file package: a typed wrapper over Node's `AsyncLocalStorage` and a singleton that runs several of them together. That's it. The entire surface fits in two skills below — most callers only need the first one.
9
-
10
- ## When to reach for it
11
-
12
- - You have request-scoped data (user, tenant, trace id, db transaction) that you'd otherwise thread through every function as a parameter. One `userContext.get("userId")` anywhere down the call tree replaces five layers of plumbing.
13
- - You're inside a `@warlock.js/*` project and want consistent context handling across modules. The framework already uses this package internally for request + user + tenant contexts.
14
- - You'd reach for `cls-hooked`, `nest-context`, or a bare `AsyncLocalStorage<T>` and want a typed wrapper with `run` / `enter` / `update` / `get` / `set` semantics out of the box.
15
-
16
- Skip if your call chain is a single function with no `await` boundaries — just pass the data as a parameter. Skip if you need cross-request shared state — that's a cache or database, not a context.
17
-
18
- ## What it is in one sentence
19
-
20
- Each `Context<TStore>` subclass declares a typed store shape and what payload builds it; the framework uses Node's `AsyncLocalStorage` under the hood so the store propagates through every `await` inside the scope and disappears when the scope ends.
21
-
22
- ## Skills index
23
-
24
- Two task skills cover everything. The first one is the daily-use one; the second is for when you have multiple contexts active at the same time.
25
-
26
- ### `define-context`
27
-
28
- Extend `Context<TStore>` to declare what your context stores and how it's
29
- built. Implement `buildStore(payload?)`; use `run` / `enter` / `update` /
30
- `get` / `set` / `getStore` / `clear` / `hasContext` to interact with the
31
- store from anywhere in the async scope.
32
-
33
- Load when sharing data (user, tenant, trace id) across async calls
34
- without threading it through every function — i.e. ~90% of the time you
35
- use this package.
36
-
37
- ### `orchestrate-contexts`
38
-
39
- Register multiple `Context<TStore>` instances on the `contextManager`
40
- singleton and run them all together with a single call. Covers
41
- `register` / `unregister`, `buildStores`, `runAll` / `enterAll`,
42
- `clearAll`, `getContext` / `hasContext`.
43
-
44
- Load when several contexts apply to the same scope (request + database
45
-
46
- - trace + tenant) and you'd otherwise nest `run()` calls by hand.
47
-
48
- ## Two operating modes — when to pick which
49
-
50
- | Situation | Reach for |
51
- | ----------------------------------------------------------------------- | ---------------------------------------------------------- |
52
- | Framework gives you a callback to wrap | `context.run(store, callback)` |
53
- | Framework expects middleware that returns synchronously (Express, etc.) | `context.enter(store)` |
54
- | You have 2+ contexts active for the same request | `contextManager.runAll(stores, callback)` |
55
- | Middleware-style with 2+ contexts | `contextManager.enterAll(stores)` then `clearAll()` at end |
56
- | You only have one context and the framework cooperates | Single `context.run(...)`. Skip the manager. |
57
-
58
- ## What this package deliberately doesn't do
59
-
60
- - **Persist data across requests.** AsyncLocalStorage dies with the scope. For cross-request state, reach for `@warlock.js/cache` or a database.
61
- - **Cross-thread context.** Worker threads don't share AsyncLocalStorage with the main thread. Serialize the data you need across the boundary and re-enter on the other side.
62
- - **Browser context.** Server-side only. The browser equivalent is React Context or a state library.
63
- - **Implicit context for non-async code.** If your call stack has no `await`, the storage works but there's no propagation benefit — just pass the value as a parameter.
64
-
65
- ## See also
66
-
67
- - The `overview` topic of the `warlock-js-core` skill — the parent framework; `context` is one of its foundation packages.
68
- - `mongez-agent-kit-authoring-skills` (load via agent-kit sync) — how this `overview` topic becomes the front-door skill in `.claude/skills/warlock-js-context-overview/`.