History

feat: API contract, server handler, and frontend with effect-atom

- packages/core/api: HttpApi contract with ToolsApi + SecretsApi groups SDK tagged errors pass through directly with status annotations (ToolNotFoundError→404, PolicyDeniedError→403, etc.) - apps/server: API handler implementation via HttpApiBuilder Exports createApiHandler() for reuse (no baked-in server runtime) Handlers are pure pass-through — no manual error catching - apps/web: Vite + React frontend served on same port as API Vite plugin forwards /v1/*, /docs, /openapi.json to Effect handler effect-atom integration: AtomHttpApi.Tag typed client, query/mutation atoms RegistryProvider + useAtomValue with Result pattern matching - Catalog pins @effect/platform, platform-bun, platform-node, cluster - All 9 packages typecheck clean

Rhys Sullivan committed 7 months ago

Commit 8babea81 parent 00219a926 files · +1022 −32Browse files

Showing the changes to packages/core/api/src/secrets (1 of 26 files). Show all

Unified · Split

packages/core/api/src/secrets/api.ts+78−0
@@ -0,0 +1,78 @@
1import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "@effect/platform";
2import { Schema } from "effect";
3import {
4 ScopeId,
5 SecretId,
6 SecretNotFoundError,
7 SecretResolutionError,
8} from "@executor/sdk";
9
10// ---------------------------------------------------------------------------
11// Params
12// ---------------------------------------------------------------------------
13
14const scopeIdParam = HttpApiSchema.param("scopeId", ScopeId);
15const secretIdParam = HttpApiSchema.param("secretId", SecretId);
16
17// ---------------------------------------------------------------------------
18// Response / payload schemas
19// ---------------------------------------------------------------------------
20
21const SecretRefResponse = Schema.Struct({
22 id: SecretId,
23 scopeId: ScopeId,
24 name: Schema.String,
25 provider: Schema.optional(Schema.String),
26 purpose: Schema.optional(Schema.String),
27 createdAt: Schema.Number,
28});
29
30const SecretStatusResponse = Schema.Struct({
31 secretId: SecretId,
32 status: Schema.Literal("resolved", "missing"),
33});
34
35const SetSecretPayload = Schema.Struct({
36 id: SecretId,
37 name: Schema.String,
38 value: Schema.String,
39 purpose: Schema.optional(Schema.String),
40 provider: Schema.optional(Schema.String),
41});
42
43// ---------------------------------------------------------------------------
44// Error schemas with HTTP status annotations
45// ---------------------------------------------------------------------------
46
47const SecretNotFound = SecretNotFoundError.annotations(
48 HttpApiSchema.annotations({ status: 404 }),
49);
50const SecretResolution = SecretResolutionError.annotations(
51 HttpApiSchema.annotations({ status: 500 }),
52);
53
54// ---------------------------------------------------------------------------
55// Group
56// ---------------------------------------------------------------------------
57
58export class SecretsApi extends HttpApiGroup.make("secrets")
59 .add(
60 HttpApiEndpoint.get("list")`/scopes/${scopeIdParam}/secrets`
61 .addSuccess(Schema.Array(SecretRefResponse)),
62 )
63 .add(
64 HttpApiEndpoint.get("status")`/scopes/${scopeIdParam}/secrets/${secretIdParam}/status`
65 .addSuccess(SecretStatusResponse),
66 )
67 .add(
68 HttpApiEndpoint.post("set")`/scopes/${scopeIdParam}/secrets`
69 .setPayload(SetSecretPayload)
70 .addSuccess(SecretRefResponse)
71 .addError(SecretResolution),
72 )
73 .add(
74 HttpApiEndpoint.del("remove")`/scopes/${scopeIdParam}/secrets/${secretIdParam}`
75 .addSuccess(Schema.Struct({ removed: Schema.Boolean }))
76 .addError(SecretNotFound),
77 )
78 .prefix("/v1") {}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t