@telorun/http-server 0.3.4 → 0.4.0

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
@@ -1,5 +1,24 @@
1
1
  # @telorun/http-server
2
2
 
3
+ ## 0.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 0f80fc5: `Bench.Suite.scenarios[*]` and `Http.Server.notFoundHandler` follow the canonical sibling shape: `invoke:` describes the dispatch target only; `inputs:` carries the call-time arguments as a sibling. The previously-accepted nested `invoke.inputs` form is gone — the benchmark runtime now reads `scenario.inputs` and the http-server runtime now reads `notFoundHandler.inputs`. Five benchmark manifests, one example, and `apps/registry/telo.yaml` migrated to the sibling form.
8
+
9
+ Statically validate CEL expressions inside `Telo.Definition` template bodies. The analyzer now registers `self` (typed from the definition's `schema:`) and `inputs` (typed from `inputType:`, falling back to the `extends:`-declared abstract's `inputType:`) as available variables in `resources:` / `invoke:` / `run:` / `provide:` / top-level `inputs:` / top-level `result:` fields, catching typos at load time instead of first invocation.
10
+
11
+ Aligns Telo.Definition's template-body shape with how Run.Sequence steps factor dispatch from data: `invoke:` / `provide:` / `run:` describe the dispatch target only; `inputs:` (values passed to the target) and `result:` (provide-only post-call mapping) live as top-level siblings on the definition. The previous nested `invoke.inputs` shape is gone — the kernel template controller now reads `definition.inputs`, and `modules/sql-repository/Read` migrates to the sibling form.
12
+
13
+ Inside top-level `result:`, the `result` CEL variable is typed from the dispatch target's `outputType:`. The produced top-level `result` value is also AJV-checked against the abstract this definition `extends` (`outputType`); top-level `inputs` is AJV-checked against the dispatch target's `inputType` when declared. Mismatches surface as a new `TEMPLATE_TARGET_MISMATCH` diagnostic.
14
+
15
+ Adds two reusable context-annotation forms used by the `Telo.Definition` builtin schema and available to any module that needs the same capabilities:
16
+
17
+ - `x-telo-context-from-root: "<path>"` — root-anchored navigation (replace semantics), used to type variables sourced from a top-level field regardless of where the CEL appears.
18
+ - `x-telo-context-from-ref-kind: "<refPath>#<field>"` — reads a kind name from `manifestRoot.<refPath>`, resolves it via the definition registry, and returns that kind's `<field>` schema.
19
+
20
+ Schema-extracted contexts are now sorted by scope specificity (longest first) so the first-match-wins resolver picks the most-specific context. No existing module relied on the previous ordering (no overlapping scopes), so this change is observably backward-compatible.
21
+
3
22
  ## 0.3.4
4
23
 
5
24
  ### Patch Changes
@@ -36,6 +36,7 @@ type HttpServerResource = RuntimeResource & {
36
36
  }>;
37
37
  notFoundHandler?: {
38
38
  invoke: KindRef<Invocable>;
39
+ inputs?: Record<string, unknown>;
39
40
  returns?: ReturnEntry[];
40
41
  catches?: CatchEntry[];
41
42
  };
@@ -138,9 +138,22 @@ class HttpServer {
138
138
  };
139
139
  const acceptHeader = request.headers["accept"]?.toString();
140
140
  const sink = fastifyReplySink(reply);
141
+ // Expand the `inputs:` sibling template against the request context,
142
+ // then pass the merged shape (spread for convenience + `inputs:` field
143
+ // for handlers that read it explicitly) to the dispatch target. Same
144
+ // contract Api.routes[*] uses. When no `inputs:` is declared, the
145
+ // request context itself is forwarded so existing manifests that read
146
+ // `request.*` directly continue to work.
147
+ const resolvedInputs = handler.inputs && Object.keys(handler.inputs).length > 0
148
+ ? (this.ctx.moduleContext.expandWith(handler.inputs, requestContext) ?? {})
149
+ : requestContext;
150
+ const invokeInput = {
151
+ ...resolvedInputs,
152
+ inputs: resolvedInputs,
153
+ };
141
154
  let result;
142
155
  try {
143
- result = await this.ctx.invoke(handler.kind, handler.name, requestContext);
156
+ result = await this.ctx.invoke(handler.kind, handler.name, invokeInput);
144
157
  }
145
158
  catch (err) {
146
159
  if (!isInvokeError(err))
@@ -206,7 +219,7 @@ export async function create(resource, ctx) {
206
219
  resolvedNotFoundHandler = {
207
220
  kind,
208
221
  name,
209
- inputs: invoke?.inputs ?? {},
222
+ inputs: resource.notFoundHandler.inputs ?? {},
210
223
  returns: resource.notFoundHandler.returns,
211
224
  catches: resource.notFoundHandler.catches,
212
225
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@telorun/http-server",
3
- "version": "0.3.4",
3
+ "version": "0.4.0",
4
4
  "description": "Telo HTTP Server module - HTTP server and API resource kinds for Telo manifests.",
5
5
  "keywords": [
6
6
  "telo",
@@ -54,6 +54,7 @@ type HttpServerResource = RuntimeResource & {
54
54
  }>;
55
55
  notFoundHandler?: {
56
56
  invoke: KindRef<Invocable>;
57
+ inputs?: Record<string, unknown>;
57
58
  returns?: ReturnEntry[];
58
59
  catches?: CatchEntry[];
59
60
  };
@@ -221,9 +222,24 @@ class HttpServer implements ResourceInstance {
221
222
 
222
223
  const sink = fastifyReplySink(reply);
223
224
 
225
+ // Expand the `inputs:` sibling template against the request context,
226
+ // then pass the merged shape (spread for convenience + `inputs:` field
227
+ // for handlers that read it explicitly) to the dispatch target. Same
228
+ // contract Api.routes[*] uses. When no `inputs:` is declared, the
229
+ // request context itself is forwarded so existing manifests that read
230
+ // `request.*` directly continue to work.
231
+ const resolvedInputs: Record<string, any> =
232
+ handler.inputs && Object.keys(handler.inputs).length > 0
233
+ ? ((this.ctx.moduleContext.expandWith(handler.inputs, requestContext) as any) ?? {})
234
+ : requestContext;
235
+ const invokeInput: Record<string, any> = {
236
+ ...resolvedInputs,
237
+ inputs: resolvedInputs,
238
+ };
239
+
224
240
  let result: any;
225
241
  try {
226
- result = await this.ctx.invoke(handler.kind, handler.name, requestContext);
242
+ result = await this.ctx.invoke(handler.kind, handler.name, invokeInput);
227
243
  } catch (err) {
228
244
  if (!isInvokeError(err)) throw err;
229
245
  return dispatchCatches(
@@ -310,7 +326,7 @@ export async function create(
310
326
  resolvedNotFoundHandler = {
311
327
  kind,
312
328
  name,
313
- inputs: (invoke as any)?.inputs ?? {},
329
+ inputs: resource.notFoundHandler.inputs ?? {},
314
330
  returns: resource.notFoundHandler.returns,
315
331
  catches: resource.notFoundHandler.catches,
316
332
  };