@rotorsoft/act-http 1.10.22 → 1.10.24
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 +7 -2
- package/dist/.tsbuildinfo +1 -1
- package/dist/@types/api/dispatch.d.ts +44 -0
- package/dist/@types/api/dispatch.d.ts.map +1 -0
- package/dist/@types/hono/index.d.ts +2 -20
- package/dist/@types/hono/index.d.ts.map +1 -1
- package/dist/@types/openapi/index.d.ts +2 -19
- package/dist/@types/openapi/index.d.ts.map +1 -1
- package/dist/@types/sse/broadcast.d.ts +2 -3
- package/dist/@types/sse/broadcast.d.ts.map +1 -1
- package/dist/@types/trpc/index.d.ts +1 -73
- package/dist/@types/trpc/index.d.ts.map +1 -1
- package/dist/chunk-H545LMMV.js +28 -0
- package/dist/chunk-H545LMMV.js.map +1 -0
- package/dist/hono/index.cjs +72 -64
- package/dist/hono/index.cjs.map +1 -1
- package/dist/hono/index.js +43 -52
- package/dist/hono/index.js.map +1 -1
- package/dist/openapi/index.cjs.map +1 -1
- package/dist/openapi/index.js.map +1 -1
- package/dist/sse/index.cjs +1 -13
- package/dist/sse/index.cjs.map +1 -1
- package/dist/sse/index.js +1 -3
- package/dist/sse/index.js.map +1 -1
- package/dist/trpc/index.cjs +54 -55
- package/dist/trpc/index.cjs.map +1 -1
- package/dist/trpc/index.js +25 -43
- package/dist/trpc/index.js.map +1 -1
- package/package.json +6 -6
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { Actor, Target } from "@rotorsoft/act";
|
|
2
|
+
import type { IdempotencyStore } from "@rotorsoft/act-ops/idempotency";
|
|
3
|
+
/**
|
|
4
|
+
* The Act surface the generated transports walk: the registry's action
|
|
5
|
+
* name → owning-state map and `do(...)`. A structural bound lets `TApp`
|
|
6
|
+
* infer to the caller's concrete `Act<...>` without leaking the variance of
|
|
7
|
+
* its nested types, and without `any`.
|
|
8
|
+
*/
|
|
9
|
+
export type ActSurface = {
|
|
10
|
+
readonly registry: {
|
|
11
|
+
actions: Record<string, {
|
|
12
|
+
readonly name: string;
|
|
13
|
+
readonly actions: Record<string, unknown>;
|
|
14
|
+
}>;
|
|
15
|
+
};
|
|
16
|
+
do(action: string, target: Target, payload: unknown): Promise<unknown>;
|
|
17
|
+
};
|
|
18
|
+
/** The target resolvers a generated transport takes, over its own context. */
|
|
19
|
+
type TargetResolvers<C> = {
|
|
20
|
+
readonly stream: (action_name: string, input: unknown, ctx: C) => string | Promise<string>;
|
|
21
|
+
readonly expectedVersion?: (action_name: string, input: unknown, ctx: C) => number | undefined | Promise<number | undefined>;
|
|
22
|
+
};
|
|
23
|
+
/** What one generated action call came to; each transport maps the refusals. */
|
|
24
|
+
export type Dispatched = {
|
|
25
|
+
kind: "done";
|
|
26
|
+
result: unknown;
|
|
27
|
+
} | {
|
|
28
|
+
kind: "missing-key";
|
|
29
|
+
} | {
|
|
30
|
+
kind: "in-flight";
|
|
31
|
+
} | {
|
|
32
|
+
kind: "conflict";
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* One generated action call: resolve the target from the validated input,
|
|
36
|
+
* then run `app.do` on the raw payload (it parses again itself, and a second
|
|
37
|
+
* parse of the parsed value would run every `.transform()` twice), under
|
|
38
|
+
* `Idempotency-Key` dedup when a store is set. A duplicate of a key still
|
|
39
|
+
* running is `in-flight`, since the original may yet fail and release it;
|
|
40
|
+
* one already committed is `conflict`.
|
|
41
|
+
*/
|
|
42
|
+
export declare function make_dispatch<C>(app: ActSurface, resolvers: TargetResolvers<C>, store: IdempotencyStore | undefined): (action_name: string, input: unknown, payload: unknown, ctx: C, actor: Actor, key: () => string | undefined) => Promise<Dispatched>;
|
|
43
|
+
export {};
|
|
44
|
+
//# sourceMappingURL=dispatch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.d.ts","sourceRoot":"","sources":["../../../src/api/dispatch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AAIvE;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG;IACvB,QAAQ,CAAC,QAAQ,EAAE;QACjB,OAAO,EAAE,MAAM,CACb,MAAM,EACN;YACE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;YACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;SAC3C,CACF,CAAC;KACH,CAAC;IACF,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CACxE,CAAC;AAEF,8EAA8E;AAC9E,KAAK,eAAe,CAAC,CAAC,IAAI;IACxB,QAAQ,CAAC,MAAM,EAAE,CACf,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,CAAC,KACH,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9B,QAAQ,CAAC,eAAe,CAAC,EAAE,CACzB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,CAAC,KACH,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;CACvD,CAAC;AAEF,gFAAgF;AAChF,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,aAAa,CAAA;CAAE,GACvB;IAAE,IAAI,EAAE,WAAW,CAAA;CAAE,GACrB;IAAE,IAAI,EAAE,UAAU,CAAA;CAAE,CAAC;AAEzB;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAC7B,GAAG,EAAE,UAAU,EACf,SAAS,EAAE,eAAe,CAAC,CAAC,CAAC,EAC7B,KAAK,EAAE,gBAAgB,GAAG,SAAS,iBAKpB,MAAM,SACZ,OAAO,WACL,OAAO,OACX,CAAC,SACC,KAAK,OACP,MAAM,MAAM,GAAG,SAAS,KAC5B,OAAO,CAAC,UAAU,CAAC,CAevB"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import type { Actor
|
|
1
|
+
import type { Actor } from "@rotorsoft/act";
|
|
2
2
|
import type { IdempotencyStore } from "@rotorsoft/act-ops/idempotency";
|
|
3
3
|
import type { Context, MiddlewareHandler } from "hono";
|
|
4
4
|
import { Hono } from "hono";
|
|
5
|
+
import { type ActSurface } from "../api/dispatch.js";
|
|
5
6
|
import { type ActorExtractor, type SseOptions } from "../api/index.js";
|
|
6
7
|
/**
|
|
7
8
|
* Hono context variables this subpath contributes. The generic on
|
|
@@ -92,24 +93,6 @@ export type HonoOptions = {
|
|
|
92
93
|
export declare function authenticated(extractor: ActorExtractor): MiddlewareHandler<{
|
|
93
94
|
Variables: ActMiddlewareVariables;
|
|
94
95
|
}>;
|
|
95
|
-
/**
|
|
96
|
-
* Structural shape of the Act surface this generator walks at
|
|
97
|
-
* runtime — the registry's action-name → owning-state map plus the
|
|
98
|
-
* `do(...)` dispatch. Letting TApp infer to the caller's concrete
|
|
99
|
-
* `Act<...>` against this structural bound keeps nested variance
|
|
100
|
-
* out of the signature and avoids `any` in either direction.
|
|
101
|
-
*
|
|
102
|
-
* @internal
|
|
103
|
-
*/
|
|
104
|
-
type ActSurface = {
|
|
105
|
-
readonly registry: {
|
|
106
|
-
actions: Record<string, {
|
|
107
|
-
readonly name: string;
|
|
108
|
-
readonly actions: Record<string, unknown>;
|
|
109
|
-
}>;
|
|
110
|
-
};
|
|
111
|
-
do(action: string, target: Target, payload: unknown): Promise<unknown>;
|
|
112
|
-
};
|
|
113
96
|
/**
|
|
114
97
|
* Build a typed Hono REST surface from a built `Act` instance.
|
|
115
98
|
*
|
|
@@ -145,5 +128,4 @@ type ActSurface = {
|
|
|
145
128
|
export declare function hono<TApp extends ActSurface = ActSurface>(app: TApp, options: HonoOptions): Hono<{
|
|
146
129
|
Variables: ActMiddlewareVariables;
|
|
147
130
|
}>;
|
|
148
|
-
export {};
|
|
149
131
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hono/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/hono/index.ts"],"names":[],"mappings":"AAiDA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,gBAAgB,CAAC;AAC5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,KAAK,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,MAAM,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAAE,KAAK,UAAU,EAAiB,MAAM,oBAAoB,CAAC;AACpE,OAAO,EACL,KAAK,cAAc,EAMnB,KAAK,UAAU,EAEhB,MAAM,iBAAiB,CAAC;AAEzB;;;;;GAKG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,EAAE,KAAK,CAAC;CACd,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,CACf,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,OAAO,EACd,CAAC,EAAE,OAAO,KACP,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9B,QAAQ,CAAC,eAAe,CAAC,EAAE,CACzB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,OAAO,EACd,CAAC,EAAE,OAAO,KACP,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACtD,QAAQ,CAAC,WAAW,CAAC,EAAE;QACrB,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;QACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,CAAC;KACvD,CAAC;IACF;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC;IAC1B,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,cAAc,GACxB,iBAAiB,CAAC;IAAE,SAAS,EAAE,sBAAsB,CAAA;CAAE,CAAC,CAe1D;AAKD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,wBAAgB,IAAI,CAAC,IAAI,SAAS,UAAU,GAAG,UAAU,EACvD,GAAG,EAAE,IAAI,EACT,OAAO,EAAE,WAAW,GACnB,IAAI,CAAC;IAAE,SAAS,EAAE,sBAAsB,CAAA;CAAE,CAAC,CA2K7C"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ActSurface } from "../api/dispatch.js";
|
|
1
2
|
/**
|
|
2
3
|
* Minimal OpenAPI 3.1 document type. The emitter targets the 3.1
|
|
3
4
|
* spec; the type is intentionally a structural subset rather than
|
|
@@ -103,23 +104,6 @@ export type OpenAPIComponents = {
|
|
|
103
104
|
readonly schemas: Record<string, Record<string, unknown>>;
|
|
104
105
|
readonly responses: Record<string, OpenAPIResponse>;
|
|
105
106
|
};
|
|
106
|
-
/**
|
|
107
|
-
* Structural shape of the Act surface this emitter walks. Letting
|
|
108
|
-
* TApp infer to the caller's concrete `Act<TSchemaReg, ...>` instead
|
|
109
|
-
* of forcing it to fit a narrow framework-typed upper bound keeps
|
|
110
|
-
* the caller's variance from leaking — and avoids `any` in the
|
|
111
|
-
* signature.
|
|
112
|
-
*
|
|
113
|
-
* @internal
|
|
114
|
-
*/
|
|
115
|
-
type ActRegistryView = {
|
|
116
|
-
readonly registry: {
|
|
117
|
-
actions: Record<string, {
|
|
118
|
-
readonly name: string;
|
|
119
|
-
readonly actions: Record<string, unknown>;
|
|
120
|
-
}>;
|
|
121
|
-
};
|
|
122
|
-
};
|
|
123
107
|
/**
|
|
124
108
|
* Build an OpenAPI 3.1 document describing a built `Act` instance's
|
|
125
109
|
* action surface.
|
|
@@ -145,6 +129,5 @@ type ActRegistryView = {
|
|
|
145
129
|
* empty, or if any `servers[].url` fails URL parsing after
|
|
146
130
|
* `{variable}` substitution.
|
|
147
131
|
*/
|
|
148
|
-
export declare function openapi<TApp extends
|
|
149
|
-
export {};
|
|
132
|
+
export declare function openapi<TApp extends Pick<ActSurface, "registry">>(app: TApp, options: OpenAPIOptions): OpenAPIDocument;
|
|
150
133
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/openapi/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/openapi/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -30,9 +30,8 @@ export declare class BroadcastChannel<S extends BroadcastState = BroadcastState>
|
|
|
30
30
|
/**
|
|
31
31
|
* Called when a subscriber callback throws. The frame is still delivered
|
|
32
32
|
* to every other subscriber and the publish still returns normally — a
|
|
33
|
-
* bad consumer must not break the publisher
|
|
34
|
-
*
|
|
35
|
-
* routes framework logs.
|
|
33
|
+
* bad consumer must not break the publisher. Defaults to `console.error`;
|
|
34
|
+
* pass your logger here to route it with the rest of your logs.
|
|
36
35
|
*/
|
|
37
36
|
onSubscriberError?: (error: unknown, streamId: string) => void;
|
|
38
37
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"broadcast.d.ts","sourceRoot":"","sources":["../../../src/sse/broadcast.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,YAAY,EAEjB,KAAK,UAAU,EAChB,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"broadcast.d.ts","sourceRoot":"","sources":["../../../src/sse/broadcast.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,YAAY,EAEjB,KAAK,UAAU,EAChB,MAAM,YAAY,CAAC;AA4KpB,qBAAa,gBAAgB,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc;IACrE,OAAO,CAAC,QAAQ,CAAyC;IACzD,OAAO,CAAC,WAAW,CAAgB;IAEnC;;;OAGG;IACH,OAAO,CAAC,mBAAmB,CAA6C;IACxE,OAAO,CAAC,eAAe,CAA6B;IAEpD,YAAY,OAAO,CAAC,EAAE;QACpB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB;;;;;;;;;;;;;;WAcG;QACH,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;QAC3C;;;;;WAKG;QACH,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;QAC/D;;;;WAIG;QACH,UAAU,CAAC,EAAE,MAAM,CAAC;KACrB,EAQA;IAED;;;OAGG;IACH,OAAO,CAAC,gBAAgB;IAMxB;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,cAAc;IAKtB;;;;;;;;;;;;;;;;OAgBG;IACH,OAAO,CAAC,mBAAmB;IAS3B;;;;;;;OAOG;IACH,OAAO,CACL,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,CAAC,EACR,OAAO,GAAE,OAAO,CAAC,CAAC,CAAC,EAAO,GACzB,YAAY,CAAC,CAAC,CAAC,CAwCjB;IAED;;;;OAIG;IACH,OAAO,CACL,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,GACxB,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS,CA6C7B;IAED;;;OAGG;IACH,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CASzD;IAED,kDAAkD;IAClD,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAExC;IAED,8EAA8E;IAC9E,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAErC;IAED,4DAA4D;IAC5D,eAAe,CACb,QAAQ,EAAE,MAAM,EAChB,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,GACxB,YAAY,CAAC,CAAC,CAAC,GAAG,SAAS,CAE7B;IAED,oEAAoE;IACpE,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE7C;IAED,0DAA0D;IAC1D,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAEzC;IAED,+EAA+E;IAC/E,IAAI,KAAK,IAAI,UAAU,CAAC,CAAC,CAAC,CAEzB;CACF"}
|
|
@@ -1,58 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @packageDocumentation
|
|
3
|
-
* @module act-http/trpc
|
|
4
|
-
*
|
|
5
|
-
* tRPC subpath for the auto-generated API epic (#835). Walks the
|
|
6
|
-
* registry of a built `Act` once at function call and emits a typed
|
|
7
|
-
* router that exposes every registered action as a flat `mutation`,
|
|
8
|
-
* matching the shape hand-written tRPC routers in the Act ecosystem
|
|
9
|
-
* already use.
|
|
10
|
-
*
|
|
11
|
-
* Usage:
|
|
12
|
-
*
|
|
13
|
-
* ```ts
|
|
14
|
-
* import { trpc } from "@rotorsoft/act-http/trpc";
|
|
15
|
-
*
|
|
16
|
-
* const router = trpc(app, {
|
|
17
|
-
* actor: (ctx) => ({ id: ctx.user.id, name: ctx.user.name }),
|
|
18
|
-
* stream: (action, input, ctx) => input.stream ?? ctx.tenant,
|
|
19
|
-
* });
|
|
20
|
-
*
|
|
21
|
-
* // Client sees:
|
|
22
|
-
* // appRouter.PressKey.mutate({ key: "5" })
|
|
23
|
-
* // appRouter.OpenTicket.mutate({ title: "..." })
|
|
24
|
-
* ```
|
|
25
|
-
*
|
|
26
|
-
* The route shape is flat: one procedure per registered action at
|
|
27
|
-
* the top level. Action names are the unique identifiers across
|
|
28
|
-
* the registry (the framework already enforces no duplicates), so
|
|
29
|
-
* an extra namespace tier would be overhead in the common case.
|
|
30
|
-
* Pure mutations for this slice; query/projection wiring lives in
|
|
31
|
-
* a follow-up. See `libs/act-http/README.md` for the full surface
|
|
32
|
-
* walkthrough.
|
|
33
|
-
*
|
|
34
|
-
* **Actor lives on the context.** The generator wires an internal
|
|
35
|
-
* tRPC middleware that runs the host's
|
|
36
|
-
* {@link TrpcOptions.actor | actor extractor} once per call and
|
|
37
|
-
* injects the resolved {@link Actor} onto the downstream context as
|
|
38
|
-
* `ctx.actor`. Every generated mutation reads from there — auth
|
|
39
|
-
* resolves at the procedure boundary, not inside each action body,
|
|
40
|
-
* and any composed middleware (logging, tracing) sees the same
|
|
41
|
-
* `ctx.actor`. The middleware factory is also exported as
|
|
42
|
-
* {@link authenticated} for hosts that need to compose it into
|
|
43
|
-
* their own procedure chain.
|
|
44
|
-
*
|
|
45
|
-
* Composes the shared utilities at `@rotorsoft/act-http/api`:
|
|
46
|
-
* {@link ActorExtractor} for the auth seam, {@link toApiError} for
|
|
47
|
-
* the uniform error→status/code mapping, {@link withIdempotency}
|
|
48
|
-
* for `Idempotency-Key` dedup. Three transports (this one, Hono,
|
|
49
|
-
* OpenAPI) ride the same utilities so a client talking to two
|
|
50
|
-
* transports never sees two error shapes for the same framework
|
|
51
|
-
* error.
|
|
52
|
-
*/
|
|
53
|
-
import { type Target } from "@rotorsoft/act";
|
|
54
1
|
import type { IdempotencyStore } from "@rotorsoft/act-ops/idempotency";
|
|
55
2
|
import { type AnyTRPCMiddlewareFunction, type AnyTRPCMutationProcedure, type AnyTRPCRootTypes, type TRPCBuiltRouter } from "@trpc/server";
|
|
3
|
+
import { type ActSurface } from "../api/dispatch.js";
|
|
56
4
|
import { type ActorExtractor, type SseOptions } from "../api/index.js";
|
|
57
5
|
/**
|
|
58
6
|
* Per-call options for {@link trpc}. The host supplies the three
|
|
@@ -147,26 +95,6 @@ export type TrpcOptions<Ctx> = {
|
|
|
147
95
|
* in the extractor body).
|
|
148
96
|
*/
|
|
149
97
|
export declare function authenticated(extractor: ActorExtractor): AnyTRPCMiddlewareFunction;
|
|
150
|
-
/**
|
|
151
|
-
* Structural shape of the Act surface this generator walks at
|
|
152
|
-
* runtime — the registry's action-name → owning-state map plus the
|
|
153
|
-
* `do(...)` dispatch. Letting TApp infer to the caller's concrete
|
|
154
|
-
* `Act<...>` against this structural bound (instead of forcing it
|
|
155
|
-
* to fit a narrow framework-typed upper bound) keeps the variance
|
|
156
|
-
* of nested types like `PatchHandler` from leaking — and avoids
|
|
157
|
-
* `any` in the signature.
|
|
158
|
-
*
|
|
159
|
-
* @internal
|
|
160
|
-
*/
|
|
161
|
-
type ActSurface = {
|
|
162
|
-
readonly registry: {
|
|
163
|
-
actions: Record<string, {
|
|
164
|
-
readonly name: string;
|
|
165
|
-
readonly actions: Record<string, unknown>;
|
|
166
|
-
}>;
|
|
167
|
-
};
|
|
168
|
-
do(action: string, target: Target, payload: unknown): Promise<unknown>;
|
|
169
|
-
};
|
|
170
98
|
/**
|
|
171
99
|
* Generated router type — one mutation procedure per action name in
|
|
172
100
|
* `TApp`'s registry. Mapped over the concrete action keys so
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/trpc/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/trpc/index.ts"],"names":[],"mappings":"AA0DA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EACL,KAAK,yBAAyB,EAC9B,KAAK,wBAAwB,EAC7B,KAAK,gBAAgB,EAErB,KAAK,eAAe,EAErB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,KAAK,UAAU,EAAiB,MAAM,oBAAoB,CAAC;AACpE,OAAO,EACL,KAAK,cAAc,EAInB,KAAK,UAAU,EAEhB,MAAM,iBAAiB,CAAC;AAEzB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,MAAM,MAAM,WAAW,CAAC,GAAG,IAAI;IAC7B,QAAQ,CAAC,KAAK,EAAE,cAAc,CAAC;IAC/B,QAAQ,CAAC,MAAM,EAAE,CACf,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,GAAG,KACL,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC9B,QAAQ,CAAC,eAAe,CAAC,EAAE,CACzB,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,OAAO,EACd,GAAG,EAAE,GAAG,KACL,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IACtD,QAAQ,CAAC,WAAW,CAAC,EAAE;QACrB,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAC;QACjC,QAAQ,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,GAAG,SAAS,CAAC;KACpD,CAAC;IACF;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,GAAG,CAAC,EAAE,UAAU,CAAC;CAC3B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,aAAa,CAC3B,SAAS,EAAE,cAAc,GACxB,yBAAyB,CAmB3B;AAuDD;;;;;;;;;;GAUG;AACH,KAAK,eAAe,CAAC,IAAI,IAAI,eAAe,CAC1C,gBAAgB,EAChB,IAAI,SAAS;IAAE,QAAQ,EAAE;QAAE,OAAO,EAAE,MAAM,QAAQ,CAAA;KAAE,CAAA;CAAE,GAClD;KAAG,CAAC,IAAI,MAAM,QAAQ,GAAG,wBAAwB;CAAE,GACnD,MAAM,CAAC,MAAM,EAAE,wBAAwB,CAAC,CAC7C,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAgB,IAAI,CAClB,GAAG,SAAS,MAAM,GAAG,MAAM,EAC3B,IAAI,SAAS,UAAU,GAAG,UAAU,EACpC,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,WAAW,CAAC,GAAG,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,CAsJ7D"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {
|
|
2
|
+
withIdempotency
|
|
3
|
+
} from "./chunk-ZQGGGU4E.js";
|
|
4
|
+
import {
|
|
5
|
+
track_in_flight
|
|
6
|
+
} from "./chunk-EERALS5E.js";
|
|
7
|
+
|
|
8
|
+
// src/api/dispatch.ts
|
|
9
|
+
function make_dispatch(app, resolvers, store) {
|
|
10
|
+
const tracker = store && track_in_flight(store);
|
|
11
|
+
return async (action_name, input, payload, ctx, actor, key) => {
|
|
12
|
+
const stream = await resolvers.stream(action_name, input, ctx);
|
|
13
|
+
const expected = await resolvers.expectedVersion?.(action_name, input, ctx);
|
|
14
|
+
const target = expected === void 0 ? { stream, actor } : { stream, actor, expectedVersion: expected };
|
|
15
|
+
const run = () => app.do(action_name, target, payload);
|
|
16
|
+
if (!tracker) return { kind: "done", result: await run() };
|
|
17
|
+
const k = key();
|
|
18
|
+
if (!k) return { kind: "missing-key" };
|
|
19
|
+
const outcome = await withIdempotency(tracker.store, k, run);
|
|
20
|
+
if (!outcome.deduped) return { kind: "done", result: outcome.result };
|
|
21
|
+
return { kind: tracker.in_flight(k) ? "in-flight" : "conflict" };
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export {
|
|
26
|
+
make_dispatch
|
|
27
|
+
};
|
|
28
|
+
//# sourceMappingURL=chunk-H545LMMV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/api/dispatch.ts"],"sourcesContent":["import type { Actor, Target } from \"@rotorsoft/act\";\nimport type { IdempotencyStore } from \"@rotorsoft/act-ops/idempotency\";\nimport { withIdempotency } from \"./idempotency.js\";\nimport { track_in_flight } from \"./in-flight.js\";\n\n/**\n * The Act surface the generated transports walk: the registry's action\n * name → owning-state map and `do(...)`. A structural bound lets `TApp`\n * infer to the caller's concrete `Act<...>` without leaking the variance of\n * its nested types, and without `any`.\n */\nexport type ActSurface = {\n readonly registry: {\n actions: Record<\n string,\n {\n readonly name: string;\n readonly actions: Record<string, unknown>;\n }\n >;\n };\n do(action: string, target: Target, payload: unknown): Promise<unknown>;\n};\n\n/** The target resolvers a generated transport takes, over its own context. */\ntype TargetResolvers<C> = {\n readonly stream: (\n action_name: string,\n input: unknown,\n ctx: C\n ) => string | Promise<string>;\n readonly expectedVersion?: (\n action_name: string,\n input: unknown,\n ctx: C\n ) => number | undefined | Promise<number | undefined>;\n};\n\n/** What one generated action call came to; each transport maps the refusals. */\nexport type Dispatched =\n | { kind: \"done\"; result: unknown }\n | { kind: \"missing-key\" }\n | { kind: \"in-flight\" }\n | { kind: \"conflict\" };\n\n/**\n * One generated action call: resolve the target from the validated input,\n * then run `app.do` on the raw payload (it parses again itself, and a second\n * parse of the parsed value would run every `.transform()` twice), under\n * `Idempotency-Key` dedup when a store is set. A duplicate of a key still\n * running is `in-flight`, since the original may yet fail and release it;\n * one already committed is `conflict`.\n */\nexport function make_dispatch<C>(\n app: ActSurface,\n resolvers: TargetResolvers<C>,\n store: IdempotencyStore | undefined\n) {\n // Counts claims per key, to tell the two kinds of duplicate apart.\n const tracker = store && track_in_flight(store);\n return async (\n action_name: string,\n input: unknown,\n payload: unknown,\n ctx: C,\n actor: Actor,\n key: () => string | undefined\n ): Promise<Dispatched> => {\n const stream = await resolvers.stream(action_name, input, ctx);\n const expected = await resolvers.expectedVersion?.(action_name, input, ctx);\n const target =\n expected === undefined\n ? { stream, actor }\n : { stream, actor, expectedVersion: expected };\n const run = () => app.do(action_name, target, payload);\n if (!tracker) return { kind: \"done\", result: await run() };\n const k = key();\n if (!k) return { kind: \"missing-key\" };\n const outcome = await withIdempotency(tracker.store, k, run);\n if (!outcome.deduped) return { kind: \"done\", result: outcome.result };\n return { kind: tracker.in_flight(k) ? \"in-flight\" : \"conflict\" };\n };\n}\n"],"mappings":";;;;;;;;AAqDO,SAAS,cACd,KACA,WACA,OACA;AAEA,QAAM,UAAU,SAAS,gBAAgB,KAAK;AAC9C,SAAO,OACL,aACA,OACA,SACA,KACA,OACA,QACwB;AACxB,UAAM,SAAS,MAAM,UAAU,OAAO,aAAa,OAAO,GAAG;AAC7D,UAAM,WAAW,MAAM,UAAU,kBAAkB,aAAa,OAAO,GAAG;AAC1E,UAAM,SACJ,aAAa,SACT,EAAE,QAAQ,MAAM,IAChB,EAAE,QAAQ,OAAO,iBAAiB,SAAS;AACjD,UAAM,MAAM,MAAM,IAAI,GAAG,aAAa,QAAQ,OAAO;AACrD,QAAI,CAAC,QAAS,QAAO,EAAE,MAAM,QAAQ,QAAQ,MAAM,IAAI,EAAE;AACzD,UAAM,IAAI,IAAI;AACd,QAAI,CAAC,EAAG,QAAO,EAAE,MAAM,cAAc;AACrC,UAAM,UAAU,MAAM,gBAAgB,QAAQ,OAAO,GAAG,GAAG;AAC3D,QAAI,CAAC,QAAQ,QAAS,QAAO,EAAE,MAAM,QAAQ,QAAQ,QAAQ,OAAO;AACpE,WAAO,EAAE,MAAM,QAAQ,UAAU,CAAC,IAAI,cAAc,WAAW;AAAA,EACjE;AACF;","names":[]}
|
package/dist/hono/index.cjs
CHANGED
|
@@ -54,6 +54,23 @@ var zValidator = zValidatorFunction;
|
|
|
54
54
|
var import_hono = require("hono");
|
|
55
55
|
var import_streaming = require("hono/streaming");
|
|
56
56
|
|
|
57
|
+
// src/api/idempotency.ts
|
|
58
|
+
async function withIdempotency(store, key, handler) {
|
|
59
|
+
const fresh = await store.claim(key);
|
|
60
|
+
if (!fresh) {
|
|
61
|
+
return { deduped: true };
|
|
62
|
+
}
|
|
63
|
+
let result;
|
|
64
|
+
try {
|
|
65
|
+
result = await handler();
|
|
66
|
+
} catch (err) {
|
|
67
|
+
await store.release(key);
|
|
68
|
+
throw err;
|
|
69
|
+
}
|
|
70
|
+
await store.commit(key);
|
|
71
|
+
return { deduped: false, result };
|
|
72
|
+
}
|
|
73
|
+
|
|
57
74
|
// src/api/in-flight.ts
|
|
58
75
|
function track_in_flight(store) {
|
|
59
76
|
let tracker = trackers.get(store);
|
|
@@ -114,6 +131,23 @@ function make_tracker(store) {
|
|
|
114
131
|
};
|
|
115
132
|
}
|
|
116
133
|
|
|
134
|
+
// src/api/dispatch.ts
|
|
135
|
+
function make_dispatch(app, resolvers, store) {
|
|
136
|
+
const tracker = store && track_in_flight(store);
|
|
137
|
+
return async (action_name, input2, payload, ctx, actor, key) => {
|
|
138
|
+
const stream = await resolvers.stream(action_name, input2, ctx);
|
|
139
|
+
const expected = await resolvers.expectedVersion?.(action_name, input2, ctx);
|
|
140
|
+
const target = expected === void 0 ? { stream, actor } : { stream, actor, expectedVersion: expected };
|
|
141
|
+
const run = () => app.do(action_name, target, payload);
|
|
142
|
+
if (!tracker) return { kind: "done", result: await run() };
|
|
143
|
+
const k = key();
|
|
144
|
+
if (!k) return { kind: "missing-key" };
|
|
145
|
+
const outcome = await withIdempotency(tracker.store, k, run);
|
|
146
|
+
if (!outcome.deduped) return { kind: "done", result: outcome.result };
|
|
147
|
+
return { kind: tracker.in_flight(k) ? "in-flight" : "conflict" };
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
|
|
117
151
|
// src/api/errors.ts
|
|
118
152
|
var import_act = require("@rotorsoft/act");
|
|
119
153
|
var ERROR_MAP = {
|
|
@@ -156,23 +190,6 @@ function toApiError(err) {
|
|
|
156
190
|
};
|
|
157
191
|
}
|
|
158
192
|
|
|
159
|
-
// src/api/idempotency.ts
|
|
160
|
-
async function withIdempotency(store, key, handler) {
|
|
161
|
-
const fresh = await store.claim(key);
|
|
162
|
-
if (!fresh) {
|
|
163
|
-
return { deduped: true };
|
|
164
|
-
}
|
|
165
|
-
let result;
|
|
166
|
-
try {
|
|
167
|
-
result = await handler();
|
|
168
|
-
} catch (err) {
|
|
169
|
-
await store.release(key);
|
|
170
|
-
throw err;
|
|
171
|
-
}
|
|
172
|
-
await store.commit(key);
|
|
173
|
-
return { deduped: false, result };
|
|
174
|
-
}
|
|
175
|
-
|
|
176
193
|
// ../../node_modules/.pnpm/zod@4.6.7/node_modules/zod/v4/classic/external.js
|
|
177
194
|
var external_exports = {};
|
|
178
195
|
__export(external_exports, {
|
|
@@ -20028,14 +20045,17 @@ function hono(app, options) {
|
|
|
20028
20045
|
);
|
|
20029
20046
|
api.use("*", authenticated(options.actor));
|
|
20030
20047
|
const key_from = options.idempotency?.keyFrom ?? default_key_from;
|
|
20031
|
-
const
|
|
20048
|
+
const dispatch = make_dispatch(
|
|
20049
|
+
app,
|
|
20050
|
+
options,
|
|
20051
|
+
options.idempotency?.store
|
|
20052
|
+
);
|
|
20032
20053
|
if (options.sse) {
|
|
20033
20054
|
const sse_config = resolveSseConfig(options.sse);
|
|
20034
20055
|
const sse_counter = new SseConnectionCounter(sse_config.maxConnections);
|
|
20035
|
-
const state_names =
|
|
20036
|
-
|
|
20037
|
-
|
|
20038
|
-
}
|
|
20056
|
+
const state_names = new Set(
|
|
20057
|
+
Object.values(app.registry.actions).map((a) => a.name)
|
|
20058
|
+
);
|
|
20039
20059
|
for (const state_name of state_names) {
|
|
20040
20060
|
api.get(`/sse/${state_name}`, async (c) => {
|
|
20041
20061
|
const stream_id = c.req.query("stream");
|
|
@@ -20120,50 +20140,38 @@ function hono(app, options) {
|
|
|
20120
20140
|
try {
|
|
20121
20141
|
const input2 = c.req.valid("json");
|
|
20122
20142
|
const raw = is_json(c.req.header("content-type")) ? await c.req.json() : {};
|
|
20123
|
-
const
|
|
20124
|
-
const stream = await options.stream(action_name, input2, c);
|
|
20125
|
-
const expected_version = options.expectedVersion ? await options.expectedVersion(action_name, input2, c) : void 0;
|
|
20126
|
-
const target = expected_version === void 0 ? { stream, actor } : { stream, actor, expectedVersion: expected_version };
|
|
20127
|
-
if (options.idempotency) {
|
|
20128
|
-
const key = key_from(c);
|
|
20129
|
-
if (!key) {
|
|
20130
|
-
const body = {
|
|
20131
|
-
error: "BadRequest",
|
|
20132
|
-
detail: "Idempotency-Key required",
|
|
20133
|
-
code: "BAD_REQUEST"
|
|
20134
|
-
};
|
|
20135
|
-
return c.json(body, 400);
|
|
20136
|
-
}
|
|
20137
|
-
const outcome = await withIdempotency(
|
|
20138
|
-
tracker.store,
|
|
20139
|
-
key,
|
|
20140
|
-
() => app.do(action_name, target, raw)
|
|
20141
|
-
);
|
|
20142
|
-
if (outcome.deduped && tracker.in_flight(key)) {
|
|
20143
|
-
const body = {
|
|
20144
|
-
error: "ServiceUnavailable",
|
|
20145
|
-
detail: "Idempotency-Key in flight; the original request has not finished, retry later",
|
|
20146
|
-
code: "IN_FLIGHT"
|
|
20147
|
-
};
|
|
20148
|
-
c.header("Retry-After", "1");
|
|
20149
|
-
return c.json(body, 503);
|
|
20150
|
-
}
|
|
20151
|
-
if (outcome.deduped) {
|
|
20152
|
-
const body = {
|
|
20153
|
-
error: "Conflict",
|
|
20154
|
-
detail: "Idempotency-Key already used; original result not cached",
|
|
20155
|
-
code: "CONFLICT"
|
|
20156
|
-
};
|
|
20157
|
-
return c.json(body, 409);
|
|
20158
|
-
}
|
|
20159
|
-
return c.json(outcome.result);
|
|
20160
|
-
}
|
|
20161
|
-
const snapshots = await app.do(
|
|
20143
|
+
const outcome = await dispatch(
|
|
20162
20144
|
action_name,
|
|
20163
|
-
|
|
20164
|
-
raw
|
|
20145
|
+
input2,
|
|
20146
|
+
raw,
|
|
20147
|
+
c,
|
|
20148
|
+
c.get("actor"),
|
|
20149
|
+
() => key_from(c)
|
|
20165
20150
|
);
|
|
20166
|
-
return c.json(
|
|
20151
|
+
if (outcome.kind === "done") return c.json(outcome.result);
|
|
20152
|
+
if (outcome.kind === "missing-key") {
|
|
20153
|
+
const body2 = {
|
|
20154
|
+
error: "BadRequest",
|
|
20155
|
+
detail: "Idempotency-Key required",
|
|
20156
|
+
code: "BAD_REQUEST"
|
|
20157
|
+
};
|
|
20158
|
+
return c.json(body2, 400);
|
|
20159
|
+
}
|
|
20160
|
+
if (outcome.kind === "in-flight") {
|
|
20161
|
+
const body2 = {
|
|
20162
|
+
error: "ServiceUnavailable",
|
|
20163
|
+
detail: "Idempotency-Key in flight; the original request has not finished, retry later",
|
|
20164
|
+
code: "IN_FLIGHT"
|
|
20165
|
+
};
|
|
20166
|
+
c.header("Retry-After", "1");
|
|
20167
|
+
return c.json(body2, 503);
|
|
20168
|
+
}
|
|
20169
|
+
const body = {
|
|
20170
|
+
error: "Conflict",
|
|
20171
|
+
detail: "Idempotency-Key already used; original result not cached",
|
|
20172
|
+
code: "CONFLICT"
|
|
20173
|
+
};
|
|
20174
|
+
return c.json(body, 409);
|
|
20167
20175
|
} catch (err) {
|
|
20168
20176
|
const { status, body } = toApiError(err);
|
|
20169
20177
|
return c.json(body, status);
|