@gjermundgaraba/effect-actions 0.1.0-rc.1 → 0.1.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.
Files changed (49) hide show
  1. package/README.md +50 -219
  2. package/dist/Action.d.mts +62 -2
  3. package/dist/Action.mjs +7 -4
  4. package/dist/ActionCatalog.d.mts +31 -0
  5. package/dist/ActionCatalog.mjs +36 -0
  6. package/dist/ActionCli.d.mts +27 -0
  7. package/dist/ActionCli.mjs +26 -0
  8. package/dist/ActionCliClient.d.mts +45 -0
  9. package/dist/ActionCliClient.mjs +52 -0
  10. package/dist/ActionGroup.d.mts +15 -14
  11. package/dist/ActionGroup.mjs +3 -2
  12. package/dist/ActionHttp.d.mts +21 -34
  13. package/dist/ActionHttp.mjs +44 -51
  14. package/dist/ActionMcp.d.mts +28 -7
  15. package/dist/ActionMcp.mjs +20 -128
  16. package/dist/ActionToolkit.d.mts +37 -0
  17. package/dist/ActionToolkit.mjs +10 -0
  18. package/dist/Authentication.d.mts +11 -12
  19. package/dist/Authentication.mjs +24 -57
  20. package/dist/Testing.d.mts +7 -4
  21. package/dist/Testing.mjs +4 -2
  22. package/dist/TestingClient.d.mts +6 -3
  23. package/dist/TestingClient.mjs +2 -2
  24. package/dist/_virtual/_rolldown/runtime.mjs +13 -0
  25. package/dist/internal/actions.d.mts +18 -0
  26. package/dist/internal/actions.mjs +16 -0
  27. package/dist/internal/cli.d.mts +29 -0
  28. package/dist/internal/cli.mjs +36 -0
  29. package/dist/internal/implementation.d.mts +39 -0
  30. package/dist/internal/implementation.mjs +37 -0
  31. package/dist/internal/tools.mjs +84 -0
  32. package/docs/Action.md +117 -0
  33. package/docs/ActionCatalog.md +56 -0
  34. package/docs/ActionCli.md +91 -0
  35. package/docs/ActionCliClient.md +77 -0
  36. package/docs/ActionGroup.md +141 -0
  37. package/docs/ActionHttp.md +106 -0
  38. package/docs/ActionMcp.md +131 -0
  39. package/docs/ActionToolkit.md +73 -0
  40. package/docs/Authentication.md +114 -0
  41. package/docs/CONTEXT.md +36 -0
  42. package/docs/README.md +85 -0
  43. package/docs/Testing.md +91 -0
  44. package/docs/guarantees.md +55 -0
  45. package/docs/setup.md +63 -0
  46. package/package.json +19 -14
  47. package/dist/Action-CXsfTEhx.d.mts +0 -54
  48. package/dist/implementation-4Q2BESw5.mjs +0 -61
  49. package/dist/implementation-DTqp_0DW.d.mts +0 -61
