Optique 0.4.0:更好的說明文字、豐富文件和 Temporal 支援

洪 民憙 (Hong Minhee) @hongminhee@hackers.pub

我們很高興宣布 Optique 0.4.0 版本發布,此版本帶來了說明文字組織的重大改進、增強的文件功能,並引入了全面的 Temporal API 支援。

Optique 是一個為 TypeScript 設計的類型安全組合式 CLI 解析器,讓建立命令列介面變得直覺且易於維護。這次的發布專注於使您的 CLI 應用程式更加用戶友好和易於維護。

更好的說明文字組織

Optique 0.4.0 中最明顯的改進之一是增強的說明文字組織。您現在可以更有效地標記和分組您的選項,使複雜的 CLI 對用戶來說更加易於理解。

標記合併群組

merge() 組合器現在接受一個可選的標籤參數,解決了開發者必須在乾淨的程式碼結構和有組織的說明輸出之間做選擇的常見痛點:

// 之前:未標記的合併選項顯得分散
const config = merge(connectionOptions, performanceOptions);

// 現在:在清晰的區段下分組相關選項
const config = merge(
  "Server Configuration",  // 新的標籤參數
  connectionOptions,
  performanceOptions
);

這個簡單的添加對說明文字的可讀性產生了巨大的差異,特別是對於那些選項分散在多個可重用模組中的 CLI。

產生的說明輸出清晰地將選項組織在 Server Configuration 區段下:

Demo app showcasing labeled merge groups
Usage: [1mdemo-merge.ts[0m [3m--host[0m [4m[2mSTRING[0m [3m--port[0m [4m[2mINTEGER[0m [3m--timeout[0m [4m[2mINTEGER[0m [3m--retries[0m
       [4m[2mINTEGER[0m

Server Configuration:
  [3m--host[0m [4m[2mSTRING[0m               Server hostname or IP address
  [3m--port[0m [4m[2mINTEGER[0m              Port number for the connection
  [3m--timeout[0m [4m[2mINTEGER[0m           Connection timeout in seconds
  [3m--retries[0m [4m[2mINTEGER[0m           Number of retry attempts

新的 group() 組合器

對於 merge() 不適用的情況,新的 group() 組合器讓您可以用文件標籤包裝任何解析器:

// 在清晰的區段下分組互斥選項
const outputFormat = group(
  "Output Format",
  or(
    map(flag("--json"), () => "json"),
    map(flag("--yaml"), () => "yaml"),
    map(flag("--xml"), () => "xml"),
  )
);

這對於組織互斥的標誌、多個輸入或任何原生不支援標記的解析器特別有用。產生的說明文字變得更加易於瀏覽和用戶友好。

以下是分組的輸出格式選項在說明文字中的顯示方式:

Demo app showcasing group combinator
Usage: [1mdemo-group.ts[0m [3m--json[0m
       [1mdemo-group.ts[0m [3m--yaml[0m
       [1mdemo-group.ts[0m [3m--xml[0m

Output Format:
  [3m--json[0m                      Output in JSON format
  [3m--yaml[0m                      Output in YAML format
  [3m--xml[0m                       Output in XML format

豐富的文件支援

Optique 0.4.0 引入了全面的文件欄位,可以直接通過 run() 函數添加,消除了為文件目的而修改解析器定義的需求。

簡短描述、詳細說明和頁腳

@optique/core/facade@optique/run 現在都通過 run() 函數支援 briefdescriptionfooter 選項:

import { run } from "@optique/run";
import { message } from "@optique/core/message";

const result = run(parser, {
  brief: message`A powerful data processing tool`,
  description: message`This tool provides comprehensive data processing capabilities with support for multiple formats and transformations. It can handle JSON, YAML, and CSV files with automatic format detection.`,
  footer: message`Examples:
  myapp process data.json --format yaml
  myapp validate config.toml --strict

For more information, visit https://example.com/docs`,
  help: "option"
});

這些文件欄位會出現在說明輸出和錯誤訊息中(當配置時),在您的 CLI 的用戶體驗中提供一致的上下文。

完整的說明輸出展示了豐富的文件功能,包括簡短描述、詳細說明、選項描述、預設值和頁腳信息:

A powerful data processing tool
Usage: [1mdemo-rich-docs.ts[0m [2m[[0m[3m--port[0m [4m[2mINTEGER[0m[2m][0m [2m[[0m[3m--format[0m [4m[2mSTRING[0m[2m][0m [3m--verbose[0m [4m[2mSTRING[0m

This tool provides comprehensive data processing capabilities with support for
multiple formats and transformations. It can handle JSON, YAML, and CSV files
with automatic format detection.

  [3m--port[0m [4m[2mINTEGER[0m              Server port number[2m [3000][0m
  [3m--format[0m [4m[2mSTRING[0m             Output format[2m [json][0m
  [3m--verbose[0m [4m[2mSTRING[0m            Verbosity level

Examples:
  myapp process data.json --format yaml
  myapp validate config.toml --strict

For more information, visit https://example.com/docs

這些文件欄位會出現在說明輸出和錯誤訊息中(當配置時),在您的 CLI 的用戶體驗中提供一致的上下文。

顯示預設值

一個經常被要求的功能現在可用了:在說明文字中直接顯示預設值。使用 withDefault() 時,通過新的 showDefault 選項啟用此功能:

const parser = object({
  port: withDefault(
    option("--port", integer(), { description: message`Server port number` }),
    3000,
  ),
  format: withDefault(
    option("--format", string(), { description: message`Output format` }),
    "json",
  ),
});

run(parser, { showDefault: true });

// 或使用自定義格式:
run(parser, {
  showDefault: {
    prefix: " (default: ",
    suffix: ")"
  }  // 顯示:--port (default: 3000)
});

當啟用顏色時,預設值會自動變暗,使其在視覺上與眾不同,同時保持可讀性。

說明輸出清楚地在每個選項旁邊標記預設值:

Usage: [1mdemo-defaults.ts[0m [2m[[0m[3m--port[0m [4m[2mINTEGER[0m[2m][0m [2m[[0m[3m--format[0m [4m[2mSTRING[0m[2m][0m

  [3m--port[0m [4m[2mINTEGER[0m              Server port number[2m [3000][0m
  [3m--format[0m [4m[2mSTRING[0m             Output format[2m [json][0m

Temporal API 支援

Optique 0.4.0 引入了一個新的套件,@optique/temporal,為現代 Temporal API 提供全面支援。這帶來了日期、時間、持續時間和時區的類型安全解析:

import { instant, duration, zonedDateTime } from "@optique/temporal";
import { option } from "@optique/core/parser";

const parser = object({
  // 解析 ISO 8601 時間戳
  timestamp: option("--at", instant()),

  // 解析持續時間,如 "PT30M" 或 "P1DT2H"
  timeout: option("--timeout", duration()),

  // 解析帶時區信息的日期時間
  meeting: option("--meeting", zonedDateTime()),
});

時間解析器返回具有完整功能的原生 Temporal 物件:

const result = parse(timestampArg, ["2023-12-25T10:30:00Z"]);
if (result.success) {
  const instant = result.value;
  console.log(`UTC: ${instant.toString()}`);
  console.log(`Seoul: ${instant.toZonedDateTimeISO("Asia/Seoul")}`);
}

使用以下命令安裝新套件:

npm add @optique/temporal

改進的類型推斷

merge() 組合器現在支援最多 10 個解析器(之前為 5 個),而 tuple() 解析器使用 TypeScript 的 const 類型參數改進了類型推斷。這些增強功能使更複雜的 CLI 結構成為可能,同時保持完美的類型安全。

破壞性變更

雖然我們為大多數 API 保持了向後兼容性,但有一些變更需要注意:

  • Parser.getDocFragments() 方法現在使用 DocState<TState> 而不是直接的狀態值(僅影響自定義解析器實現)
  • merge() 組合器現在在編譯時強制執行更嚴格的類型約束,拒絕非物件產生的解析器

了解更多

有關變更、錯誤修復和改進的完整列表,請參閱完整變更日誌

查看更新的文件:

安裝

升級到 Optique 0.4.0:

npm update @optique/core @optique/run
# 或
deno add jsr:@optique/core@^0.4.0 jsr:@optique/run@^0.4.0

添加時間支援(可選):

npm add @optique/temporal
# 或
deno add jsr:@optique/temporal

我們希望這些改進能讓使用 Optique 構建 CLI 應用程式變得更加愉快。一如既往,我們歡迎您在 GitHub 上提供反饋和貢獻。

1

No comments

If you have a fediverse account, you can comment on this article from your own instance. Search https://hackers.pub/ap/articles/01991aa2-edea-797e-aad6-2f1ece168909 on your instance and reply to it.