@knpkv/herdr-hub 0.21.0 → 0.22.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/README.md +15 -1
- package/dist/activity-history.d.ts +3 -1
- package/dist/activity-history.d.ts.map +1 -1
- package/dist/activity-history.js +14 -23
- package/dist/activity-history.js.map +1 -1
- package/dist/approval-client.js +29 -4
- package/dist/approval-client.js.map +1 -1
- package/dist/approval.js +46 -46
- package/dist/approval.js.map +4 -4
- package/dist/http.d.ts +4 -1
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +130 -33
- package/dist/http.js.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.css.map +3 -3
- package/dist/module-contract.d.ts +13 -2
- package/dist/module-contract.d.ts.map +1 -1
- package/dist/module-contract.js +9 -1
- package/dist/module-contract.js.map +1 -1
- package/dist/module-needs-you-server.d.ts +59 -0
- package/dist/module-needs-you-server.d.ts.map +1 -0
- package/dist/module-needs-you-server.js +96 -0
- package/dist/module-needs-you-server.js.map +1 -0
- package/dist/module-needs-you.d.ts +146 -0
- package/dist/module-needs-you.d.ts.map +1 -0
- package/dist/module-needs-you.js +63 -0
- package/dist/module-needs-you.js.map +1 -0
- package/dist/module-server.d.ts +12 -9
- package/dist/module-server.d.ts.map +1 -1
- package/dist/module-server.js +29 -8
- package/dist/module-server.js.map +1 -1
- package/dist/modules.d.ts +1 -0
- package/dist/modules.d.ts.map +1 -1
- package/dist/modules.js +1 -0
- package/dist/modules.js.map +1 -1
- package/dist/superapp-view.d.ts.map +1 -1
- package/dist/superapp-view.js +1 -1
- package/dist/superapp-view.js.map +1 -1
- package/dist/today-fleet-activity.d.ts +11 -0
- package/dist/today-fleet-activity.d.ts.map +1 -0
- package/dist/today-fleet-activity.js +18 -0
- package/dist/today-fleet-activity.js.map +1 -0
- package/dist/today-module-view.d.ts +18 -0
- package/dist/today-module-view.d.ts.map +1 -0
- package/dist/today-module-view.js +45 -0
- package/dist/today-module-view.js.map +1 -0
- package/dist/today-view.d.ts +19 -0
- package/dist/today-view.d.ts.map +1 -0
- package/dist/today-view.js +80 -0
- package/dist/today-view.js.map +1 -0
- package/dist/views.d.ts +1 -0
- package/dist/views.d.ts.map +1 -1
- package/dist/views.js +1 -0
- package/dist/views.js.map +1 -1
- package/package.json +5 -5
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Result, Schema } from "effect";
|
|
2
|
-
export declare const ModuleListener: Schema.Literals<readonly ["serve", "approval", "tailnet", "lan"
|
|
2
|
+
export declare const ModuleListener: Schema.Literals<readonly ["serve", "approval", "tailnet", "lan"]>;
|
|
3
3
|
export type ModuleListener = typeof ModuleListener.Type;
|
|
4
4
|
/** Shared metadata. `requires` describes UI capabilities; the server mount enforces access. */
|
|
5
5
|
export declare const ModuleDescriptor: Schema.Struct<{
|
|
@@ -10,7 +10,7 @@ export declare const ModuleDescriptor: Schema.Struct<{
|
|
|
10
10
|
readonly id: Schema.String;
|
|
11
11
|
readonly label: Schema.String;
|
|
12
12
|
}>>;
|
|
13
|
-
readonly listeners: Schema.$Array<Schema.Literals<readonly ["serve", "approval", "tailnet", "lan"
|
|
13
|
+
readonly listeners: Schema.$Array<Schema.Literals<readonly ["serve", "approval", "tailnet", "lan"]>>;
|
|
14
14
|
readonly requires: Schema.$Array<Schema.Literals<readonly ["read", "write"]>>;
|
|
15
15
|
}>;
|
|
16
16
|
export type ModuleDescriptor = typeof ModuleDescriptor.Type;
|
|
@@ -52,5 +52,16 @@ export declare const fleetModule: {
|
|
|
52
52
|
readonly requires: readonly ["read", "write"];
|
|
53
53
|
};
|
|
54
54
|
export type FleetModuleDestination = ModuleDestination<typeof fleetModule>;
|
|
55
|
+
export declare const todayModule: {
|
|
56
|
+
readonly id: "today";
|
|
57
|
+
readonly label: "Today";
|
|
58
|
+
readonly defaultPage: "overview";
|
|
59
|
+
readonly pages: readonly [{
|
|
60
|
+
readonly id: "overview";
|
|
61
|
+
readonly label: "Today";
|
|
62
|
+
}];
|
|
63
|
+
readonly listeners: readonly ["serve"];
|
|
64
|
+
readonly requires: readonly ["read"];
|
|
65
|
+
};
|
|
55
66
|
export {};
|
|
56
67
|
//# sourceMappingURL=module-contract.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-contract.d.ts","sourceRoot":"","sources":["../src/module-contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAKvC,eAAO,MAAM,cAAc,
|
|
1
|
+
{"version":3,"file":"module-contract.d.ts","sourceRoot":"","sources":["../src/module-contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAKvC,eAAO,MAAM,cAAc,mEAA2D,CAAA;AACtF,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAA;AAEvD,+FAA+F;AAC/F,eAAO,MAAM,gBAAgB;;;;;;;;;;EAO3B,CAAA;AACF,MAAM,MAAM,gBAAgB,GAAG,OAAO,gBAAgB,CAAC,IAAI,CAAA;;;;;AAE3D,qBAAa,uBAAwB,SAAQ,4BAY3C;CAAG;AAEL,iGAAiG;AACjG,eAAO,MAAM,sBAAsB,UAC1B,aAAa,CAAC,gBAAgB,CAAC,KACrC,MAAM,CAAC,MAAM,CAAC,aAAa,CAAC,gBAAgB,CAAC,EAAE,uBAAuB,CAuBxE,CAAA;AAED,gGAAgG;AAChG,eAAO,MAAM,YAAY,GAAI,KAAK,CAAC,CAAC,SAAS,gBAAgB,cAAc,CAAC,KAAG,CAAe,CAAA;AAE9F,mGAAmG;AACnG,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,gBAAgB,GAAG,gBAAgB,IAAI,CAAC,SAAS,gBAAgB,GACrG;IAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAA;CAAE,GACrE,KAAK,CAAA;AAET,iGAAiG;AACjG,eAAO,MAAM,yBAAyB,gBAAiB,aAAa,CAAC,gBAAgB,CAAC,KAAG,MAUtF,CAAA;AAEH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;CAYtB,CAAA;AAEF,MAAM,MAAM,sBAAsB,GAAG,iBAAiB,CAAC,OAAO,WAAW,CAAC,CAAA;AAE1E,eAAO,MAAM,WAAW;;;;;;;;;;CAOtB,CAAA"}
|
package/dist/module-contract.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Result, Schema } from "effect";
|
|
2
2
|
const Segment = Schema.String.check(Schema.isPattern(/^[a-z][a-z0-9-]*$/));
|
|
3
3
|
const Label = Schema.String.check(Schema.isMinLength(1));
|
|
4
|
-
export const ModuleListener = Schema.Literals(["serve", "approval", "tailnet", "lan"
|
|
4
|
+
export const ModuleListener = Schema.Literals(["serve", "approval", "tailnet", "lan"]);
|
|
5
5
|
/** Shared metadata. `requires` describes UI capabilities; the server mount enforces access. */
|
|
6
6
|
export const ModuleDescriptor = Schema.Struct({
|
|
7
7
|
id: Segment,
|
|
@@ -74,4 +74,12 @@ export const fleetModule = defineModule({
|
|
|
74
74
|
listeners: ["serve"],
|
|
75
75
|
requires: ["read", "write"]
|
|
76
76
|
});
|
|
77
|
+
export const todayModule = defineModule({
|
|
78
|
+
id: "today",
|
|
79
|
+
label: "Today",
|
|
80
|
+
defaultPage: "overview",
|
|
81
|
+
pages: [{ id: "overview", label: "Today" }],
|
|
82
|
+
listeners: ["serve"],
|
|
83
|
+
requires: ["read"]
|
|
84
|
+
});
|
|
77
85
|
//# sourceMappingURL=module-contract.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-contract.js","sourceRoot":"","sources":["../src/module-contract.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAEvC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC,CAAA;AAC1E,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAA;AAExD,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,KAAK,
|
|
1
|
+
{"version":3,"file":"module-contract.js","sourceRoot":"","sources":["../src/module-contract.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Effect } from "effect";
|
|
2
|
+
import { NeedsYouProviderResult } from "./module-needs-you.js";
|
|
3
|
+
export interface NeedsYouProvider {
|
|
4
|
+
readonly id: string;
|
|
5
|
+
readonly read: Effect.Effect<NeedsYouProviderResult>;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Providers close their service requirements at startup. Keep the whole earliest-created row
|
|
9
|
+
* for duplicate opaque keys; sort expiry ascending, null last, then creation time and key.
|
|
10
|
+
*/
|
|
11
|
+
export declare const collectNeedsYou: (providers: readonly NeedsYouProvider[]) => Effect.Effect<{
|
|
12
|
+
readonly _tag: "Complete";
|
|
13
|
+
readonly items: readonly {
|
|
14
|
+
readonly key: string;
|
|
15
|
+
readonly provider: string;
|
|
16
|
+
readonly destination: {
|
|
17
|
+
readonly _tag: "FleetApproval";
|
|
18
|
+
readonly module: "fleet";
|
|
19
|
+
readonly host: string;
|
|
20
|
+
readonly jobId: string;
|
|
21
|
+
};
|
|
22
|
+
readonly kind: "agent.delegate" | "agent.message" | "browser.mcp.recover" | "nix.apply" | "nix.check" | "work.abandon" | "work.admit" | "work.reassign" | "work.reconcile" | "work.recover";
|
|
23
|
+
readonly actor: string;
|
|
24
|
+
readonly createdAt: number;
|
|
25
|
+
readonly expiresAt: number | null;
|
|
26
|
+
}[];
|
|
27
|
+
} | {
|
|
28
|
+
readonly _tag: "Partial";
|
|
29
|
+
readonly items: readonly {
|
|
30
|
+
readonly key: string;
|
|
31
|
+
readonly provider: string;
|
|
32
|
+
readonly destination: {
|
|
33
|
+
readonly _tag: "FleetApproval";
|
|
34
|
+
readonly module: "fleet";
|
|
35
|
+
readonly host: string;
|
|
36
|
+
readonly jobId: string;
|
|
37
|
+
};
|
|
38
|
+
readonly kind: "agent.delegate" | "agent.message" | "browser.mcp.recover" | "nix.apply" | "nix.check" | "work.abandon" | "work.admit" | "work.reassign" | "work.reconcile" | "work.recover";
|
|
39
|
+
readonly actor: string;
|
|
40
|
+
readonly createdAt: number;
|
|
41
|
+
readonly expiresAt: number | null;
|
|
42
|
+
}[];
|
|
43
|
+
readonly sources: readonly {
|
|
44
|
+
readonly provider: string;
|
|
45
|
+
readonly issue: {
|
|
46
|
+
readonly state: "truncated";
|
|
47
|
+
} | {
|
|
48
|
+
readonly state: "failed";
|
|
49
|
+
readonly reason: "internal" | "invalid_response" | "offline" | "request_failed" | "timeout" | "unavailable";
|
|
50
|
+
} | {
|
|
51
|
+
readonly state: "hosts";
|
|
52
|
+
readonly hosts: readonly {
|
|
53
|
+
readonly host: string;
|
|
54
|
+
readonly reason: "internal" | "invalid_response" | "offline" | "request_failed" | "timeout" | "unavailable";
|
|
55
|
+
}[];
|
|
56
|
+
};
|
|
57
|
+
}[];
|
|
58
|
+
}, never, never>;
|
|
59
|
+
//# sourceMappingURL=module-needs-you-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module-needs-you-server.d.ts","sourceRoot":"","sources":["../src/module-needs-you-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAgC,MAAM,QAAQ,CAAA;AACpE,OAAO,EAEL,sBAAsB,EAGvB,MAAM,uBAAuB,CAAA;AAE9B,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;IACnB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAA;CACrD;AAED;;;GAGG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;gBA6F1B,CAAA"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import { Cause, Effect, Exit, Option, Result, Schema } from "effect";
|
|
2
|
+
import { NeedsYouProviderResult } from "./module-needs-you.js";
|
|
3
|
+
/**
|
|
4
|
+
* Providers close their service requirements at startup. Keep the whole earliest-created row
|
|
5
|
+
* for duplicate opaque keys; sort expiry ascending, null last, then creation time and key.
|
|
6
|
+
*/
|
|
7
|
+
export const collectNeedsYou = Effect.fn("ModuleRegistry.collectNeedsYou")(function* (providers) {
|
|
8
|
+
const readings = yield* Effect.forEach(providers, Effect.fnUntraced(function* (provider) {
|
|
9
|
+
const result = yield* Effect.exit(provider.read.pipe(Effect.timeoutOption("4 seconds")));
|
|
10
|
+
if (Exit.isFailure(result)) {
|
|
11
|
+
if (Cause.hasInterrupts(result.cause))
|
|
12
|
+
return yield* Effect.failCause(result.cause);
|
|
13
|
+
yield* Effect.logError("Needs-you provider failed", result.cause).pipe(Effect.annotateLogs("module", provider.id));
|
|
14
|
+
return {
|
|
15
|
+
items: [],
|
|
16
|
+
sources: [{
|
|
17
|
+
provider: provider.id,
|
|
18
|
+
issue: {
|
|
19
|
+
state: "failed",
|
|
20
|
+
reason: "internal"
|
|
21
|
+
}
|
|
22
|
+
}]
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
if (Option.isNone(result.value)) {
|
|
26
|
+
return {
|
|
27
|
+
items: [],
|
|
28
|
+
sources: [{
|
|
29
|
+
provider: provider.id,
|
|
30
|
+
issue: {
|
|
31
|
+
state: "failed",
|
|
32
|
+
reason: "timeout"
|
|
33
|
+
}
|
|
34
|
+
}]
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const decoded = Schema.decodeUnknownResult(NeedsYouProviderResult, { onExcessProperty: "error" })(result.value.value);
|
|
38
|
+
if (Result.isFailure(decoded) || decoded.success.items.some((item) => item.destination.module !== provider.id)) {
|
|
39
|
+
return {
|
|
40
|
+
items: [],
|
|
41
|
+
sources: [{
|
|
42
|
+
provider: provider.id,
|
|
43
|
+
issue: {
|
|
44
|
+
state: "failed",
|
|
45
|
+
reason: "invalid_response"
|
|
46
|
+
}
|
|
47
|
+
}]
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
items: decoded.success.items.map(({ sourceKey, ...item }) => ({
|
|
52
|
+
...item,
|
|
53
|
+
provider: provider.id,
|
|
54
|
+
key: `${provider.id}:${sourceKey}`
|
|
55
|
+
})),
|
|
56
|
+
sources: decoded.success.issues.map((issue) => ({ provider: provider.id, issue }))
|
|
57
|
+
};
|
|
58
|
+
}), { concurrency: 4 });
|
|
59
|
+
const unique = new Map();
|
|
60
|
+
for (const item of readings.flatMap((reading) => reading.items)) {
|
|
61
|
+
const previous = unique.get(item.key);
|
|
62
|
+
if (previous === undefined || item.createdAt < previous.createdAt)
|
|
63
|
+
unique.set(item.key, item);
|
|
64
|
+
}
|
|
65
|
+
const items = [...unique.values()].sort((a, b) => {
|
|
66
|
+
if (a.expiresAt !== b.expiresAt) {
|
|
67
|
+
if (a.expiresAt === null)
|
|
68
|
+
return 1;
|
|
69
|
+
if (b.expiresAt === null)
|
|
70
|
+
return -1;
|
|
71
|
+
return a.expiresAt - b.expiresAt;
|
|
72
|
+
}
|
|
73
|
+
return a.createdAt - b.createdAt || (a.key < b.key ? -1 : a.key > b.key ? 1 : 0);
|
|
74
|
+
});
|
|
75
|
+
const sources = readings.flatMap((reading) => reading.sources);
|
|
76
|
+
const counts = new Map();
|
|
77
|
+
const truncated = new Set();
|
|
78
|
+
const bounded = [];
|
|
79
|
+
for (const item of items) {
|
|
80
|
+
const count = counts.get(item.provider) ?? 0;
|
|
81
|
+
if (count < 256) {
|
|
82
|
+
bounded.push(item);
|
|
83
|
+
counts.set(item.provider, count + 1);
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
truncated.add(item.provider);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
for (const provider of truncated) {
|
|
90
|
+
if (!sources.some((source) => source.provider === provider && source.issue.state === "truncated")) {
|
|
91
|
+
sources.push({ provider, issue: { state: "truncated" } });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return sources.length === 0 ? { _tag: "Complete", items: bounded } : { _tag: "Partial", items: bounded, sources };
|
|
95
|
+
});
|
|
96
|
+
//# sourceMappingURL=module-needs-you-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module-needs-you-server.js","sourceRoot":"","sources":["../src/module-needs-you-server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
/** Exact object selectors, without an approval proof, action payload or URL. */
|
|
3
|
+
export declare const NeedsYouDestination: Schema.TaggedStruct<"FleetApproval", {
|
|
4
|
+
readonly module: Schema.Literal<"fleet">;
|
|
5
|
+
readonly host: Schema.String;
|
|
6
|
+
readonly jobId: Schema.String;
|
|
7
|
+
}>;
|
|
8
|
+
export interface NeedsYouDestination extends Schema.Schema.Type<typeof NeedsYouDestination> {
|
|
9
|
+
}
|
|
10
|
+
/** Providers supply local keys; the hub owns their module namespace. */
|
|
11
|
+
export declare const NeedsYouCandidate: Schema.Struct<{
|
|
12
|
+
readonly sourceKey: Schema.String;
|
|
13
|
+
readonly destination: Schema.TaggedStruct<"FleetApproval", {
|
|
14
|
+
readonly module: Schema.Literal<"fleet">;
|
|
15
|
+
readonly host: Schema.String;
|
|
16
|
+
readonly jobId: Schema.String;
|
|
17
|
+
}>;
|
|
18
|
+
readonly kind: Schema.Literals<readonly ["nix.check", "nix.apply", "agent.delegate", "agent.message", "work.reconcile", "work.admit", "work.recover", "work.reassign", "work.abandon", "browser.mcp.recover"]>;
|
|
19
|
+
readonly actor: Schema.String;
|
|
20
|
+
readonly createdAt: Schema.Number;
|
|
21
|
+
readonly expiresAt: Schema.NullOr<Schema.Number>;
|
|
22
|
+
}>;
|
|
23
|
+
export interface NeedsYouCandidate extends Schema.Schema.Type<typeof NeedsYouCandidate> {
|
|
24
|
+
}
|
|
25
|
+
export declare const NeedsYouFailureReason: Schema.Literals<readonly ["offline", "unavailable", "timeout", "request_failed", "invalid_response", "internal"]>;
|
|
26
|
+
export declare const NeedsYouIssue: Schema.Union<readonly [Schema.Struct<{
|
|
27
|
+
readonly state: Schema.Literal<"truncated">;
|
|
28
|
+
}>, Schema.Struct<{
|
|
29
|
+
readonly state: Schema.Literal<"failed">;
|
|
30
|
+
readonly reason: Schema.Literals<readonly ["offline", "unavailable", "timeout", "request_failed", "invalid_response", "internal"]>;
|
|
31
|
+
}>, Schema.Struct<{
|
|
32
|
+
readonly state: Schema.Literal<"hosts">;
|
|
33
|
+
readonly hosts: Schema.$Array<Schema.Struct<{
|
|
34
|
+
readonly host: Schema.String;
|
|
35
|
+
readonly reason: Schema.Literals<readonly ["offline", "unavailable", "timeout", "request_failed", "invalid_response", "internal"]>;
|
|
36
|
+
}>>;
|
|
37
|
+
}>]>;
|
|
38
|
+
export type NeedsYouIssue = typeof NeedsYouIssue.Type;
|
|
39
|
+
/** A failed or bounded source remains visible even when it returned no items. */
|
|
40
|
+
export declare const NeedsYouProviderResult: Schema.Struct<{
|
|
41
|
+
readonly items: Schema.$Array<Schema.Struct<{
|
|
42
|
+
readonly sourceKey: Schema.String;
|
|
43
|
+
readonly destination: Schema.TaggedStruct<"FleetApproval", {
|
|
44
|
+
readonly module: Schema.Literal<"fleet">;
|
|
45
|
+
readonly host: Schema.String;
|
|
46
|
+
readonly jobId: Schema.String;
|
|
47
|
+
}>;
|
|
48
|
+
readonly kind: Schema.Literals<readonly ["nix.check", "nix.apply", "agent.delegate", "agent.message", "work.reconcile", "work.admit", "work.recover", "work.reassign", "work.abandon", "browser.mcp.recover"]>;
|
|
49
|
+
readonly actor: Schema.String;
|
|
50
|
+
readonly createdAt: Schema.Number;
|
|
51
|
+
readonly expiresAt: Schema.NullOr<Schema.Number>;
|
|
52
|
+
}>>;
|
|
53
|
+
readonly issues: Schema.$Array<Schema.Union<readonly [Schema.Struct<{
|
|
54
|
+
readonly state: Schema.Literal<"truncated">;
|
|
55
|
+
}>, Schema.Struct<{
|
|
56
|
+
readonly state: Schema.Literal<"failed">;
|
|
57
|
+
readonly reason: Schema.Literals<readonly ["offline", "unavailable", "timeout", "request_failed", "invalid_response", "internal"]>;
|
|
58
|
+
}>, Schema.Struct<{
|
|
59
|
+
readonly state: Schema.Literal<"hosts">;
|
|
60
|
+
readonly hosts: Schema.$Array<Schema.Struct<{
|
|
61
|
+
readonly host: Schema.String;
|
|
62
|
+
readonly reason: Schema.Literals<readonly ["offline", "unavailable", "timeout", "request_failed", "invalid_response", "internal"]>;
|
|
63
|
+
}>>;
|
|
64
|
+
}>]>>;
|
|
65
|
+
}>;
|
|
66
|
+
export interface NeedsYouProviderResult extends Schema.Schema.Type<typeof NeedsYouProviderResult> {
|
|
67
|
+
}
|
|
68
|
+
export declare const NeedsYouItem: Schema.Struct<{
|
|
69
|
+
readonly key: Schema.String;
|
|
70
|
+
readonly provider: Schema.String;
|
|
71
|
+
readonly destination: Schema.TaggedStruct<"FleetApproval", {
|
|
72
|
+
readonly module: Schema.Literal<"fleet">;
|
|
73
|
+
readonly host: Schema.String;
|
|
74
|
+
readonly jobId: Schema.String;
|
|
75
|
+
}>;
|
|
76
|
+
readonly kind: Schema.Literals<readonly ["nix.check", "nix.apply", "agent.delegate", "agent.message", "work.reconcile", "work.admit", "work.recover", "work.reassign", "work.abandon", "browser.mcp.recover"]>;
|
|
77
|
+
readonly actor: Schema.String;
|
|
78
|
+
readonly createdAt: Schema.Number;
|
|
79
|
+
readonly expiresAt: Schema.NullOr<Schema.Number>;
|
|
80
|
+
}>;
|
|
81
|
+
export interface NeedsYouItem extends Schema.Schema.Type<typeof NeedsYouItem> {
|
|
82
|
+
}
|
|
83
|
+
export declare const NeedsYouSource: Schema.Struct<{
|
|
84
|
+
readonly provider: Schema.String;
|
|
85
|
+
readonly issue: Schema.Union<readonly [Schema.Struct<{
|
|
86
|
+
readonly state: Schema.Literal<"truncated">;
|
|
87
|
+
}>, Schema.Struct<{
|
|
88
|
+
readonly state: Schema.Literal<"failed">;
|
|
89
|
+
readonly reason: Schema.Literals<readonly ["offline", "unavailable", "timeout", "request_failed", "invalid_response", "internal"]>;
|
|
90
|
+
}>, Schema.Struct<{
|
|
91
|
+
readonly state: Schema.Literal<"hosts">;
|
|
92
|
+
readonly hosts: Schema.$Array<Schema.Struct<{
|
|
93
|
+
readonly host: Schema.String;
|
|
94
|
+
readonly reason: Schema.Literals<readonly ["offline", "unavailable", "timeout", "request_failed", "invalid_response", "internal"]>;
|
|
95
|
+
}>>;
|
|
96
|
+
}>]>;
|
|
97
|
+
}>;
|
|
98
|
+
export interface NeedsYouSource extends Schema.Schema.Type<typeof NeedsYouSource> {
|
|
99
|
+
}
|
|
100
|
+
/** Complete has no source problems; Partial always names at least one. */
|
|
101
|
+
export declare const NeedsYouResult: Schema.Union<readonly [Schema.TaggedStruct<"Complete", {
|
|
102
|
+
readonly items: Schema.$Array<Schema.Struct<{
|
|
103
|
+
readonly key: Schema.String;
|
|
104
|
+
readonly provider: Schema.String;
|
|
105
|
+
readonly destination: Schema.TaggedStruct<"FleetApproval", {
|
|
106
|
+
readonly module: Schema.Literal<"fleet">;
|
|
107
|
+
readonly host: Schema.String;
|
|
108
|
+
readonly jobId: Schema.String;
|
|
109
|
+
}>;
|
|
110
|
+
readonly kind: Schema.Literals<readonly ["nix.check", "nix.apply", "agent.delegate", "agent.message", "work.reconcile", "work.admit", "work.recover", "work.reassign", "work.abandon", "browser.mcp.recover"]>;
|
|
111
|
+
readonly actor: Schema.String;
|
|
112
|
+
readonly createdAt: Schema.Number;
|
|
113
|
+
readonly expiresAt: Schema.NullOr<Schema.Number>;
|
|
114
|
+
}>>;
|
|
115
|
+
}>, Schema.TaggedStruct<"Partial", {
|
|
116
|
+
readonly items: Schema.$Array<Schema.Struct<{
|
|
117
|
+
readonly key: Schema.String;
|
|
118
|
+
readonly provider: Schema.String;
|
|
119
|
+
readonly destination: Schema.TaggedStruct<"FleetApproval", {
|
|
120
|
+
readonly module: Schema.Literal<"fleet">;
|
|
121
|
+
readonly host: Schema.String;
|
|
122
|
+
readonly jobId: Schema.String;
|
|
123
|
+
}>;
|
|
124
|
+
readonly kind: Schema.Literals<readonly ["nix.check", "nix.apply", "agent.delegate", "agent.message", "work.reconcile", "work.admit", "work.recover", "work.reassign", "work.abandon", "browser.mcp.recover"]>;
|
|
125
|
+
readonly actor: Schema.String;
|
|
126
|
+
readonly createdAt: Schema.Number;
|
|
127
|
+
readonly expiresAt: Schema.NullOr<Schema.Number>;
|
|
128
|
+
}>>;
|
|
129
|
+
readonly sources: Schema.$Array<Schema.Struct<{
|
|
130
|
+
readonly provider: Schema.String;
|
|
131
|
+
readonly issue: Schema.Union<readonly [Schema.Struct<{
|
|
132
|
+
readonly state: Schema.Literal<"truncated">;
|
|
133
|
+
}>, Schema.Struct<{
|
|
134
|
+
readonly state: Schema.Literal<"failed">;
|
|
135
|
+
readonly reason: Schema.Literals<readonly ["offline", "unavailable", "timeout", "request_failed", "invalid_response", "internal"]>;
|
|
136
|
+
}>, Schema.Struct<{
|
|
137
|
+
readonly state: Schema.Literal<"hosts">;
|
|
138
|
+
readonly hosts: Schema.$Array<Schema.Struct<{
|
|
139
|
+
readonly host: Schema.String;
|
|
140
|
+
readonly reason: Schema.Literals<readonly ["offline", "unavailable", "timeout", "request_failed", "invalid_response", "internal"]>;
|
|
141
|
+
}>>;
|
|
142
|
+
}>]>;
|
|
143
|
+
}>>;
|
|
144
|
+
}>]>;
|
|
145
|
+
export type NeedsYouResult = typeof NeedsYouResult.Type;
|
|
146
|
+
//# sourceMappingURL=module-needs-you.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module-needs-you.d.ts","sourceRoot":"","sources":["../src/module-needs-you.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAK/B,gFAAgF;AAChF,eAAO,MAAM,mBAAmB;;;;EAI9B,CAAA;AACF,MAAM,WAAW,mBAAoB,SAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,mBAAmB,CAAC;CAAG;AAE9F,wEAAwE;AACxE,eAAO,MAAM,iBAAiB;;;;;;;;;;;EAO5B,CAAA;AACF,MAAM,WAAW,iBAAkB,SAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,iBAAiB,CAAC;CAAG;AAE1F,eAAO,MAAM,qBAAqB,mHAOhC,CAAA;AAEF,eAAO,MAAM,aAAa;;;;;;;;;;;IAUxB,CAAA;AACF,MAAM,MAAM,aAAa,GAAG,OAAO,aAAa,CAAC,IAAI,CAAA;AAErD,iFAAiF;AACjF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;;;;;;;;EAGjC,CAAA;AACF,MAAM,WAAW,sBAAuB,SAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,sBAAsB,CAAC;CAAG;AAGpG,eAAO,MAAM,YAAY;;;;;;;;;;;;EAQvB,CAAA;AACF,MAAM,WAAW,YAAa,SAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,YAAY,CAAC;CAAG;AAEhF,eAAO,MAAM,cAAc;;;;;;;;;;;;;;EAAgE,CAAA;AAC3F,MAAM,WAAW,cAAe,SAAQ,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,cAAc,CAAC;CAAG;AAEpF,0EAA0E;AAC1E,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAMzB,CAAA;AACF,MAAM,MAAM,cAAc,GAAG,OAAO,cAAc,CAAC,IAAI,CAAA"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { FleetHostName, JobActor, JobIdentifier, JobPayload } from "@knpkv/herdr-fleet/model";
|
|
2
|
+
import { Schema } from "effect";
|
|
3
|
+
const SourceKey = Schema.String.check(Schema.isNonEmpty(), Schema.isMaxLength(512));
|
|
4
|
+
const Timestamp = Schema.Number.check(Schema.isInt(), Schema.isBetween({ minimum: 0, maximum: 8_640_000_000_000_000 }));
|
|
5
|
+
/** Exact object selectors, without an approval proof, action payload or URL. */
|
|
6
|
+
export const NeedsYouDestination = Schema.TaggedStruct("FleetApproval", {
|
|
7
|
+
module: Schema.Literal("fleet"),
|
|
8
|
+
host: FleetHostName,
|
|
9
|
+
jobId: JobIdentifier
|
|
10
|
+
});
|
|
11
|
+
/** Providers supply local keys; the hub owns their module namespace. */
|
|
12
|
+
export const NeedsYouCandidate = Schema.Struct({
|
|
13
|
+
sourceKey: SourceKey,
|
|
14
|
+
destination: NeedsYouDestination,
|
|
15
|
+
kind: Schema.Literals(Schema.Union(JobPayload.members).pipe(Schema.toTaggedUnion("kind")).discriminants),
|
|
16
|
+
actor: JobActor,
|
|
17
|
+
createdAt: Timestamp,
|
|
18
|
+
expiresAt: Schema.NullOr(Timestamp)
|
|
19
|
+
});
|
|
20
|
+
export const NeedsYouFailureReason = Schema.Literals([
|
|
21
|
+
"offline",
|
|
22
|
+
"unavailable",
|
|
23
|
+
"timeout",
|
|
24
|
+
"request_failed",
|
|
25
|
+
"invalid_response",
|
|
26
|
+
"internal"
|
|
27
|
+
]);
|
|
28
|
+
export const NeedsYouIssue = Schema.Union([
|
|
29
|
+
Schema.Struct({ state: Schema.Literal("truncated") }),
|
|
30
|
+
Schema.Struct({ state: Schema.Literal("failed"), reason: NeedsYouFailureReason }),
|
|
31
|
+
Schema.Struct({
|
|
32
|
+
state: Schema.Literal("hosts"),
|
|
33
|
+
hosts: Schema.Array(Schema.Struct({
|
|
34
|
+
host: FleetHostName,
|
|
35
|
+
reason: NeedsYouFailureReason
|
|
36
|
+
})).check(Schema.isMinLength(1))
|
|
37
|
+
})
|
|
38
|
+
]);
|
|
39
|
+
/** A failed or bounded source remains visible even when it returned no items. */
|
|
40
|
+
export const NeedsYouProviderResult = Schema.Struct({
|
|
41
|
+
items: Schema.Array(NeedsYouCandidate),
|
|
42
|
+
issues: Schema.Array(NeedsYouIssue)
|
|
43
|
+
});
|
|
44
|
+
const ProviderId = Schema.String.check(Schema.isPattern(/^[a-z][a-z0-9-]*$/));
|
|
45
|
+
export const NeedsYouItem = Schema.Struct({
|
|
46
|
+
key: Schema.String.check(Schema.isNonEmpty(), Schema.isMaxLength(1_024)),
|
|
47
|
+
provider: ProviderId,
|
|
48
|
+
destination: NeedsYouCandidate.fields.destination,
|
|
49
|
+
kind: NeedsYouCandidate.fields.kind,
|
|
50
|
+
actor: NeedsYouCandidate.fields.actor,
|
|
51
|
+
createdAt: NeedsYouCandidate.fields.createdAt,
|
|
52
|
+
expiresAt: NeedsYouCandidate.fields.expiresAt
|
|
53
|
+
});
|
|
54
|
+
export const NeedsYouSource = Schema.Struct({ provider: ProviderId, issue: NeedsYouIssue });
|
|
55
|
+
/** Complete has no source problems; Partial always names at least one. */
|
|
56
|
+
export const NeedsYouResult = Schema.Union([
|
|
57
|
+
Schema.TaggedStruct("Complete", { items: Schema.Array(NeedsYouItem) }),
|
|
58
|
+
Schema.TaggedStruct("Partial", {
|
|
59
|
+
items: Schema.Array(NeedsYouItem),
|
|
60
|
+
sources: Schema.Array(NeedsYouSource).check(Schema.isMinLength(1))
|
|
61
|
+
})
|
|
62
|
+
]);
|
|
63
|
+
//# sourceMappingURL=module-needs-you.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"module-needs-you.js","sourceRoot":"","sources":["../src/module-needs-you.ts"],"names":[],"mappings":"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"}
|
package/dist/module-server.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Context, Effect, Layer, Schema } from "effect";
|
|
2
2
|
import { type ModuleDescriptor, type ModuleListener, ModuleRegistrationError } from "./module-contract.js";
|
|
3
|
+
import { type NeedsYouProviderResult } from "./module-needs-you.js";
|
|
3
4
|
export interface ModuleResponse {
|
|
4
5
|
readonly status: 200 | 201 | 202;
|
|
5
6
|
readonly body: Schema.Json;
|
|
@@ -24,6 +25,8 @@ export interface ModuleApiRoute {
|
|
|
24
25
|
}
|
|
25
26
|
declare const ModuleHandlers_base: Context.ServiceClass<ModuleHandlers, "@knpkv/herdr-hub/ModuleHandlers", {
|
|
26
27
|
readonly routes: ReadonlyArray<ModuleApiRoute>;
|
|
28
|
+
/** Closed over services at layer build; expected source failures are returned as issues. */
|
|
29
|
+
readonly needsYou?: Effect.Effect<NeedsYouProviderResult>;
|
|
27
30
|
}>;
|
|
28
31
|
export declare class ModuleHandlers extends ModuleHandlers_base {
|
|
29
32
|
}
|
|
@@ -43,22 +46,22 @@ export declare class ModuleRegistry extends ModuleRegistry_base {
|
|
|
43
46
|
}
|
|
44
47
|
/** Validate both registrations before acquiring any module layer; metadata must be shared. */
|
|
45
48
|
export declare const makeModuleLayer: <E, R>(descriptors: ReadonlyArray<ModuleDescriptor>, modules: ReadonlyArray<ServerModule<E, R>>) => Layer.Layer<ModuleRegistry, E | ModuleRegistrationError, R>;
|
|
46
|
-
/** Read routes
|
|
47
|
-
export declare const moduleReadRoute: <A>(path: ModuleApiRoute["path"], success: Schema.Codec<A, Schema.Json, never, never>, handle: (query:
|
|
48
|
-
/** Decode
|
|
49
|
-
export declare const moduleWriteRoute: <A, B>(method: Exclude<ModuleApiRoute["method"], "GET">, path: ModuleApiRoute["path"], schema: Schema.Codec<A, unknown, never, never>, success: Schema.Codec<B, Schema.Json, never, never>, handle: (body: A, query:
|
|
49
|
+
/** Read routes decode a query codec and encode success; stable services are acquired by the product layer. */
|
|
50
|
+
export declare const moduleReadRoute: <Q, A>(path: ModuleApiRoute["path"], querySchema: Schema.Codec<Q, URLSearchParams, never, never>, success: Schema.Codec<A, Schema.Json, never, never>, handle: (query: Q) => Effect.Effect<A, ModuleRouteFailure>, status?: ModuleResponse["status"]) => ModuleApiRoute;
|
|
51
|
+
/** Decode query and body after authorization; handlers receive the validated selectors and body. */
|
|
52
|
+
export declare const moduleWriteRoute: <Q, A, B>(method: Exclude<ModuleApiRoute["method"], "GET">, path: ModuleApiRoute["path"], querySchema: Schema.Codec<Q, URLSearchParams, never, never>, schema: Schema.Codec<A, unknown, never, never>, success: Schema.Codec<B, Schema.Json, never, never>, handle: (body: A, query: Q) => Effect.Effect<B, ModuleRouteFailure>, status?: ModuleResponse["status"]) => ModuleApiRoute;
|
|
50
53
|
/**
|
|
51
54
|
* Return null for unmatched methods, modules or listeners. For `/v1/modules/*`, callers must
|
|
52
55
|
* answer 404 on null, never delegate that namespace to another handler. A work-mode listener
|
|
53
56
|
* remains restricted to its existing peer API and must not invoke this mount.
|
|
54
57
|
*/
|
|
55
|
-
export declare const dispatchModuleRoute: <E, R>(request: {
|
|
58
|
+
export declare const dispatchModuleRoute: <E, R, OriginError = E, BodyError = E>(request: {
|
|
56
59
|
readonly method: string;
|
|
57
60
|
readonly url: URL;
|
|
58
|
-
readonly listener: ModuleListener;
|
|
61
|
+
readonly listener: ModuleListener | "work";
|
|
59
62
|
readonly authorize: Effect.Effect<unknown, E, R>;
|
|
60
|
-
readonly sameOrigin: Effect.Effect<unknown,
|
|
61
|
-
readonly readJson: () => Effect.Effect<Schema.Json,
|
|
62
|
-
}) => Effect.Effect<ModuleResponse | null, E | ModuleRouteFailure, R | ModuleRegistry>;
|
|
63
|
+
readonly sameOrigin: Effect.Effect<unknown, OriginError, R>;
|
|
64
|
+
readonly readJson: () => Effect.Effect<Schema.Json, BodyError, R>;
|
|
65
|
+
}) => Effect.Effect<ModuleResponse | null, BodyError | E | OriginError | ModuleRouteFailure, R | ModuleRegistry>;
|
|
63
66
|
export {};
|
|
64
67
|
//# sourceMappingURL=module-server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"module-server.d.ts","sourceRoot":"","sources":["../src/module-server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAU,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/D,OAAO,EACL,KAAK,gBAAgB,EACrB,KAAK,cAAc,EACnB,uBAAuB,
|
|
1
|
+
{"version":3,"file":"module-server.d.ts","sourceRoot":"","sources":["../src/module-server.ts"],"names":[],"mappings":"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"}
|
package/dist/module-server.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Context, Effect, Layer, Result, Schema } from "effect";
|
|
2
|
-
import { ModuleRegistrationError, moduleRegistryFingerprint, validateModuleRegistry } from "./module-contract.js";
|
|
2
|
+
import { ModuleRegistrationError, moduleRegistryFingerprint, todayModule, validateModuleRegistry } from "./module-contract.js";
|
|
3
|
+
import { collectNeedsYou } from "./module-needs-you-server.js";
|
|
4
|
+
import { NeedsYouResult } from "./module-needs-you.js";
|
|
3
5
|
/** Safe route failures carry public copy only. Provider errors stay inside the module. */
|
|
4
6
|
export class ModuleRouteFailure extends Schema.TaggedError()("ModuleRouteFailure", {
|
|
5
7
|
status: Schema.Literals([400, 404, 409, 500, 503]),
|
|
@@ -38,20 +40,39 @@ export const makeModuleLayer = (descriptors, modules) => Layer.effect(ModuleRegi
|
|
|
38
40
|
if (!routeHandlers.has(route) || Result.isFailure(Schema.decodeUnknownResult(ApiPath)(route.path))) {
|
|
39
41
|
return yield* new ModuleRegistrationError({ module: module.descriptor.id, reason: "invalid_route" });
|
|
40
42
|
}
|
|
43
|
+
if (module.descriptor.id === todayModule.id && route.method === "GET" && route.path === "/needs-you") {
|
|
44
|
+
return yield* new ModuleRegistrationError({ module: module.descriptor.id, reason: "duplicate_route" });
|
|
45
|
+
}
|
|
41
46
|
const identity = `${route.method} ${route.path}`;
|
|
42
47
|
if (identities.has(identity)) {
|
|
43
48
|
return yield* new ModuleRegistrationError({ module: module.descriptor.id, reason: "duplicate_route" });
|
|
44
49
|
}
|
|
45
50
|
identities.add(identity);
|
|
46
51
|
}
|
|
47
|
-
return { descriptor: module.descriptor, routes: handlers.routes };
|
|
52
|
+
return { descriptor: module.descriptor, routes: handlers.routes, needsYou: handlers.needsYou };
|
|
48
53
|
}));
|
|
49
|
-
|
|
54
|
+
const providers = mounted.flatMap((module) => module.needsYou === undefined
|
|
55
|
+
? [] :
|
|
56
|
+
[{ id: module.descriptor.id, read: module.needsYou }]);
|
|
57
|
+
const readNeedsYou = collectNeedsYou(providers);
|
|
58
|
+
return {
|
|
59
|
+
modules: mounted.map((module) => ({
|
|
60
|
+
descriptor: module.descriptor,
|
|
61
|
+
routes: module.descriptor.id === todayModule.id
|
|
62
|
+
? [
|
|
63
|
+
...module.routes,
|
|
64
|
+
moduleReadRoute("/needs-you", Schema.fromURLSearchParams(Schema.Record(Schema.String, Schema.Never)), NeedsYouResult, () => readNeedsYou)
|
|
65
|
+
]
|
|
66
|
+
: module.routes
|
|
67
|
+
}))
|
|
68
|
+
};
|
|
50
69
|
}));
|
|
51
|
-
/**
|
|
52
|
-
|
|
53
|
-
/**
|
|
54
|
-
export const
|
|
70
|
+
/** Decode query selectors before the handler; unknown keys fail instead of being discarded. */
|
|
71
|
+
const decodeModuleQuery = (schema, query) => Schema.decodeUnknownEffect(schema, { onExcessProperty: "error" })(query).pipe(Effect.mapError(() => new ModuleRouteFailure({ status: 400, code: "invalid_query" })));
|
|
72
|
+
/** Read routes decode a query codec and encode success; stable services are acquired by the product layer. */
|
|
73
|
+
export const moduleReadRoute = (path, querySchema, success, handle, status = 200) => registerRoute("GET", path, (query) => decodeModuleQuery(querySchema, query).pipe(Effect.flatMap(handle), Effect.flatMap((body) => Schema.encodeEffect(success)(body)), Effect.mapError((error) => error._tag === "ModuleRouteFailure" ? error : new ModuleRouteFailure({ status: 500, code: "invalid_response" })), Effect.map((body) => ({ status, body }))));
|
|
74
|
+
/** Decode query and body after authorization; handlers receive the validated selectors and body. */
|
|
75
|
+
export const moduleWriteRoute = (method, path, querySchema, schema, success, handle, status = 200) => registerRoute(method, path, (query, body) => decodeModuleQuery(querySchema, query).pipe(Effect.flatMap((decodedQuery) => Schema.decodeUnknownEffect(schema)(body).pipe(Effect.mapError(() => new ModuleRouteFailure({ status: 400, code: "invalid_body" })), Effect.flatMap((decoded) => handle(decoded, decodedQuery)))), Effect.flatMap((response) => Schema.encodeEffect(success)(response).pipe(Effect.mapError(() => new ModuleRouteFailure({ status: 500, code: "invalid_response" })))), Effect.map((body) => ({ status, body }))));
|
|
55
76
|
/**
|
|
56
77
|
* Return null for unmatched methods, modules or listeners. For `/v1/modules/*`, callers must
|
|
57
78
|
* answer 404 on null, never delegate that namespace to another handler. A work-mode listener
|
|
@@ -63,7 +84,7 @@ export const dispatchModuleRoute = Effect.fn("ModuleRegistry.dispatch")(function
|
|
|
63
84
|
const prefix = `/v1/modules/${module.descriptor.id}`;
|
|
64
85
|
if (!request.url.pathname.startsWith(`${prefix}/`))
|
|
65
86
|
continue;
|
|
66
|
-
if (!module.descriptor.listeners.
|
|
87
|
+
if (!module.descriptor.listeners.some((listener) => listener === request.listener))
|
|
67
88
|
return null;
|
|
68
89
|
const route = module.routes.find((candidate) => candidate.method === request.method && `${prefix}${candidate.path}` === request.url.pathname);
|
|
69
90
|
if (route === undefined)
|