@@ -1,54 +0,0 @@
1
- import { Effect, Schema } from "effect";
2
- declare namespace Action_d_exports {
3
- export { Action, Any, Codec, Handler, McpOptions, Options, SchemaErrorPolicy, SchemaFailure, make };
4
- }
5
- type Codec = Schema.Codec<unknown, unknown, never, never>;
6
- /** Failed request decoding or successful-result encoding, independent of transport terminology. */
7
- interface SchemaFailure {
8
- readonly phase: "input" | "output";
9
- /** May contain sensitive values. Do not reflect it in public error messages. */
10
- readonly cause: Schema.SchemaError;
11
- }
12
- /** Pure application-owned mapping, set on a group and applied by both adapters. */
13
- interface SchemaErrorPolicy<Errors extends ReadonlyArray<Codec>> {
14
- readonly errors: Errors;
15
- readonly map: (failure: SchemaFailure) => NoInfer<Errors[number]["Type"]>;
16
- }
17
- interface McpOptions {
18
- readonly name?: string;
19
- readonly readOnly?: boolean;
20
- /** Defaults to `!readOnly`; the MCP spec only defines it for non-read-only tools. */
21
- readonly destructive?: boolean;
22
- }
23
- interface Options<Input extends Codec, Output extends Codec, Errors extends ReadonlyArray<Codec>, Http extends boolean = boolean> {
24
- readonly description: string;
25
- /** Omit for an action without arguments. */
26
- readonly input?: Input;
27
- readonly success: Output;
28
- /** One schema per declared failure; each keeps its own HTTP status annotation. Defaults to none. */
29
- readonly errors?: Errors;
30
- readonly http?: Http;
31
- readonly mcp?: false | McpOptions;
32
- }
33
- /** A pure contract: schemas and transport metadata. Implementations are bound by `ActionGroup.implement`. */
34
- interface Action<Name extends string, Input extends Codec, Output extends Codec, Errors extends ReadonlyArray<Codec>, Http extends boolean = boolean> {
35
- readonly name: Name;
36
- readonly description: string;
37
- readonly input: Input;
38
- readonly success: Output;
39
- readonly errors: Errors;
40
- readonly http: Http;
41
- readonly mcp: false | {
42
- readonly name: string;
43
- readonly readOnly: boolean;
44
- readonly destructive: boolean;
45
- };
46
- }
47
- type Any = Action<string, Codec, Codec, ReadonlyArray<Codec>>;
48
- /** Receives decoded input; may fail only with the declared errors. */
49
- type Handler<A extends Any, R = never> = (input: A["input"]["Type"]) => Effect.Effect<A["success"]["Type"], A["errors"][number]["Type"], R>;
50
- /** An empty object schema that also produces the object root MCP requires. */
51
- declare const NoInput: Schema.$Record<Schema.String, Schema.Never>;
52
- declare function make<const Name extends string, Input extends Codec = typeof NoInput, Output extends Codec = never, const Errors extends ReadonlyArray<Codec> = [], const Http extends boolean = true>(name: Name, options: Options<Input, Output, Errors, Http>): Action<Name, Input, Output, Errors, Http>;
53
- //#endregion
54
- export { Handler as a, SchemaErrorPolicy as c, __exportAll as d, Codec as i, SchemaFailure as l, Action_d_exports as n, McpOptions as o, Any as r, Options as s, Action as t, make as u };
@@ -1,61 +0,0 @@
1
- import { Context, Effect, Layer } from "effect";
2
- //#region src/internal/actions.ts
3
- /** Each namespace is checked by whoever owns it: a group, the routes, or the MCP tools. */
4
- const assertDistinct = (what, names) => {
5
- const seen = /* @__PURE__ */ new Set();
6
- for (const name of names) {
7
- if (seen.has(name)) throw new Error(`Duplicate ${what}: ${name}`);
8
- seen.add(name);
9
- }
10
- };
11
- const served = (groups, serves) => groups.flatMap((group) => {
12
- const actions = group.actions.filter(serves);
13
- return actions.length === 0 ? [] : [{
14
- group,
15
- actions
16
- }];
17
- });
18
- //#endregion
19
- //#region src/internal/implementation.ts
20
- let implementations = 0;
21
- /**
22
- * Opaque implementation value; only its type is public. `R` is required per
23
- * request, `EX`/`RX` describe handler acquisition at Layer build. Layer
24
- * memoization lets both adapters share one handler build per runtime.
25
- */
26
- var Implementation = class Implementation {
27
- group;
28
- #handlers;
29
- #layer;
30
- constructor(group, handlers, layer) {
31
- this.group = group;
32
- this.#handlers = handlers;
33
- this.#layer = layer;
34
- }
35
- static make(group, build) {
36
- const handlers = Context.Service(`effect-actions/Handlers#${++implementations}`);
37
- return new Implementation(group, handlers, Layer.effect(handlers, build));
38
- }
39
- /**
40
- * Acquire exactly the implementations an adapter serves. Each resolves its
41
- * own handlers, so records are never merged across implementations.
42
- */
43
- static register(serving, make) {
44
- const [first, ...rest] = serving;
45
- if (first === void 0) return make([]);
46
- const bound = Effect.all(serving.map(({ app, actions }) => Effect.map(app.#handlers, (handlers) => ({
47
- group: app.group,
48
- actions,
49
- handle: (action) => {
50
- const handle = handlers[action.name];
51
- if (handle === void 0) throw new Error(`Missing handler: ${action.name}`);
52
- const dispatch = handle;
53
- const name = `${app.group.name}.${action.name}`;
54
- return (input) => Effect.withSpan(Effect.suspend(() => dispatch(input)), name, { captureStackTrace: false });
55
- }
56
- }))));
57
- return Layer.unwrap(Effect.map(bound, make)).pipe(Layer.provide(Layer.mergeAll(first.app.#layer, ...rest.map(({ app }) => app.#layer))));
58
- }
59
- };
60
- //#endregion
61
- export { assertDistinct as n, served as r, Implementation as t };
@@ -1,61 +0,0 @@
1
- import { c as SchemaErrorPolicy, i as Codec, n as Action_d_exports, r as Any } from "./Action-CXsfTEhx.mjs";
2
- import { Effect, Layer, Scope } from "effect";
3
- //#region src/internal/actions.d.ts
4
- /** The contract half of a group: what adapters and clients need, without `implement`. */
5
- interface Actions<Name extends string = string, A extends ReadonlyArray<Any> = ReadonlyArray<Any>, PolicyErrors extends ReadonlyArray<Codec> = ReadonlyArray<Codec>> {
6
- readonly name: Name;
7
- readonly actions: A;
8
- /** How both transports answer failed decoding or encoding; their native behavior without one. */
9
- readonly schemaError: SchemaErrorPolicy<PolicyErrors> | undefined;
10
- }
11
- /** The errors a group's policy may answer with, by lookup rather than a conditional type. */
12
- type PolicyError<G extends Actions> = NonNullable<G["schemaError"]>["errors"][number];
13
- /**
14
- * What one adapter serves of a group. Each adapter projects its groups once and
15
- * reads nothing else, so an action it does not serve cannot influence its
16
- * names, routes, clients, pairing or acquisition.
17
- */
18
- interface Served {
19
- readonly group: Actions;
20
- readonly actions: ReadonlyArray<Any>;
21
- }
22
- //#endregion
23
- //#region src/internal/implementation.d.ts
24
- /** Decoded action values after schema parsing, erased across actions at the adapter boundary. */
25
- type ErasedValue = Any["input"]["Type"];
26
- type Erased<R> = {
27
- handle(input: ErasedValue): Effect.Effect<ErasedValue, ErasedValue, R>;
28
- }["handle"];
29
- type Handlers<R> = Readonly<Record<string, Erased<R>>>;
30
- type Dispatch = (input: ErasedValue) => Effect.Effect<ErasedValue, ErasedValue>;
31
- /** One acquired implementation and the actions its adapter serves. */
32
- interface Bound extends Served {
33
- readonly handle: (action: Any) => Dispatch;
34
- }
35
- /**
36
- * Opaque implementation value; only its type is public. `R` is required per
37
- * request, `EX`/`RX` describe handler acquisition at Layer build. Layer
38
- * memoization lets both adapters share one handler build per runtime.
39
- */
40
- declare class Implementation<G extends Actions, R, EX, RX> {
41
- #private;
42
- /** Adapters pair an implementation with its contract by this identity. */
43
- readonly group: G;
44
- private constructor();
45
- static make<G extends Actions, R, EX, RX>(group: G, build: Effect.Effect<Handlers<R>, EX, RX>): Implementation<G, R, EX, Exclude<RX, Scope.Scope>>;
46
- /**
47
- * Acquire exactly the implementations an adapter serves. Each resolves its
48
- * own handlers, so records are never merged across implementations.
49
- */
50
- static register<R, EX, RX, Out, E, In>(serving: ReadonlyArray<{
51
- readonly app: Implementation<Actions, R, EX, RX>;
52
- readonly actions: ReadonlyArray<Any>;
53
- }>, make: (apps: ReadonlyArray<Bound>) => Layer.Layer<Out, E, In>): Layer.Layer<Out, E | EX, In | RX>;
54
- }
55
- type AnyImplementation<G extends Actions = Actions> = Implementation<G, any, any, any>;
56
- /** Per-request requirements of one implementation, or of a union of them. */
57
- type RequestContext<App> = App extends Implementation<any, infer R, any, any> ? R : never;
58
- type BuildError<App> = App extends Implementation<any, any, infer EX, any> ? EX : never;
59
- type BuildContext<App> = App extends Implementation<any, any, any, infer RX> ? RX : never;
60
- //#endregion
61
- export { RequestContext as a, Implementation as i, BuildContext as n, Actions as o, BuildError as r, PolicyError as s, AnyImplementation as t };