⁂ Article
Optique 0.8.0: Conditional parsing, pass-through options, and LogTape integration
We're excited to announce Optique 0.8.0! This release introduces powerful new features for building sophisticated CLI applications: the conditional() combinator for discriminated union patterns, the passThrough() parser for wrapper tools, and the new @optique/logtape package for seamless logging configuration.
Optique is a type-safe combinatorial CLI parser for TypeScript, providing a functional approach to building command-line interfaces with composable parsers and full type inference.
New conditional parsing with conditional()
Ever needed to enable different sets of options based on a discriminator value? The new conditional() combinator makes this pattern first-class. It creates discriminated unions where certain options only become valid when a specific discriminator value is selected.
import { conditional, object } from "@optique/core/constructs";
import { option } from "@optique/core/primitives";
import { choice, string } from "@optique/core/valueparser";
const parser = conditional(
option("--reporter", choice(["console", "junit", "html"])),
{
console: object({}),
junit: object({ outputFile: option("--output-file", string()) }),
html: object({ outputFile: option("--output-file", string()) }),
}
);
// Result type: ["console", {}] | ["junit", { outputFile: string }] | ...
Key features:
- Explicit discriminator option determines which branch is selected
- Tuple result
[discriminator, branchValue]for clear type narrowing - Optional default branch for when discriminator is not provided
- Clear error messages indicating which options are required for each discriminator value
The conditional() parser provides a more structured alternative to or() for discriminated union patterns. Use it when you have an explicit discriminator option that determines which set of options is valid.
See the conditional() documentation for more details and examples.
Pass-through options with passThrough()
Building wrapper CLI tools that need to forward unrecognized options to an underlying tool? The new passThrough() parser enables legitimate wrapper/proxy patterns by capturing unknown options without validation errors.
import { object } from "@optique/core/constructs";
import { option, passThrough } from "@optique/core/primitives";
const parser = object({
debug: option("--debug"),
extra: passThrough(),
});
// mycli --debug --foo=bar --baz=qux
// → { debug: true, extra: ["--foo=bar", "--baz=qux"] }
Key features:
- Three capture formats:
"equalsOnly"(default, safest),"nextToken"(captures--opt valpairs), and"greedy"(captures all remaining tokens) - Lowest priority (−10) ensures explicit parsers always match first
- Respects
--options terminator in"equalsOnly"and"nextToken"modes - Works seamlessly with
object(), subcommands, and other combinators
This feature is designed for building Docker-like CLIs, build tool wrappers, or any tool that proxies commands to another process.
See the passThrough() documentation for usage patterns and best practices.
LogTape logging integration
The new @optique/logtape package provides seamless integration with LogTape, enabling you to configure logging through command-line arguments with various parsing strategies.
# Deno
deno add --jsr @optique/logtape @logtape/logtape
# npm
npm add @optique/logtape @logtape/logtape
Quick start with the loggingOptions() preset:
import { loggingOptions, createLoggingConfig } from "@optique/logtape";
import { object } from "@optique/core/constructs";
import { parse } from "@optique/core/parser";
import { configure } from "@logtape/logtape";
const parser = object({
logging: loggingOptions({ level: "verbosity" }),
});
const args = ["-vv", "--log-output=-"];
const result = parse(parser, args);
if (result.success) {
const config = await createLoggingConfig(result.value.logging);
await configure(config);
}
The package offers multiple approaches to control log verbosity:
verbosity()parser: The classic-v/-vv/-vvvpattern where each flag increases verbosity (no flags →"warning",-v→"info",-vv→"debug",-vvv→"trace")debug()parser: Simple--debug/-dflag that toggles between normal and debug levelslogLevel()value parser: Explicit--log-level=debugoption for direct level selectionlogOutput()parser: Log output destination with-for console or file path for file output
See the LogTape integration documentation for complete examples and configuration options.
Bug fix: negative integers now accepted
Fixed an issue where the integer() value parser rejected negative integers when using type: "number". The regex pattern has been updated from /^\d+$/ to /^-?\d+$/ to correctly handle values like -42. Note that type: "bigint" already accepted negative integers, so this change brings consistency between the two types.
Installation
# Deno
deno add jsr:@optique/core
# npm
npm add @optique/core
# pnpm
pnpm add @optique/core
# Yarn
yarn add @optique/core
# Bun
bun add @optique/core
For the LogTape integration:
# Deno
deno add --jsr @optique/logtape @logtape/logtape
# npm
npm add @optique/logtape @logtape/logtape
# pnpm
pnpm add @optique/logtape @logtape/logtape
# Yarn
yarn add @optique/logtape @logtape/logtape
# Bun
bun add @optique/logtape @logtape/logtape
Looking forward
Optique 0.8.0 continues our focus on making CLI development more expressive and type-safe. The conditional() combinator brings discriminated union patterns to the forefront, passThrough() enables new wrapper tool use cases, and the LogTape integration makes logging configuration a breeze.
As always, all new features maintain full backward compatibility—your existing parsers continue to work unchanged.
We're grateful to the community for feedback and suggestions. If you have ideas for future improvements or encounter any issues, please let us know through GitHub Issues. For more information about Optique and its features, visit the documentation or check out the full changelog.
한국어:Optique 0.8.0 출시를 발표하게 되어 기쁩니다! 이번 릴리스는 정교한 CLI 애플리케이션 구축을 위한 강력한 새 기능을 소개합니다: 판별 유니온 패턴을 위한 conditional() 조합기, 래퍼 도구를 위한 passThrough() 파서, 그리고 원활한 로깅 구성을 위한 새로운 @optique/logtape 패키지가 포함되어 있습니다.
Optique는 TypeScript를 위한 타입 안전 조합형 CLI 파서로, 조합 가능한 파서와 완전한 타입 추론을 통해 명령줄 인터페이스를 구축하는 함수형 접근 방식을 제공합니다.
conditional()을 이용한 새로운 조건부 파싱
판별자 값에 따라 다른 옵션 세트를 활성화해야 할 필요가 있었나요? 새로운 conditional() 조합기는 이 패턴을 일급 객체로 만듭니다. 특정 판별자 값이 선택되었을 때만 특정 옵션이 유효해지는 판별 유니온을 생성합니다.
import { conditional, object } from "@optique/core/constructs";
import { option } from "@optique/core/primitives";
import { choice, string } from "@optique/core/valueparser";
const parser = conditional(
option("--reporter", choice(["console", "junit", "html"])),
{
console: object({}),
junit: object({ outputFile: option("--output-file", string()) }),
html: object({ outputFile: option("--output-file", string()) }),
}
);
// Result type: ["console", {}] | ["junit", { outputFile: string }] | ...
주요 기능:
- 명시적 판별자 옵션이 어떤 분기가 선택될지 결정
- 명확한 타입 좁히기를 위한 튜플 결과
[discriminator, branchValue] - 판별자가 제공되지 않을 때를 위한 선택적 기본 분기
- 각 판별자 값에 필요한 옵션을 명확히 표시하는 오류 메시지
conditional() 파서는 판별 유니온 패턴에 대한 or()의 더 구조화된 대안을 제공합니다. 어떤 옵션 세트가 유효한지 결정하는 명시적 판별자 옵션이 있을 때 사용하세요.
자세한 내용과 예제는 conditional() 문서를 참조하세요.
passThrough()를 이용한 패스스루 옵션
인식되지 않은 옵션을 기본 도구로 전달해야 하는 래퍼 CLI 도구를 구축하고 계신가요? 새로운 passThrough() 파서는 검증 오류 없이 알 수 없는 옵션을 캡처하여 정당한 래퍼/프록시 패턴을 가능하게 합니다.
import { object } from "@optique/core/constructs";
import { option, passThrough } from "@optique/core/primitives";
const parser = object({
debug: option("--debug"),
extra: passThrough(),
});
// mycli --debug --foo=bar --baz=qux
// → { debug: true, extra: ["--foo=bar", "--baz=qux"] }
주요 기능:
- 세 가지 캡처 형식:
"equalsOnly"(기본값, 가장 안전),"nextToken"(--opt val쌍 캡처),"greedy"(남은 모든 토큰 캡처) - 가장 낮은 우선순위(-10)로 명시적 파서가 항상 먼저 일치하도록 보장
"equalsOnly"와"nextToken"모드에서--옵션 종결자 존중object(), 서브커맨드 및 기타 조합기와 원활하게 작동
이 기능은 Docker와 같은 CLI, 빌드 도구 래퍼 또는 다른 프로세스에 명령을 프록시하는 모든 도구를 구축하기 위해 설계되었습니다.
사용 패턴과 모범 사례는 passThrough() 문서를 참조하세요.
LogTape 로깅 통합
새로운 @optique/logtape 패키지는 LogTape와의 원활한 통합을 제공하여 다양한 파싱 전략을 통해 명령줄 인수로 로깅을 구성할 수 있게 합니다.
# Deno
deno add --jsr @optique/logtape @logtape/logtape
# npm
npm add @optique/logtape @logtape/logtape
loggingOptions() 프리셋으로 빠르게 시작하기:
import { loggingOptions, createLoggingConfig } from "@optique/logtape";
import { object } from "@optique/core/constructs";
import { parse } from "@optique/core/parser";
import { configure } from "@logtape/logtape";
const parser = object({
logging: loggingOptions({ level: "verbosity" }),
});
const args = ["-vv", "--log-output=-"];
const result = parse(parser, args);
if (result.success) {
const config = await createLoggingConfig(result.value.logging);
await configure(config);
}
이 패키지는 로그 상세도를 제어하기 위한 여러 접근 방식을 제공합니다:
verbosity()파서: 각 플래그가 상세도를 높이는 고전적인-v/-vv/-vvv패턴 (플래그 없음 →"warning",-v→"info",-vv→"debug",-vvv→"trace")debug()파서: 일반 레벨과 디버그 레벨 사이를 전환하는 간단한--debug/-d플래그logLevel()값 파서: 직접 레벨 선택을 위한 명시적--log-level=debug옵션logOutput()파서: 콘솔을 위한-또는 파일 출력을 위한 파일 경로로 로그 출력 대상 지정
전체 예제와 구성 옵션은 LogTape 통합 문서를 참조하세요.
버그 수정: 음수 정수 이제 허용
type: "number"를 사용할 때 integer() 값 파서가 음수 정수를 거부하는 문제를 수정했습니다. 정규식 패턴이 /^\d+$/에서 /^-?\d+$/로 업데이트되어 -42와 같은 값을 올바르게 처리합니다. type: "bigint"는 이미 음수 정수를 허용했으므로, 이 변경으로 두 타입 간의 일관성이 확보되었습니다.
설치
# Deno
deno add jsr:@optique/core
# npm
npm add @optique/core
# pnpm
pnpm add @optique/core
# Yarn
yarn add @optique/core
# Bun
bun add @optique/core
LogTape 통합을 위한 설치:
# Deno
deno add --jsr @optique/logtape @logtape/logtape
# npm
npm add @optique/logtape @logtape/logtape
# pnpm
pnpm add @optique/logtape @logtape/logtape
# Yarn
yarn add @optique/logtape @logtape/logtape
# Bun
bun add @optique/logtape @logtape/logtape
앞으로의 계획
Optique 0.8.0은 CLI 개발을 더 표현력 있고 타입 안전하게 만드는 데 계속 초점을 맞추고 있습니다. conditional() 조합기는 판별 유니온 패턴을 전면에 내세우고, passThrough()는 새로운 래퍼 도구 사용 사례를 가능하게 하며, LogTape 통합은 로깅 구성을 간편하게 만듭니다.
항상 그렇듯이, 모든 새로운 기능은 완전한 하위 호환성을 유지합니다—기존 파서는 변경 없이 계속 작동합니다.
피드백과 제안을 해주신 커뮤니티에 감사드립니다. 향후 개선 사항에 대한 아이디어가 있거나 문제가 발생하면 GitHub Issues를 통해 알려주세요. Optique와 그 기능에 대한 자세한 정보는 문서를 방문하거나 전체 변경 로그를 확인하세요.
한국어(대한민국):Optique 0.8.0 출시를 발표하게 되어 기쁩니다! 이번 릴리스는 정교한 CLI 애플리케이션을 구축하기 위한 강력한 새 기능을 소개합니다: 판별 유니온 패턴을 위한 conditional() 조합기, 래퍼 도구를 위한 passThrough() 파서, 그리고 원활한 로깅 구성을 위한 새로운 @optique/logtape 패키지가 포함되어 있습니다.
Optique는 TypeScript를 위한 타입 안전 조합형 CLI 파서로, 조합 가능한 파서와 완전한 타입 추론을 통해 명령줄 인터페이스를 구축하는 함수형 접근 방식을 제공합니다.
conditional()을 이용한 새로운 조건부 파싱
판별자 값에 따라 다른 옵션 세트를 활성화해야 할 필요가 있었나요? 새로운 conditional() 조합기는 이 패턴을 일급 객체로 만듭니다. 특정 판별자 값이 선택되었을 때만 특정 옵션이 유효해지는 판별 유니온을 생성합니다.
import { conditional, object } from "@optique/core/constructs";
import { option } from "@optique/core/primitives";
import { choice, string } from "@optique/core/valueparser";
const parser = conditional(
option("--reporter", choice(["console", "junit", "html"])),
{
console: object({}),
junit: object({ outputFile: option("--output-file", string()) }),
html: object({ outputFile: option("--output-file", string()) }),
}
);
// Result type: ["console", {}] | ["junit", { outputFile: string }] | ...
주요 기능:
- 명시적 판별자 옵션이 어떤 분기가 선택될지 결정
- 명확한 타입 좁히기를 위한 튜플 결과
[discriminator, branchValue] - 판별자가 제공되지 않을 때를 위한 선택적 기본 분기
- 각 판별자 값에 필요한 옵션을 명확히 표시하는 오류 메시지
conditional() 파서는 판별 유니온 패턴에 대한 or()의 더 구조화된 대안을 제공합니다. 어떤 옵션 세트가 유효한지 결정하는 명시적 판별자 옵션이 있을 때 사용하세요.
자세한 내용과 예제는 conditional() 문서를 참조하세요.
passThrough()를 이용한 패스스루 옵션
인식되지 않은 옵션을 기본 도구로 전달해야 하는 래퍼 CLI 도구를 구축하고 계신가요? 새로운 passThrough() 파서는 유효성 검사 오류 없이 알 수 없는 옵션을 캡처하여 정당한 래퍼/프록시 패턴을 가능하게 합니다.
import { object } from "@optique/core/constructs";
import { option, passThrough } from "@optique/core/primitives";
const parser = object({
debug: option("--debug"),
extra: passThrough(),
});
// mycli --debug --foo=bar --baz=qux
// → { debug: true, extra: ["--foo=bar", "--baz=qux"] }
주요 기능:
- 세 가지 캡처 형식:
"equalsOnly"(기본값, 가장 안전),"nextToken"(--opt val쌍 캡처),"greedy"(남은 모든 토큰 캡처) - 가장 낮은 우선순위(-10)로 명시적 파서가 항상 먼저 일치하도록 보장
"equalsOnly"와"nextToken"모드에서--옵션 종결자 존중object(), 서브커맨드 및 기타 조합기와 원활하게 작동
이 기능은 Docker와 같은 CLI, 빌드 도구 래퍼 또는 명령을 다른 프로세스로 프록시하는 모든 도구를 구축하기 위해 설계되었습니다.
사용 패턴과 모범 사례는 passThrough() 문서를 참조하세요.
LogTape 로깅 통합
새로운 @optique/logtape 패키지는 LogTape와의 원활한 통합을 제공하여 다양한 파싱 전략을 통해 명령줄 인수로 로깅을 구성할 수 있게 합니다.
# Deno
deno add --jsr @optique/logtape @logtape/logtape
# npm
npm add @optique/logtape @logtape/logtape
loggingOptions() 프리셋을 사용한 빠른 시작:
import { loggingOptions, createLoggingConfig } from "@optique/logtape";
import { object } from "@optique/core/constructs";
import { parse } from "@optique/core/parser";
import { configure } from "@logtape/logtape";
const parser = object({
logging: loggingOptions({ level: "verbosity" }),
});
const args = ["-vv", "--log-output=-"];
const result = parse(parser, args);
if (result.success) {
const config = await createLoggingConfig(result.value.logging);
await configure(config);
}
이 패키지는 로그 상세 수준을 제어하기 위한 여러 접근 방식을 제공합니다:
verbosity()파서: 각 플래그가 상세 수준을 높이는 고전적인-v/-vv/-vvv패턴 (플래그 없음 →"warning",-v→"info",-vv→"debug",-vvv→"trace")debug()파서: 일반 수준과 디버그 수준 사이를 전환하는 간단한--debug/-d플래그logLevel()값 파서: 직접적인 수준 선택을 위한 명시적--log-level=debug옵션logOutput()파서: 콘솔을 위한-또는 파일 출력을 위한 파일 경로의 로그 출력 대상
전체 예제와 구성 옵션은 LogTape 통합 문서를 참조하세요.
버그 수정: 음수 정수 이제 허용
type: "number"를 사용할 때 integer() 값 파서가 음수 정수를 거부하는 문제가 수정되었습니다. 정규식 패턴이 /^\d+$/에서 /^-?\d+$/로 업데이트되어 -42와 같은 값을 올바르게 처리합니다. type: "bigint"는 이미 음수 정수를 허용했으므로, 이 변경으로 두 타입 간의 일관성이 유지됩니다.
설치
# Deno
deno add jsr:@optique/core
# npm
npm add @optique/core
# pnpm
pnpm add @optique/core
# Yarn
yarn add @optique/core
# Bun
bun add @optique/core
LogTape 통합을 위한 설치:
# Deno
deno add --jsr @optique/logtape @logtape/logtape
# npm
npm add @optique/logtape @logtape/logtape
# pnpm
pnpm add @optique/logtape @logtape/logtape
# Yarn
yarn add @optique/logtape @logtape/logtape
# Bun
bun add @optique/logtape @logtape/logtape
앞으로의 계획
Optique 0.8.0은 CLI 개발을 더 표현력 있고 타입 안전하게 만드는 데 계속 집중하고 있습니다. conditional() 조합기는 판별 유니온 패턴을 전면에 내세우고, passThrough()는 새로운 래퍼 도구 사용 사례를 가능하게 하며, LogTape 통합은 로깅 구성을 쉽게 만듭니다.
항상 그렇듯이, 모든 새로운 기능은 완전한 하위 호환성을 유지합니다—기존 파서는 변경 없이 계속 작동합니다.
피드백과 제안을 해주신 커뮤니티에 감사드립니다. 향후 개선 사항에 대한 아이디어가 있거나 문제가 발생하면 GitHub Issues를 통해 알려주세요. Optique와 그 기능에 대한 자세한 정보는 문서를 방문하거나 전체 변경 로그를 확인하세요.