### Defining and Serving an HTTP API with OpenAPI Documentation Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md Illustrates the complete setup for an HTTP API, including defining multiple endpoints (GET, POST, DELETE, PATCH), implementing handlers, and integrating HttpApiScalar for interactive OpenAPI documentation. ```APIDOC ## getUsers / ### Description Retrieves a list of all users. ### Method GET ### Endpoint /users ### Parameters (No parameters) ### Response #### Success Response (200) - (Array of User objects) - A list of users. ### Request Example (No request body for GET) ### Response Example ```json [ { "id": 1, "name": "User 1" }, { "id": 2, "name": "User 2" } ] ``` ``` ```APIDOC ## getUser /user/:id ### Description Retrieves a specific user by their ID. ### Method GET ### Endpoint /user/:id ### Parameters #### Path Parameters - **id** (int) - Required - The ID of the user to retrieve. ### Response #### Success Response (200) - **id** (int) - The user's ID. - **name** (string) - The user's name. ### Request Example (No request body for GET) ### Response Example ```json { "id": 1, "name": "User 1" } ``` ``` ```APIDOC ## createUser /user ### Description Creates a new user. ### Method POST ### Endpoint /user ### Parameters #### Request Body - **id** (int) - Required - The ID of the new user. - **name** (string) - Required - The name of the new user. ### Request Example ```json { "id": 1, "name": "User 1" } ``` ### Response #### Success Response (200) - **id** (int) - The ID of the created user. - **name** (string) - The name of the created user. ### Response Example ```json { "id": 1, "name": "User 1" } ``` ``` ```APIDOC ## deleteUser /user/:id ### Description Deletes a user by their ID. ### Method DELETE ### Endpoint /user/:id ### Parameters #### Path Parameters - **id** (int) - Required - The ID of the user to delete. ### Response #### Success Response (200) (No content) ### Request Example (No request body for DELETE) ### Response Example (No response body) ``` ```APIDOC ## updateUser /user/:id ### Description Updates an existing user's name. ### Method PATCH ### Endpoint /user/:id ### Parameters #### Path Parameters - **id** (int) - Required - The ID of the user to update. #### Request Body - **name** (string) - Required - The new name for the user. ### Request Example ```json { "name": "Updated User Name" } ``` ### Response #### Success Response (200) - **id** (int) - The ID of the updated user. - **name** (string) - The updated name of the user. ### Response Example ```json { "id": 1, "name": "Updated User Name" } ``` ``` -------------------------------- ### Install Vitest Source: https://github.com/effect-ts/effect-smol/blob/main/packages/vitest/README.md Install vitest as a development dependency. ```sh pnpm add -D vitest ``` -------------------------------- ### Complete MCP Server Example Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/MCP.md A full-fledged MCP server example demonstrating tools, parameterized resources, prompts, and server layer configuration. This example combines multiple MCP features for a comprehensive use case. ```typescript import { NodeRuntime, NodeStdio } from "@effect/platform-node" import { Effect, Layer, Logger, Schema } from "effect" import { McpSchema, McpServer, Tool, Toolkit } from "effect/unstable/ai" // Define tools const GreetTool = Tool.make("GreetTool", { description: "Generate a greeting message", parameters: Schema.Struct({ name: Schema.String, style: Schema.Union([Schema.Literal("formal"), Schema.Literal("casual")]) }), success: Schema.String }) const CalculatorTool = Tool.make("CalculatorTool", { description: "Perform basic arithmetic operations", parameters: Schema.Struct({ operation: Schema.Union([ Schema.Literal("add"), Schema.Literal("subtract"), Schema.Literal("multiply"), Schema.Literal("divide") ]), a: Schema.Number, b: Schema.Number }), success: Schema.Number }) // Create toolkit const MyToolkit = Toolkit.make(GreetTool, CalculatorTool) // Define a resource const ReadmeResource = McpServer.resource({ uri: "file:///README.md", name: "README", description: "Project README file", mimeType: "text/markdown", content: Effect.succeed("# MCP Server Demo\n\nThis is a demo MCP server built with Effect.") }) // Define a parameterized resource const idParam = McpSchema.param("id", Schema.NumberFromString) const UserResource = McpServer.resource`file://users/${idParam}.json`({ name: "User Data", description: "User information by ID", completion: { id: (_: string) => Effect.succeed([1, 2, 3, 4, 5]) }, content: Effect.fn(function*(_uri, id) { return JSON.stringify( { id, name: `User ${id}`, email: `user${id}@example.com` }, null, 2 ) }), mimeType: "application/json" }) // Define a prompt const AnalysisPrompt = McpServer.prompt({ name: "Analyze Data", description: "Analyze data and provide insights", parameters: { dataType: Schema.String, focus: Schema.Union([Schema.Literal("summary"), Schema.Literal("details")]) }, completion: { dataType: () => Effect.succeed(["sales", "users", "metrics"]), focus: () => Effect.succeed(["summary" as const, "details" as const]) }, content: ({ dataType, focus }) => Effect.succeed( `Please analyze the ${dataType} data and provide a ${focus} analysis. Use available tools to gather information.` ) }) // Create the server layer const ServerLayer = Layer.mergeAll( ReadmeResource, UserResource, AnalysisPrompt, McpServer.toolkit(MyToolkit).pipe( Layer.provideMerge( MyToolkit.toLayer({ GreetTool: ({ name, style }) => { const greeting = style === "formal" ? `Good day, ${name}. It is a pleasure to meet you.` : `Hey ${name}! What's up?` return Effect.succeed(greeting) }, CalculatorTool: ({ operation, a, b }) => { let result: number switch (operation) { case "add": result = a + b break case "subtract": result = a - b break case "multiply": result = a * b break case "divide": result = a / b break } return Effect.succeed(result) } }) ) ) ).pipe( Layer.provide( McpServer.layerStdio({ name: "Demo MCP Server", version: "1.0.0" }) ), Layer.provide(NodeStdio.layer), Layer.provide(Layer.succeed(Logger.LogToStderr)(true)) ) // Run the server Layer.launch(ServerLayer).pipe(NodeRuntime.runMain) ``` -------------------------------- ### MCP Server Implementation with Effect Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/MCP.md This snippet demonstrates the full setup of an MCP server using Effect-TS. It defines a demo tool, a resource, a prompt, and configures the server with standard I/O. Ensure necessary Effect platform and schema packages are installed. ```typescript import { NodeRuntime, NodeSink, NodeStream } from "@effect/platform-node" import { Effect, Layer, Logger } from "effect" import { Schema } from "effect/schema" import { McpServer, Tool, Toolkit } from "effect/unstable/ai" // Define a simple tool const DemoTool = Tool.make("DemoTool", { description: "A demo tool that echoes back the input", parameters: { message: Schema.String }, success: Schema.String }) const MyToolkit = Toolkit.make(DemoTool) const DemoResource = McpServer.resource({ uri: "file:///demo.txt", name: "Demo Resource", content: Effect.succeed("# Demo Content\nThis is a demo resource.") }) const DemoPrompt = McpServer.prompt({ name: "Demo Prompt", description: "A demo prompt", parameters: { topic: Schema.String }, completion: { topic: () => Effect.succeed(["AI", "programming", "Effect"]) }, content: ({ topic }) => Effect.succeed(`Tell me about ${topic}`) }) const ServerLayer = Layer.mergeAll( DemoResource, DemoPrompt, McpServer.toolkit(MyToolkit).pipe( Layer.provideMerge( MyToolkit.toLayer({ DemoTool: ({ message }) => Effect.succeed(`Echo: ${message}`) }) ) ) ).pipe( Layer.provide( McpServer.layerStdio({ name: "Demo MCP Server", version: "1.0.0", stdin: NodeStream.stdin, stdout: NodeSink.stdout }) ), Layer.provide(Logger.layer([Logger.consolePretty({ stderr: true })])) ) Layer.launch(ServerLayer).pipe(NodeRuntime.runMain) ``` -------------------------------- ### Example Suite Entry in config.json Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/typeperf/README.md Example configuration for a 'schema' suite, including its baseline, thresholds file, and a list of fixtures. ```json { "name": "schema", "baseline": "suites/schema/baseline.ts", "thresholds": "suites/schema/thresholds.json", "fixtures": [ { "name": "struct-required", "file": "suites/schema/fixtures/struct-required.ts" } ] } ``` -------------------------------- ### Install @effect/vitest Source: https://github.com/effect-ts/effect-smol/blob/main/packages/vitest/README.md Install the @effect/vitest package to integrate Effect with Vitest. ```sh pnpm add -D @effect/vitest ``` -------------------------------- ### Security Middleware Example Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md This example shows how to define and apply security middlewares for API key, Basic, and Bearer token authentication. ```APIDOC ## Security Middleware ### Description Middlewares for enforcing security on HTTP endpoints. ### Supported Authorization Types | Authorization Type | Description | | ------------------------ | ---------------------------------------------------------------- | | `HttpApiSecurity.apiKey` | API key authorization via headers, query parameters, or cookies. | | `HttpApiSecurity.basic` | HTTP Basic authentication. | | `HttpApiSecurity.bearer` | Bearer token authentication. | ### Example (Bearer Token) This example defines a `Authorization` middleware that uses Bearer token authentication. #### Middleware Definition ```ts class Authorization extends HttpApiMiddleware.Service()( "Authorization", { error: Unauthorized, security: { myBearer: HttpApiSecurity.bearer } } ) {} ``` #### Applying Middleware - To a single endpoint: `.middleware(Authorization)` - To an entire group: `.middleware(Authorization)` - To the entire API: `.middleware(Authorization)` ### Error Handling - `Unauthorized` error with HTTP status 401. ``` -------------------------------- ### Add New Fixture Example Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/typeperf/README.md Example of a fixture file measuring the marginal type-level cost of Schema.Struct with optional keys. It includes type aliases to force type computation. ```typescript // Measures the marginal type-level cost of Schema.Struct when all fields are optional keys. import { Schema } from "effect" Schema.String const schema = Schema.Struct({ id: Schema.optionalKey(Schema.String), count: Schema.optionalKey(Schema.NumberFromString) }) export type Type = typeof schema.Type export type Encoded = typeof schema.Encoded export type Iso = typeof schema.Iso export type MakeIn = typeof schema["~type.make.in"] ``` -------------------------------- ### JSDoc Example Changes Validation Source: https://github.com/effect-ts/effect-smol/blob/main/AGENTS.md After making changes to JSDoc examples, run linting and then regenerate documentation from the changed package directory. ```bash pnpm lint ``` ```bash pnpm docgen ``` -------------------------------- ### Multi-step Task Plan Example Source: https://github.com/effect-ts/effect-smol/blob/main/AGENTS.md Use this format to outline multi-step tasks, specifying the action and its verification criteria for each step. ```plaintext 1. [Step] → verify: [check] 2. [Step] → verify: [check] 3. [Step] → verify: [check] ``` -------------------------------- ### Install Effect Core Package Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/README.md Install the core 'effect' package using npm. This command adds the necessary dependencies to your project. ```bash npm install effect ``` -------------------------------- ### Web Handler Conversion Example Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md Illustrates converting an Effect HTTP API into a standard web handler that can be integrated with existing HTTP servers. ```APIDOC ## GET / ### Description Retrieves a simple string message. ### Method GET ### Endpoint / ### Parameters #### Query Parameters None #### Request Body None ### Request Example None ### Response #### Success Response (200) - **body** (string) - The response message. ### Response Example ```json "Hello, world!" ``` ``` -------------------------------- ### Logger Middleware Example Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md This example demonstrates how to define and apply a custom logger middleware to an HTTP endpoint and a group. ```APIDOC ## Logger Middleware ### Description A middleware that logs incoming HTTP requests. ### Method Applies to any HTTP method. ### Endpoint Applies to `/user/:id` endpoint and its group. ### Parameters None directly on the middleware definition. ### Request Example Not applicable for middleware definition. ### Response Handles potential errors with a 405 status code and text encoding. #### Success Response (200) Returns the user data. #### Response Example ```json { "id": 1, "name": "User 1" } ``` ``` -------------------------------- ### Example Fixture Code Source: https://github.com/effect-ts/effect-smol/blob/main/packages/tools/bundle/README.md This is an example of a self-contained temporary fixture. It imports public APIs from 'effect/Effect' and 'effect/Schema' and demonstrates basic usage. ```ts import * as Effect from "effect/Effect" import * as Schema from "effect/Schema" const schema = Schema.Struct({ name: Schema.String }) Schema.decodeUnknownEffect(schema)({ name: "effect" }).pipe(Effect.runFork) ``` -------------------------------- ### Serve Auto-Generated Swagger Documentation Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md Integrates Swagger UI for interactive API documentation into the server setup by providing `HttpApiSwagger.layer`. Access documentation at '/docs'. ```typescript const ApiLive = HttpApiBuilder.layer(Api).pipe( Layer.provide(GroupLive), // Provide the Swagger layer so clients can access auto-generated docs Layer.provide(HttpApiSwagger.layer(Api)), // "/docs" is the default path. // or Layer.provide(HttpApiScalar.layer(Api)), HttpRouter.serve, Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 })) ) ``` -------------------------------- ### Register Fixture in config.json Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/typeperf/README.md Example configuration entry for a fixture in config.json. This registers the fixture file with the type performance harness. ```json { "name": "struct-optional-only", "file": "suites/schema/fixtures/struct-optional-only.ts" } ``` -------------------------------- ### Serve Auto-Generated Scalar Documentation Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md Integrates Scalar UI for interactive API documentation into the server setup by providing `HttpApiScalar.layer`. Access documentation at '/docs'. ```typescript const ApiLive = HttpApiBuilder.layer(Api).pipe( // Provide the Scalar layer so clients can access auto-generated docs Layer.provide(GroupLive), Layer.provide(HttpApiScalar.layer(Api)), HttpRouter.serve, Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 })) ) ``` -------------------------------- ### Handling Streaming Requests Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md This example demonstrates how to define an endpoint that accepts streaming binary data from the client. The payload is defined as a `Uint8Array` and can be decoded as needed. ```APIDOC ## POST /stream ### Description Accepts a streaming request with a binary payload. ### Method POST ### Endpoint /stream ### Parameters #### Request Body - **payload** (Uint8Array) - Required - The binary data stream from the client. ### Response #### Success Response (200) - **success** (String) - The decoded string from the binary payload. ### Request Example ```sh echo "abc" | curl -X POST 'http://localhost:3000/stream' --data-binary @- -H "Content-Type: application/octet-stream" ``` ### Response Example ``` abc ``` ``` -------------------------------- ### Test Streaming Request with curl Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md Example command to test the streaming endpoint using curl, sending binary data. ```bash echo "abc" | curl -X POST 'http://localhost:3000/stream' --data-binary @- -H "Content-Type: application/octet-stream" # Output: abc ``` -------------------------------- ### v3 Static Accessor with Effect.Tag Source: https://github.com/effect-ts/effect-smol/blob/main/migration/services.md This example demonstrates the v3 pattern of using `Effect.Tag` with static accessor proxies for calling service methods directly. ```typescript import { Effect } from "effect" class Notifications extends Effect.Tag("Notifications") Effect.Effect }>() {} // Static proxy access const program = Notifications.notify("hello") ``` -------------------------------- ### Implementing and Serving a Hello World API Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md This example demonstrates how to implement the defined API and serve it using Node.js. It includes setting up the handler for the 'hello' endpoint and launching the server. ```APIDOC ## Implementing the API ### Description Provides the implementation logic for the 'Greetings' API group and its 'hello' endpoint. ### Handler - **hello**: () => Effect.succeed("Hello, World!") ## Serving the API ### Description Configures and launches the HTTP server for the defined API, including the implementation and necessary layers. ### Server Configuration - **Port**: 3000 ### Launch Command `Layer.launch(ApiLive).pipe(NodeRuntime.runMain)` ``` -------------------------------- ### Defining a GET Endpoint with a Custom Status Code Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md This example shows how to define a GET endpoint that returns a custom HTTP status code (206 Partial Content) for its success response. ```APIDOC ## GET /users ### Description Retrieves a list of users with a custom success status code. ### Method GET ### Endpoint /users ### Parameters #### Query Parameters None ### Response #### Success Response (206) - **id** (Int) - The user's ID. - **name** (String) - The user's name. ### Response Example ```json [ { "id": 1, "name": "User 1" }, { "id": 2, "name": "User 2" } ] ``` ``` -------------------------------- ### Reading FiberRef in v3 Source: https://github.com/effect-ts/effect-smol/blob/main/migration/fiberref.md In v3, FiberRef.get was used to retrieve the current value of a FiberRef. This example shows how to get the current log level. ```typescript import { Effect, FiberRef } from "effect" const program = Effect.gen(function*() { const level = yield* FiberRef.get(FiberRef.currentLogLevel) console.log(level) }) ``` -------------------------------- ### Reporting Filter Guidance Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/SCHEMA.md Use `{ report: true }` with `Schema.toArbitrary` to get a report on which filters did not guide the generation process. This helps identify potential inefficiencies in custom filters. ```typescript import { Schema } from "effect" const isPalindrome = (s: string) => s === Array.from(s).reverse().join("") const Palindrome = Schema.String.check( Schema.makeFilter(isPalindrome, { expected: "a palindrome" }) ) const result = Schema.toArbitrary(Palindrome, { report: true }) result.value result.report.warnings ``` -------------------------------- ### Accessing the HttpServerRequest in a GET Endpoint Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md This example shows how to access the raw incoming HTTP request object within a handler. This is useful for retrieving low-level details such as the HTTP method or URL when they are not directly provided by the endpoint schema. ```APIDOC ## GET / ### Description Responds with a "Hello, World!" message. This endpoint demonstrates accessing the raw HTTP request object within the handler to log the request method. ### Method GET ### Endpoint / ### Response #### Success Response (200) - (string) - A greeting message. #### Response Example ``` Hello, World! ``` ``` -------------------------------- ### Retry Safe GET Reads Source: https://github.com/effect-ts/effect-smol/blob/main/cookbooks/schedule.md Retry a GET resource read operation only for specific transient errors like 'Timeout' or 'ServiceUnavailable' when the method is 'GET'. `recurs(n)` counts follow-up recurrences after the first execution. ```ts import { Effect, Schedule } from "effect" type Resource = unknown type GetError = | { readonly _tag: "Timeout"; readonly method: "GET" | "POST" } | { readonly _tag: "ServiceUnavailable"; readonly method: "GET" | "POST" } | { readonly _tag: "BadRequest"; readonly method: "GET" | "POST" } declare const getResource: Effect.Effect const isRetryableGetError = (error: GetError) => error.method === "GET" && (error._tag === "Timeout" || error._tag === "ServiceUnavailable") const program = getResource.pipe( Effect.retry({ schedule: Schedule.exponential("100 millis").pipe(Schedule.both(Schedule.recurs(3))), while: isRetryableGetError }) ) ``` -------------------------------- ### Create Custom ConfigProvider with ConfigProvider.make Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/CONFIG.md Builds a ConfigProvider from any backing store by providing a function that resolves paths to values. Return undefined for not found, and fail with SourceError only for I/O errors. ```ts import { ConfigProvider, Effect } from "effect" const data: Record = { host: "localhost", port: "5432" } const provider = ConfigProvider.make((path) => { const key = path.join(".") const value = data[key] return Effect.succeed( value !== undefined ? ConfigProvider.makeValue(value) : undefined ) }) ``` -------------------------------- ### GET /users Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md Defines a GET endpoint to retrieve a list of users. The response is an array of User objects. ```APIDOC ## HttpApiEndpoint.get "getUsers" /users ### Description Retrieves a list of all users. ### Method GET ### Endpoint /users ### Response #### Success Response (200) - **id** (integer) - Description - **name** (string) - Description #### Response Example [ { "id": 1, "name": "User 1" }, { "id": 2, "name": "User 2" } ] ``` -------------------------------- ### Example cURL requests for array query parameters Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md Demonstrates how to test an endpoint configured to accept an array of string values for a query parameter using `curl`. Shows valid requests with multiple values, no values, and a single value. ```shell curl "http://localhost:3000/users?a=1&a=2" # Two values for the `a` parameter ``` ```shell curl "http://localhost:3000/users" # No values for the `a` parameter ``` ```shell curl "http://localhost:3000/users?a=1" # One value for the `a` parameter ``` -------------------------------- ### Define Service with Context.Service (v4 function syntax) Source: https://github.com/effect-ts/effect-smol/blob/main/migration/services.md v4 introduces `Context.Service` as the unified way to define services. This example shows the function syntax for defining a service. ```typescript import { Context } from "effect" interface Database { readonly query: (sql: string) => string } const Database = Context.Service("Database") ``` -------------------------------- ### Define and Implement a Simple HTTP API Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md Defines a basic 'Hello, World!' API with one endpoint, implements it, and sets up a server. Requires importing necessary modules from 'effect' and '@effect/platform-node'. ```typescript import { NodeHttpServer, NodeRuntime } from "@effect/platform-node" import { Effect, Layer, Schema } from "effect" import { HttpRouter } from "effect/unstable/http" import { HttpApi, HttpApiBuilder, HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi" import { createServer } from "node:http" // Definition const Api = HttpApi.make("MyApi").add( // Define the API group HttpApiGroup.make("Greetings").add( // Define the endpoint HttpApiEndpoint.get("hello", "/", { // Define the success schema success: Schema.String }) ) ) // Implementation const GroupLive = HttpApiBuilder.group( Api, "Greetings", // The name of the group to handle (handlers) => handlers.handle( "hello", // The name of the endpoint to handle () => Effect.succeed("Hello, World!") // The handler function ) ) // Server const ApiLive = HttpApiBuilder.layer(Api).pipe( Layer.provide(GroupLive), HttpRouter.serve, Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 })) ) // Launch Layer.launch(ApiLive).pipe(NodeRuntime.runMain) ``` -------------------------------- ### Define and Load Application Configuration Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/CONFIG.md Sets up a structured application configuration using Effect TS schemas for server, database, and debug settings. It shows how to provide a test configuration and run the program. ```typescript import { Config, ConfigProvider, Effect, Schema } from "effect" // Define your config shape const ServerConfig = Config.schema( Schema.Struct({ host: Schema.String, port: Schema.Int, logLevel: Schema.Literals(["debug", "info", "warn", "error"]) }), "server" ) const DbConfig = Config.schema( Schema.Struct({ url: Schema.String, poolSize: Schema.Int }), "db" ) const AppConfig = Config.all({ server: ServerConfig, db: DbConfig, debug: Config.boolean("debug").pipe(Config.withDefault(false)) }) // In production, just yield it — reads from process.env const program = Effect.gen(function*() { const config = yield* AppConfig console.log(config) }) // For testing, provide a specific provider const testProvider = ConfigProvider.fromUnknown({ server: { host: "localhost", port: 3000, logLevel: "debug" }, db: { url: "postgres://localhost/testdb", poolSize: 5 }, debug: true }) Effect.runSync( program.pipe(Effect.provide(ConfigProvider.layer(testProvider))) ) ``` -------------------------------- ### Elysia GET /id/:id Endpoint Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/SCHEMA.md Demonstrates defining path and query parameters using Effect TS Schema for a GET request. ```APIDOC ## GET /id/:id ### Description Handles GET requests to retrieve data based on an ID, with defined query parameters. ### Method GET ### Endpoint /id/:id ### Parameters #### Path Parameters - **id** (Schema.Int) - Required - The identifier for the resource. #### Query Parameters - **required** (Schema.String) - Required - A mandatory string parameter. - **optional** (Schema.String) - Optional - An optional string parameter. - **array** (Schema.Array) - Required - An array of strings. - **tuple** (Schema.Tuple<[Schema.String, Schema.Int]>) - Required - A tuple containing a string and an integer. ### Response #### Success Response (200) - **date** (Schema.ValidDate) - The date and time of the response. ``` -------------------------------- ### GET Endpoint with Path Parameter Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md Defines a GET endpoint that retrieves a specific resource by its ID, using a path parameter to capture the ID from the URL. ```APIDOC ## GET /user/:id ### Description Retrieves a specific user by their unique identifier. ### Method GET ### Endpoint /user/:id ### Parameters #### Path Parameters - **id** (int) - Required - The unique identifier of the user to retrieve. ### Response #### Success Response (200) - **id** (int) - The user's ID. - **name** (string) - The user's name. ``` -------------------------------- ### Service.use and Service.useSync Examples Source: https://github.com/effect-ts/effect-smol/blob/main/migration/services.md Illustrates the usage of `Service.use` for effectful callbacks and `Service.useSync` for synchronous callbacks when accessing services. `useSync` returns an `Effect` with a `never` error channel. ```typescript // ┌─── Effect // ▼ const program = Notifications.use((n) => n.notify("hello")) // ┌─── Effect // ▼ const port = Config.useSync((c) => c.port) ``` -------------------------------- ### Analyze Multiple Bundle Compositions Source: https://github.com/effect-ts/effect-smol/blob/main/packages/tools/bundle/README.md Pass multiple explicit file paths to analyze the bundle composition of several fixtures simultaneously. The wrapper builds the current checkout before generating analysis artifacts. ```sh pnpm bundle-analyze \ scratchpad/schema-codec.ts \ scratchpad/schema-arbitrary.ts ``` -------------------------------- ### Define GET Endpoint with Custom Status Code Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md Create a GET endpoint that returns an array of users, specifying a custom success status code of 206 using HttpApiSchema.status(). ```typescript import { NodeHttpServer, NodeRuntime } from "@effect/platform-node" import { Effect, Layer, Schema } from "effect" import { HttpRouter } from "effect/unstable/http" import { HttpApi, HttpApiBuilder, HttpApiEndpoint, HttpApiGroup, HttpApiScalar, HttpApiSchema } from "effect/unstable/httpapi" import { createServer } from "node:http" const User = Schema.Struct({ id: Schema.Int, name: Schema.String }) const Api = HttpApi.make("MyApi") .add( HttpApiGroup.make("Users") .add( HttpApiEndpoint.get("getUsers", "/users", { success: Schema.Array(User) .pipe(HttpApiSchema.status(206)) }) ) ) const GroupLive = HttpApiBuilder.group( Api, "Users", (handlers) => handlers .handle("getUsers", () => { return Effect.succeed( [{ id: 1, name: "User 1" }, { id: 2, name: "User 2" }] ) }) ) const ApiLive = HttpApiBuilder.layer(Api).pipe( Layer.provide(GroupLive), Layer.provide(HttpApiScalar.layer(Api)), HttpRouter.serve, Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 })) ) Layer.launch(ApiLive).pipe(NodeRuntime.runMain) ``` -------------------------------- ### Deriving and Using a Typed HTTP Client Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md Illustrates how to generate a fully typed client from an API definition and use it to make requests. ```APIDOC # Deriving a Client The `HttpApiClient` module generates a fully typed client from your API definition. Each endpoint becomes a method — grouped by `HttpApiGroup` name — so calling your API is as simple as calling a function. **Example** (Deriving and Using a Client) ```ts import { NodeHttpServer, NodeRuntime } from "@effect/platform-node" import { Effect, Layer, Schema } from "effect" import { HttpRouter } from "effect/unstable/http" import { FetchHttpClient } from "effect/unstable/http" import { HttpApi, HttpApiBuilder, HttpApiClient, HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi" import { createServer } from "node:http" const Api = HttpApi.make("MyApi") .add( HttpApiGroup.make("Greetings") .add( HttpApiEndpoint.get("hello", "/", { success: Schema.String }) ) ) const GroupLive = HttpApiBuilder.group( Api, "Greetings", (handlers) => handlers.handle("hello", () => Effect.succeed("Hello, World!")) ) const ApiLive = HttpApiBuilder.layer(Api).pipe( Layer.provide(GroupLive), HttpRouter.serve, Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 })) ) Layer.launch(ApiLive).pipe(NodeRuntime.runMain) // Create a program that derives and uses the client const program = Effect.gen(function*() { // Derive the client const client = yield* HttpApiClient.make(Api, { baseUrl: "http://localhost:3000" }) // Call the "hello-world" endpoint const hello = yield* client.Greetings.hello() console.log(hello) }) // Provide a Fetch-based HTTP client and run the program Effect.runFork(program.pipe(Effect.provide(FetchHttpClient.layer))) /* Output: [18:55:26.051] INFO (#2): Listening on http://0.0.0.0:3000 [18:55:26.057] INFO (#12) http.span=2ms: Sent HTTP response { 'http.method': 'GET', 'http.url': '/', 'http.status': 200 } Hello, World! */ ``` ``` -------------------------------- ### Basic Optic Operations: Get, Replace, Modify Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/OPTIC.md Demonstrates the fundamental operations of an optic: getting a focused value, replacing it, and modifying it with a function. Requires importing the Optic module. ```typescript import { Optic } from "effect" type S = { readonly a: number } const _a = Optic.id().key("a") /** * Get the value of the focused field */ const value = _a.get({ a: 1 }) console.log(value) // 1 /** * Replace the value of the focused field */ const replaced = _a.replace(2, { a: 1 }) console.log(replaced) // { a: 2 } /** * Modify the value of the focused field */ const modified = _a.modify((n) => n + 1)({ a: 1 }) console.log(modified) // { a: 2 } ``` -------------------------------- ### Retry Cold-Start Dependencies with Effect TS Source: https://github.com/effect-ts/effect-smol/blob/main/cookbooks/schedule.md Configure a retry mechanism for a service startup check. It employs exponential backoff, a maximum of 6 retries, and a 30-second duration limit, retrying only transient dependency check errors. ```ts import { Effect, Schedule } from "effect" type DependencyCheckError = | { readonly _tag: "DnsLookup" } | { readonly _tag: "ConnectionRefused" } | { readonly _tag: "Timeout" } | { readonly _tag: "BadCredentials" } | { readonly _tag: "SchemaMismatch" } declare const checkDependency: Effect.Effect const isRetryableStartupCheckError = (error: DependencyCheckError): boolean => error._tag === "DnsLookup" || error._tag === "ConnectionRefused" || error._tag === "Timeout" const dependencyStartup = Schedule.exponential("100 millis").pipe( Schedule.both(Schedule.recurs(6)), Schedule.both(Schedule.during("30 seconds")) ) const program = checkDependency.pipe( Effect.retry({ schedule: dependencyStartup, while: isRetryableStartupCheckError }) ) ``` -------------------------------- ### Define a GET Endpoint to Retrieve All Users Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md Defines a GET endpoint named 'getUsers' for retrieving a list of users. It specifies the API path and the success schema for the response, which is an array of User entities. ```ts import { NodeHttpServer, NodeRuntime } from "@effect/platform-node" import { Effect, Layer, Schema } from "effect" import { HttpRouter } from "effect/unstable/http" import { HttpApi, HttpApiBuilder, HttpApiEndpoint, HttpApiGroup, HttpApiScalar } from "effect/unstable/httpapi" import { createServer } from "node:http" // Define a schema representing a User entity const User = Schema.Struct({ id: Schema.Int, name: Schema.String }) const Api = HttpApi.make("MyApi") .add( HttpApiGroup.make("Users") .add( // Define the "getUsers" endpoint, returning a list of users // ┌─── Endpoint name (used in the client as the method name) // │ ┌─── Endpoint path // ▼ ▼ HttpApiEndpoint.get("getUsers", "/users", { // ┌─── success schema // │ // ▼ success: Schema.Array(User) }) ) ) const GroupLive = HttpApiBuilder.group( Api, "Users", (handlers) => handlers.handle("getUsers", () => Effect.succeed( [{ id: 1, name: "User 1" }, { id: 2, name: "User 2" }] )) ) const ApiLive = HttpApiBuilder.layer(Api).pipe( Layer.provide(GroupLive), Layer.provide(HttpApiScalar.layer(Api)), HttpRouter.serve, Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 })) ) Layer.launch(ApiLive).pipe(NodeRuntime.runMain) ``` -------------------------------- ### Defining an Array of Values for a Query Parameter Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md This example shows how to define a query parameter that can accept an array of values. This is useful for parameters where multiple values can be provided in the query string (e.g., `?a=1&a=2`). ```APIDOC ## GET /users ### Description Retrieves a list of users, with a query parameter that accepts an array of string values. ### Method GET ### Endpoint /users ### Parameters #### Query Parameters - **a** (Array) - Optional - A parameter that can accept multiple string values. ### Request Example ```json { "example": "No request body for GET request" } ``` ### Response #### Success Response (200) - **id** (int) - The user's unique identifier. - **name** (string) - The user's name. #### Response Example ```json { "example": [ { "id": 1, "name": "User 1" }, { "id": 2, "name": "User 2" } ] } ``` ### Example Usage ```sh curl "http://localhost:3000/users?a=1&a=2" ``` ``` -------------------------------- ### Analyze Bundle Composition with pnpm Source: https://github.com/effect-ts/effect-smol/blob/main/packages/tools/bundle/README.md Use this command to analyze the bundle composition of a specific fixture file. It builds the current checkout before generating analysis artifacts. ```sh pnpm bundle-analyze scratchpad/my-fixture.ts ``` -------------------------------- ### Get Items Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md Retrieves a list of items. Supports filtering and pagination. ```APIDOC ## GET /items ### Description Returns an array of items. ### Endpoint /items ### Response #### Success Response (200) - **items** (array) - An array of item objects. - **id** (number) - The unique identifier for the item. - **name** (string) - The name of the item. #### Response Example ```json { "items": [ { "id": 1, "name": "Example Item" } ] } ``` ### Error Handling #### Bad Request (400) - **_tag** (string) - Indicates the type of error, must be "HttpApiSchemaError". - **message** (string) - A description of the error. #### Error Response Example ```json { "_tag": "HttpApiSchemaError", "message": "Invalid input provided." } ``` ``` -------------------------------- ### v3 Context.Reference with default value Source: https://github.com/effect-ts/effect-smol/blob/main/migration/services.md Example of defining a reference with a default value in Effect-TS v3. ```typescript import { Context } from "effect" class LogLevel extends Context.Reference()("LogLevel", { defaultValue: () => "info" as const }) {} ``` -------------------------------- ### ISO Codec with Class Schema Example Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/SCHEMA.md Demonstrates using the `toCodecIso` to convert a custom class schema into an `Iso` representation. This allows for serialization to and deserialization from plain objects. ```typescript import { Schema } from "effect" // Define a class schema class Person extends Schema.Class("Person")({ name: Schema.String, age: Schema.Number }) const codecIso = Schema.toCodecIso(Person) // The Iso type represents the "focus" of the schema. // For Class schemas, the Iso type is the struct representation // of the class fields: { readonly name: string; readonly age: number } // This allows you to convert between the class instance and a plain object // with the same shape, which is useful for optics and transformations. const person = new Person({ name: "John", age: 30 }) const serialized = Schema.encodeUnknownSync(codecIso)(person) console.log(serialized) // { name: 'John', age: 30 } const deserialized = Schema.decodeUnknownSync(codecIso)(serialized) console.log(deserialized) // Person { name: 'John', age: 30 } ``` -------------------------------- ### Create Exponential Backoff Schedule Source: https://github.com/effect-ts/effect-smol/blob/main/cookbooks/schedule.md Defines a schedule for exponential backoff starting at 100 milliseconds. ```typescript import { Schedule } from "effect" const retryBackoff = Schedule.exponential("100 millis") ``` -------------------------------- ### Derive and Use HTTP API Client Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md Define an API, set up a server, derive a client, and make requests. Requires providing a Fetch-based HTTP client. ```typescript import { NodeHttpServer, NodeRuntime } from "@effect/platform-node" import { Effect, Layer, Schema } from "effect" import { HttpRouter } from "effect/unstable/http" import { FetchHttpClient } from "effect/unstable/http" import { HttpApi, HttpApiBuilder, HttpApiClient, HttpApiEndpoint, HttpApiGroup } from "effect/unstable/httpapi" import { createServer } from "node:http" const Api = HttpApi.make("MyApi") .add( HttpApiGroup.make("Greetings") .add( HttpApiEndpoint.get("hello", "/", { success: Schema.String }) ) ) const GroupLive = HttpApiBuilder.group( Api, "Greetings", (handlers) => handlers.handle("hello", () => Effect.succeed("Hello, World!")) ) const ApiLive = HttpApiBuilder.layer(Api).pipe( Layer.provide(GroupLive), HttpRouter.serve, Layer.provide(NodeHttpServer.layer(createServer, { port: 3000 })) ) Layer.launch(ApiLive).pipe(NodeRuntime.runMain) // Create a program that derives and uses the client const program = Effect.gen(function*() { // Derive the client const client = yield* HttpApiClient.make(Api, { baseUrl: "http://localhost:3000" }) // Call the "hello-world" endpoint const hello = yield* client.Greetings.hello() console.log(hello) }) // Provide a Fetch-based HTTP client and run the program Effect.runFork(program.pipe(Effect.provide(FetchHttpClient.layer))) ``` -------------------------------- ### Customizing Response Description Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/HTTPAPI.md This example demonstrates how to customize the description for a successful response by annotating the success schema. ```APIDOC ## GET /users ### Description Retrieves a list of users. ### Method GET ### Endpoint /users ### Parameters ### Request Example ### Response #### Success Response (200) - **description** (array) - Returns an array of users #### Response Example { "example": [ { "id": 1, "name": "John Doe" } ] } ``` -------------------------------- ### Retry Startup Config Fetches with Exponential Backoff Source: https://github.com/effect-ts/effect-smol/blob/main/cookbooks/schedule.md Retries startup config loading for transient network or service failures using exponential backoff. Attempts at most 3 more times. ```typescript import { Effect, Schedule } from "effect" type ClientConfig = unknown type ConfigFetchError = | { readonly _tag: "NetworkUnavailable" } | { readonly _tag: "ServiceUnavailable" } | { readonly _tag: "MalformedConfig" } declare const fetchStartupConfig: Effect.Effect const isTransientConfigFailure = (error: ConfigFetchError): boolean => error._tag === "NetworkUnavailable" || error._tag === "ServiceUnavailable" const startupConfigRetryPolicy = Schedule.exponential("100 millis").pipe( Schedule.both(Schedule.recurs(3)) ) const program = fetchStartupConfig.pipe( Effect.retry({ schedule: startupConfigRetryPolicy, while: isTransientConfigFailure }) ) ``` -------------------------------- ### Schema.format Migration Source: https://github.com/effect-ts/effect-smol/blob/main/migration/schema.md The `Schema.format` API has been replaced. In v4, use `SchemaRepresentation.fromAST` to get an AST, then `SchemaRepresentation.toMultiDocument` and `SchemaRepresentation.toCodeDocument` to format it. ```typescript import { Schema } from "effect" console.log(Schema.format(Schema.String)) // string ``` ```typescript import { Schema, SchemaRepresentation } from "effect" const doc = SchemaRepresentation.fromAST(Schema.String.ast) const multi = SchemaRepresentation.toMultiDocument(doc) const codeDoc = SchemaRepresentation.toCodeDocument(multi) console.log(codeDoc.codes[0].Type) // string ``` -------------------------------- ### Create a Layer from a Toolkit with Implementations Source: https://github.com/effect-ts/effect-smol/blob/main/packages/effect/MCP.md Transforms a 'MyToolkit' into a Layer using 'McpServer.toolkit'. It then provides concrete implementations for 'DemoTool' and 'OtherDemoTool' using '.toLayer', allowing them to be merged into the MCP server. ```typescript const ToolkitLayer = McpServer.toolkit(MyToolkit).pipe( Layer.provideMerge( MyToolkit.toLayer({ DemoTool: ({ demoId, demoName }) => Effect.succeed(`Processed ${demoName} with ID ${demoId}`), OtherDemoTool: ({ value }) => Effect.succeed(`Other tool result: ${value * 2}`) }) ) ) ```