Effect-TS / effect

An ecosystem of tools to build robust applications in TypeScript
https://effect.website
MIT License
7.74k stars 246 forks source link

@effect/cli options that handles Schema #3782

Closed joepjoosten closed 1 month ago

joepjoosten commented 1 month ago

What is the problem this feature would solve?

If you add a options constructor for schema's you leverage the power of schema's, to encode a string options into anything schema supports:

Simple example:

import { Command, HelpDoc, Options, ValidationError } from "@effect/cli"
import { NodeContext, NodeRuntime } from "@effect/platform-node"
import { Schema } from "@effect/schema"
import { Console, Effect, pipe } from "effect"

export const validateWithSchema = <A, I>(schema: Schema.Schema<A, I>) =>
  Options.mapEffect((x: A) =>
    pipe(
      Schema.encode(schema)(x),
      Effect.mapError((e) => ValidationError.invalidValue(HelpDoc.p(e.message)))
    )
  )

const schemaOption = Options.integer("option1").pipe(validateWithSchema(Schema.Int.pipe(Schema.clamp(1, 10))))

const run = Command.make("example", { schemaOption }, (opts) => Console.log(opts)).pipe(
  Command.run({
    name: "Test",
    version: "1.0.0"
  })
)

const main = Effect.suspend(() => run(globalThis.process.argv))

main.pipe(
  Effect.provide(NodeContext.layer),
  Effect.tapErrorCause(Effect.logError),
  NodeRuntime.runMain
)

What is the feature you are proposing to solve the problem?

You get the build in functions that schema supports.

I know this would can create a coupling between @effect/cli and @effect/schema, but isn't @effect/schema becoming a de-facto standard package (like effect itself) for all other packages?

What alternatives have you considered?

Creating my own set of option validators...

tim-smart commented 1 month ago

There is Options.withSchema: https://effect-ts.github.io/effect/cli/Options.ts.html#withschema

What was your suggestion?

joepjoosten commented 1 month ago

Ah, yes! Thank you. It was also due to my misinterpretation of clamp why i couldn't get an error when a number outside the range was not throwing an error. I need Schema.between ...

Sorry about that!

Thank you!