Skip to content

Instantly share code, notes, and snippets.

@moatorres
Created May 6, 2025 13:30
Show Gist options
  • Save moatorres/7d40ca3dc4ade2c5be7862dbf870860f to your computer and use it in GitHub Desktop.
Save moatorres/7d40ca3dc4ade2c5be7862dbf870860f to your computer and use it in GitHub Desktop.
Effect CLI
import { join } from 'path'
import { error, info, warn } from '@blog/utils'
import { Args, Command, Options } from '@effect/cli'
import { NodeContext, NodeRuntime } from '@effect/platform-node'
import { Console, Effect, Option, pipe } from 'effect'
const root = Args.text({ name: 'root' }).pipe(
Args.withDescription('Path to the project root directory')
)
const file = Options.text('file').pipe(
Options.withAlias('f'),
Options.withDefault('./config.json'),
Options.withDescription('Path to the configuration file')
)
const content = Options.text('content').pipe(
Options.withAlias('c'),
Options.withDefault('src/content'),
Options.withDescription('Path to the configuration file')
)
const photos = Options.text('photos').pipe(
Options.optional,
Options.withAlias('p'),
Options.withDefault(Option.some('public/images')),
Options.withDescription('Path to the photos directory')
)
const blogx = Command.make('blogx', { root, file, content, photos }, (o) => {
// these will be printed
info('Root -', o.root)
info('Config -', join(o.root ? o.root : process.cwd(), o.file))
info('Content -', join(o.root ? o.root : process.cwd(), o.content))
// this will not be printed
Console.log('Add .pipe(NodeRuntime.runMain) to print this.')
// example using pipe
pipe(
Effect.succeed(o.photos),
Effect.map((photos) => {
if (Option.isNone(photos)) {
return warn('No photos directory, using default')
}
return info(`${join(process.cwd(), photos.toString())}`)
}),
Effect.catchAll((e) => {
error('Error:', e)
return Effect.succeed(0)
})
)
// example using option match
Option.match(o.photos, {
onNone: () => Effect.succeed(warn('No photos directory, using default')),
onSome: (file) => Effect.succeed(info(`${join(process.cwd(), file)}`)),
}).pipe(NodeRuntime.runMain)
// example using generator
Effect.gen(function* () {
yield* Effect.succeed(
Option.isNone(o.photos) ? info('Photos ✅') : warn('Photos ❌')
)
yield* Effect.fail(new Error('Effect.fail works like a throw here'))
yield* Console.log('I will never run because the previous effect failed')
}).pipe(NodeRuntime.runMain)
// this will not be printed
error('The previous failure bubbles up, so this will also not be printed')
// exit
return Effect.exit(Effect.succeed(0))
})
const cli = Command.run(blogx, {
name: 'blogx cli',
version: 'v0.0.1',
})
// pnpm exec -- tsx src/lib/cli.ts -c root/example/path -f apps/blog/info.json root
cli(process.argv).pipe(Effect.provide(NodeContext.layer), NodeRuntime.runMain)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment