- 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
Showing the changes to packages/core/api/src/secrets (1 of 26 files). Show all
Unified · Split
| @@ -0,0 +1,78 @@ | |||
| 1 | import { HttpApiEndpoint, HttpApiGroup, HttpApiSchema } from "@effect/platform"; | ||
| 2 | import { Schema } from "effect"; | ||
| 3 | import { | ||
| 4 | ScopeId, | ||
| 5 | SecretId, | ||
| 6 | SecretNotFoundError, | ||
| 7 | SecretResolutionError, | ||
| 8 | } from "@executor/sdk"; | ||
| 9 | |||
| 10 | // --------------------------------------------------------------------------- | ||
| 11 | // Params | ||
| 12 | // --------------------------------------------------------------------------- | ||
| 13 | |||
| 14 | const scopeIdParam = HttpApiSchema.param("scopeId", ScopeId); | ||
| 15 | const secretIdParam = HttpApiSchema.param("secretId", SecretId); | ||
| 16 | |||
| 17 | // --------------------------------------------------------------------------- | ||
| 18 | // Response / payload schemas | ||
| 19 | // --------------------------------------------------------------------------- | ||
| 20 | |||
| 21 | const 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 | |||
| 30 | const SecretStatusResponse = Schema.Struct({ | ||
| 31 | secretId: SecretId, | ||
| 32 | status: Schema.Literal("resolved", "missing"), | ||
| 33 | }); | ||
| 34 | |||
| 35 | const 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 | |||
| 47 | const SecretNotFound = SecretNotFoundError.annotations( | ||
| 48 | HttpApiSchema.annotations({ status: 404 }), | ||
| 49 | ); | ||
| 50 | const SecretResolution = SecretResolutionError.annotations( | ||
| 51 | HttpApiSchema.annotations({ status: 500 }), | ||
| 52 | ); | ||
| 53 | |||
| 54 | // --------------------------------------------------------------------------- | ||
| 55 | // Group | ||
| 56 | // --------------------------------------------------------------------------- | ||
| 57 | |||
| 58 | export 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") {} | ||