Skip to content

Commit c8143f9

Browse files
committed
added cli
1 parent 79f8b69 commit c8143f9

File tree

4 files changed

+104
-1
lines changed

4 files changed

+104
-1
lines changed

packages/effect-http/package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,13 @@
4141
},
4242
"devDependencies": {
4343
"@apidevtools/swagger-parser": "^10.1.0",
44+
"@effect/cli": "^0.36.62",
4445
"@effect/platform": "^0.58.4",
46+
"@effect/platform-node": "^0.53.3",
4547
"@effect/schema": "^0.68.6",
46-
"effect": "^3.4.0"
48+
"effect": "^3.4.0",
49+
"effect-http-node": "^0.15.3",
50+
"effect-log": "^0.31.5",
51+
"importx": "^0.3.7"
4752
}
4853
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { Data } from "effect";
2+
import { Api } from "effect-http";
3+
4+
export class CliConfig extends Data.TaggedClass("CliConfig")<{
5+
api: Api.Api.Any,
6+
server?: Partial<{
7+
port: number
8+
}>
9+
}> {}

packages/effect-http/src/bin.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { Command, Options } from "@effect/cli";
2+
import { NodeContext, NodeRuntime } from "@effect/platform-node";
3+
import * as Path from "@effect/platform/Path";
4+
import { Data, Effect, Option } from "effect";
5+
import { NodeServer } from "effect-http-node";
6+
import * as PrettyLogger from "effect-log/PrettyLogger";
7+
import * as importx from "importx";
8+
import pkg from "../package.json";
9+
import * as CliConfig from "./CliConfig.js";
10+
import * as ExampleServer from "./ExampleServer.js";
11+
import * as RouterBuilder from "./RouterBuilder.js";
12+
13+
14+
/**
15+
* An error that occurs when loading the config file.
16+
*/
17+
class ConfigError extends Data.TaggedError("ConfigError")<{
18+
message: string;
19+
}> {}
20+
21+
const configArg = Options.file("config").pipe(
22+
Options.withAlias("c"),
23+
Options.withDescription("Path to the config file"),
24+
Options.withDefault("./effect-http.config.ts"),
25+
);
26+
27+
const portArg = Options.integer("port").pipe(
28+
Options.withAlias("p"),
29+
Options.withDescription("Port to run the server on"),
30+
Options.optional
31+
);
32+
33+
const loadConfig = (relativePath: string) =>
34+
Effect.flatMap(Path.Path, (path) =>
35+
Effect.tryPromise(() =>
36+
importx.import(path.join(process.cwd(), relativePath), import.meta.url),
37+
).pipe(
38+
Effect.mapError(
39+
() => new ConfigError({ message: `Failed to find config at ${path}` }),
40+
),
41+
Effect.flatMap((module) =>
42+
module?.default
43+
? Effect.succeed(module.default)
44+
: new ConfigError({ message: `No default export found in ${path}` }),
45+
),
46+
Effect.flatMap((defaultExport) =>
47+
defaultExport instanceof CliConfig.CliConfig
48+
? Effect.succeed(defaultExport)
49+
: new ConfigError({ message: `Invalid config found in ${path}` }),
50+
),
51+
Effect.withSpan("loadConfig", { attributes: { path } })
52+
),
53+
);
54+
55+
const command = Command.make("serve", { config: configArg, port: portArg }, (args) =>
56+
Effect.gen(function* () {
57+
const config = yield* loadConfig(args.config);
58+
const port = Option.getOrUndefined(args.port) ?? config.server?.port ?? 11779;
59+
yield* ExampleServer.make(config.api).pipe(RouterBuilder.buildPartial, NodeServer.listen({ port }))
60+
}),
61+
);
62+
63+
const cli = Command.run(command, {
64+
name: "Effect Http Cli",
65+
version: `v${pkg.version}`,
66+
});
67+
68+
cli(process.argv).pipe(
69+
Effect.provide(NodeContext.layer),
70+
Effect.provide(PrettyLogger.layer({ showFiberId: false })),
71+
NodeRuntime.runMain,
72+
);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { Schema } from "@effect/schema";
2+
import { pipe } from "effect";
3+
import * as Api from "./Api.js";
4+
import { CliConfig } from "./CliConfig.js";
5+
6+
const api = pipe(
7+
Api.make({ title: "Users API" }),
8+
Api.addEndpoint(
9+
Api.get("getUser", "/user").pipe(
10+
Api.setResponseBody(Schema.Number),
11+
)
12+
)
13+
)
14+
15+
export default new CliConfig({
16+
api,
17+
})

0 commit comments

Comments
 (0)