{"id":30180961,"url":"https://github.com/streamich/json-type-cli","last_synced_at":"2025-08-12T08:06:36.544Z","repository":{"id":306592436,"uuid":"869169879","full_name":"streamich/json-type-cli","owner":"streamich","description":"...","archived":false,"fork":false,"pushed_at":"2025-08-07T15:15:44.000Z","size":4445,"stargazers_count":1,"open_issues_count":4,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-07T17:28:13.710Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/streamich.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"github":"streamich"}},"created_at":"2024-10-07T20:49:03.000Z","updated_at":"2025-07-29T22:58:55.000Z","dependencies_parsed_at":"2025-07-26T17:53:47.096Z","dependency_job_id":"cae60f72-52a0-43fb-8b54-856a5f3f81f3","html_url":"https://github.com/streamich/json-type-cli","commit_stats":null,"previous_names":["streamich/json-type-cli"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/streamich/json-type-cli","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/streamich%2Fjson-type-cli","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/streamich%2Fjson-type-cli/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/streamich%2Fjson-type-cli/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/streamich%2Fjson-type-cli/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/streamich","download_url":"https://codeload.github.com/streamich/json-type-cli/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/streamich%2Fjson-type-cli/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":270024697,"owners_count":24514054,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-12T02:00:09.011Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-08-12T08:06:18.024Z","updated_at":"2025-08-12T08:06:36.530Z","avatar_url":"https://github.com/streamich.png","language":"TypeScript","funding_links":["https://github.com/sponsors/streamich"],"categories":[],"sub_categories":[],"readme":"# JSON Type CLI\n\nJSON Type CLI is a powerful Node.js package for building command-line interface (CLI) utilities that implement the JSON Rx RPC protocol. It uses JSON as the primary data format and provides request/response communication pattern where each CLI interaction is a request that produces a response.\n\n## Overview\n\nThis package enables you to build type-safe CLI tools where:\n- Each CLI command is a **method** with typed input/output schemas\n- Input data forms the **request** payload (following JSON Rx RPC)\n- Output data is the **response** payload \n- Multiple input sources can be composed together\n- Multiple output formats are supported (JSON, CBOR, MessagePack, etc.)\n\nThe library implements the **JSON Rx RPC protocol**, where each CLI interaction follows the request/response pattern. You define methods with typed schemas using the JSON Type system, and the CLI handles parsing, validation, method calling, and response formatting automatically.\n\n## Quick Start\n\n### Installation\n\n```bash\nnpm install json-type-cli\n```\n\n### Basic Usage\n\n```typescript\nimport { createCli } from 'json-type-cli';\nimport { ObjectValue } from '@jsonjoy.com/json-type/lib/value/ObjectValue';\n\n// Create a router with your methods\nconst router = ObjectValue.create()\n  .prop('greet', \n    t.Function(\n      t.Object(t.prop('name', t.str)),  // Request schema\n      t.Object(t.prop('message', t.str)) // Response schema\n    ).options({\n      title: 'Greet a person',\n      description: 'Returns a greeting message for the given name'\n    }),\n    async ({ name }) =\u003e ({ \n      message: `Hello, ${name}!` \n    })\n  );\n\n// Create and run CLI\nconst cli = createCli({\n  router,\n  version: 'v1.0.0',\n  cmd: 'my-cli'\n});\n\ncli.run();\n```\n\nSave this as `my-cli.js` and run:\n\n```bash\nnode my-cli.js greet '{\"name\": \"World\"}'\n# Output: {\"message\": \"Hello, World!\"}\n\nnode my-cli.js greet --str/name=Alice  \n# Output: {\"message\": \"Hello, Alice!\"}\n```\n\n## JSON Rx RPC Protocol Implementation\n\nThis CLI tool implements the JSON Rx RPC protocol with the following characteristics:\n\n### Request/Response Pattern\n- Each CLI command is a **method call** in JSON Rx RPC terms\n- The method name is the first positional argument: `my-cli \u003cmethod\u003e ...`\n- Request data is composed from multiple sources (see [Input Sources](#input-sources))\n- Response data is returned to STDOUT in the specified format\n\n### JSON Rx RPC Message Flow\n1. **Request Composition**: CLI parses arguments and builds request payload\n2. **Method Invocation**: Calls the specified method with the request data\n3. **Response Generation**: Method returns response payload  \n4. **Response Encoding**: Encodes response in the specified format (JSON, CBOR, etc.)\n\nThis follows the JSON Rx RPC **Request Complete** message pattern where the client (CLI) sends a complete request and receives a complete response.\n\n## Building CLI Tools\n\n### Defining Methods\n\nMethods are defined using the JSON Type system and added to a router:\n\n```typescript\nimport { createCli } from 'json-type-cli';\nimport { ObjectValue } from '@jsonjoy.com/json-type/lib/value/ObjectValue';\n\nconst router = ObjectValue.create();\nconst { t } = router;\n\n// Simple echo method\nrouter.prop('echo', \n  t.Function(t.any, t.any).options({\n    title: 'Echo input',\n    description: 'Returns the input unchanged'\n  }),\n  async (input) =\u003e input\n);\n\n// Math operations\nrouter.prop('math.add',\n  t.Function(\n    t.Object(\n      t.prop('a', t.num),\n      t.prop('b', t.num)\n    ),\n    t.Object(t.prop('result', t.num))\n  ).options({\n    title: 'Add two numbers',\n    description: 'Adds two numbers and returns the result'\n  }),\n  async ({ a, b }) =\u003e ({ result: a + b })\n);\n\n// File processing\nrouter.prop('file.process',\n  t.Function(\n    t.Object(\n      t.prop('filename', t.str),\n      t.propOpt('encoding', t.str)\n    ),\n    t.Object(\n      t.prop('size', t.num),\n      t.prop('content', t.str)\n    )\n  ).options({\n    title: 'Process a file',\n    description: 'Reads and processes a file'\n  }),\n  async ({ filename, encoding = 'utf8' }) =\u003e {\n    const fs = require('fs');\n    const content = fs.readFileSync(filename, encoding);\n    return {\n      size: content.length,\n      content: content\n    };\n  }\n);\n```\n\n### Organizing Routes\n\nFor larger applications, organize routes into modules:\n\n```typescript\n// routes/user.ts\nexport const defineUserRoutes = \u003cRoutes extends ObjectType\u003cany\u003e\u003e(r: ObjectValue\u003cRoutes\u003e) =\u003e {\n  return r.extend((t, r) =\u003e [\n    r('user.create',\n      t.Function(\n        t.Object(\n          t.prop('name', t.str),\n          t.prop('email', t.str)\n        ),\n        t.Object(\n          t.prop('id', t.str),\n          t.prop('name', t.str),\n          t.prop('email', t.str)\n        )\n      ).options({\n        title: 'Create a user',\n        description: 'Creates a new user account'\n      }),\n      async ({ name, email }) =\u003e ({\n        id: generateId(),\n        name,\n        email\n      })\n    ),\n\n    r('user.get',\n      t.Function(\n        t.Object(t.prop('id', t.str)),\n        t.Object(\n          t.prop('id', t.str),\n          t.prop('name', t.str),\n          t.prop('email', t.str)\n        )\n      ).options({\n        title: 'Get user by ID',\n        description: 'Retrieves user information by ID'\n      }),\n      async ({ id }) =\u003e getUserById(id)\n    )\n  ]);\n};\n\n// main.ts\nimport { defineUserRoutes } from './routes/user';\n\nconst router = defineUserRoutes(ObjectValue.create());\nconst cli = createCli({ router });\n```\n\n## Input Sources (Request Composition)\n\nThe CLI composes request data from three sources in this priority order:\n\n### 1. Command Line JSON Parameter\n\nProvide JSON directly as the second argument:\n\n```bash\nmy-cli greet '{\"name\": \"Alice\", \"age\": 30}'\nmy-cli math.add '{\"a\": 5, \"b\": 3}'\n```\n\n### 2. STDIN Input\n\nPipe JSON data to the CLI:\n\n```bash\necho '{\"name\": \"Bob\"}' | my-cli greet\ncat user.json | my-cli user.create\ncurl -s api.example.com/data.json | my-cli process.data\n```\n\n### 3. Command Line Options\n\nUse typed parameters to build the request object:\n\n```bash\n# String values\nmy-cli greet --str/name=Alice --str/title=\"Ms.\"\n\n# Numeric values  \nmy-cli math.add --num/a=10 --num/b=20\n\n# Boolean values\nmy-cli user.update --bool/active=true --bool/verified=false\n\n# JSON values\nmy-cli config.set --json/settings='{\"theme\": \"dark\", \"lang\": \"en\"}'\n\n# Nested paths using JSON Pointer (requires parent structure to exist)\nmy-cli user.update '{\"profile\": {}}' --str/profile/name=\"Alice\" --num/profile/age=25\n\n# To create nested structures, provide the base structure first\nmy-cli config.set '{\"database\": {}}' --str/database/host=localhost --num/database/port=5432\n```\n\n### Combining Input Sources\n\nAll sources can be combined. Command line options override STDIN data, which overrides the JSON parameter:\n\n```bash\necho '{\"name\": \"Default\", \"age\": 0}' | my-cli greet --str/name=Alice --num/age=30\n# Result: {\"name\": \"Alice\", \"age\": 30}\n```\n\n## Output Formats (Response Encoding)\n\n### Supported Codecs\n\nThe CLI supports multiple output formats through codecs:\n\n| Codec | Description | Use Case |\n|-------|-------------|----------|\n| `json` | Standard JSON (default) | Human-readable, web APIs |\n| `json2` | Pretty JSON (2 spaces) | Development, debugging |\n| `json4` | Pretty JSON (4 spaces) | Documentation, config files |\n| `cbor` | CBOR binary format | Compact binary, IoT |\n| `msgpack` | MessagePack binary | High performance, caching |\n| `ubjson` | Universal Binary JSON | Cross-platform binary |\n| `text` | Formatted text output | Human-readable reports |\n| `tree` | Tree visualization | Debugging, data exploration |\n| `raw` | Raw data output | Binary data, strings |\n\n### Using Output Formats\n\n```bash\n# Default JSON output\nmy-cli user.get '{\"id\": \"123\"}'\n\n# Pretty-printed JSON\nmy-cli user.get '{\"id\": \"123\"}' --format=json4\n\n# Binary formats\nmy-cli data.export --format=cbor \u003e data.cbor\nmy-cli data.export --format=msgpack \u003e data.msgpack\n\n# Text visualization  \nmy-cli config.get --format=tree\nmy-cli config.get --format=text\n\n# Different input/output formats\ncat data.cbor | my-cli process.data --format=cbor:json\necho '{\"test\": 123}' | my-cli echo --format=json:tree\n```\n\n### Extracting Response Data\n\nUse the `--stdout` or `--out` parameter to extract specific parts of the response:\n\n```bash\n# Extract specific field\nmy-cli user.get '{\"id\": \"123\"}' --out=/user/name\n\n# Extract nested data\nmy-cli api.fetch '{\"url\": \"example.com\"}' --out=/response/data/items\n\n# Combine with format conversion\nmy-cli data.complex --out=/results/summary --format=json:text\n```\n\n## Command Line Parameters\n\nAll parameter paths use **JSON Pointer** syntax as defined in [RFC 6901](https://tools.ietf.org/html/rfc6901). JSON Pointers provide a standardized way to reference specific values within JSON documents using slash-separated paths.\n\nWhen a path doesn't exist in the target object, the CLI automatically creates the necessary nested structure. For example, `--str/database/host=localhost` will create the object `{\"database\": {\"host\": \"localhost\"}}` even if neither `database` nor `host` existed previously.\n\n### Data Type Parameters\n\n#### String Values (`--str` or `--s`)\n```bash\nmy-cli greet --str/name=Alice\nmy-cli config.set --s/database/host=localhost --s/database/name=mydb\n```\n\n#### Numeric Values (`--num` or `--n`)\n```bash\nmy-cli math.add --num/a=10 --num/b=20\nmy-cli server.start --n/port=3000 --n/workers=4\n```\n\n#### Boolean Values (`--bool` or `--b`)\n```bash\nmy-cli user.update --bool/active=true\nmy-cli feature.toggle --b/enabled=false\n```\n\n#### JSON Values (`--json` or `--j`)\n```bash\nmy-cli config.merge --json/settings='{\"theme\": \"dark\"}'\nmy-cli api.call --j/payload='[1,2,3]'  \n```\n\n#### Undefined Values (`--und`)\n```bash\nmy-cli optional.field --und/optionalParam\n```\n\n### File Input (`--file` or `--f`)\n\nRead values from files with optional format and path extraction:\n\n```bash\n# Read JSON file\nmy-cli process.data --file/input=data.json\n\n# Read with specific codec\nmy-cli import.data --f/data=data.cbor:cbor\n\n# Extract path from file  \nmy-cli user.create --f/profile=user.json:json:/personalInfo\n\n# Chain: file -\u003e codec -\u003e path\nmy-cli complex.import --f/config=settings.msgpack:msgpack:/database/credentials\n```\n\n### Command Execution (`--cmd` or `--c`)\n\nExecute commands and use their output as values:\n\n```bash\n# Use command output as string\nmy-cli log.write --cmd/message='(echo \"Current time: $(date)\"):text'\n\n# Use command output as JSON\nmy-cli api.send --c/data='(curl -s api.example.com/data):json'\n\n# Extract path from command output\nmy-cli process.status --c/info='(ps aux | grep node):json:/0/pid'\n```\n\n### Format Control (`--format` or `--fmt`)\n\nControl input and output encoding:\n\n```bash\n# Single format (for both input and output)  \nmy-cli echo --format=cbor\n\n# Separate input and output formats\nmy-cli convert --format=cbor:json\nmy-cli transform --fmt=json:tree\n```\n\n### STDIN Control (`--stdin` or `--in`)\n\nExplicitly control STDIN data mapping:\n\n```bash\n# Use all STDIN data\necho '{\"name\": \"Alice\"}' | my-cli greet --stdin\n\n# Map STDIN to specific path\necho '{\"users\": [...]}' | my-cli process.users --in/data=/users\n\n# Map with path extraction\necho '{\"response\": {\"users\": [...]}}' | my-cli save.users --in/users=/response/users\n```\n\n### Output Control (`--stdout` or `--out`)\n\nExtract specific parts of the response:\n\n```bash\n# Extract single field\nmy-cli user.get '{\"id\": \"123\"}' --out=/name\n\n# Extract nested object\nmy-cli api.fetch --out=/response/data\n\n# Use with format conversion\nmy-cli complex.data --out=/results --format=json:tree\n```\n\n### Utility Parameters\n\n#### Help (`--help` or `--h`)\n```bash\nmy-cli --help                    # General help\nmy-cli method.name --help        # Method-specific help  \n```\n\n#### Version (`--version` or `--v`)\n```bash\nmy-cli --version\n```\n\n#### Execution Plan (`--plan`)\n```bash\nmy-cli complex.operation --plan  # Show what would be executed\n```\n\n## Advanced Features\n\n### Type Introspection\n\nGet information about available methods and their schemas:\n\n```bash\n# List all methods\nmy-cli .type\n\n# Get method schema\nmy-cli .type --out=/methodName\nmy-cli .type --out=/user.create/req --format=tree\nmy-cli .type --out=/user.create/res --format=json4\n```\n\n### Binary Data Handling\n\nThe CLI supports binary data through various codecs:\n\n```bash\n# Process binary data\ncat image.jpg | my-cli image.process --format=raw:json\n\n# Convert between binary formats  \ncat data.cbor | my-cli convert --format=cbor:msgpack \u003e data.msgpack\n\n# Encode JSON as binary\nmy-cli data.export '{\"large\": \"dataset\"}' --format=json:cbor \u003e export.cbor\n```\n\n### Error Handling\n\nErrors follow JSON Rx RPC error format and are sent to STDERR:\n\n```bash\nmy-cli invalid.method 2\u003eerrors.log\nmy-cli user.get '{\"invalid\": \"data\"}' 2\u003evalidation-errors.json\n```\n\nError objects include:\n- `message`: Human-readable error description\n- `code`: Stable error code for programmatic handling  \n- `errno`: Numeric error code\n- `errorId`: Unique error identifier for logging\n- `meta`: Additional error metadata (stack traces, etc.)\n\n### Performance Optimization\n\nFor high-performance scenarios:\n\n```bash\n# Use binary formats for large data\nmy-cli large.dataset --format=msgpack\n\n# Use raw format for simple string/binary output  \nmy-cli get.file.content --format=raw\n\n# Stream processing with STDIN/STDOUT\ncat large-file.json | my-cli process.stream --format=json:cbor | my-cli save.processed --format=cbor\n```\n\n## Complete Example\n\nHere's a complete example building a file processing CLI:\n\n```typescript\nimport { createCli } from '@jsonjoy.com/json-type-cli';\nimport { ObjectValue } from '@jsonjoy.com/json-type/lib/value/ObjectValue';\nimport * as fs from 'fs';\nimport * as path from 'path';\n\nconst router = ObjectValue.create();\nconst { t } = router;\n\n// File operations\nrouter\n  .prop('file.read',\n    t.Function(\n      t.Object(\n        t.prop('path', t.str),\n        t.propOpt('encoding', t.str)\n      ),\n      t.Object(\n        t.prop('content', t.str),\n        t.prop('size', t.num)\n      )\n    ).options({\n      title: 'Read file content',\n      description: 'Reads a file and returns its content and size'\n    }),\n    async ({ path: filePath, encoding = 'utf8' }) =\u003e {\n      const content = fs.readFileSync(filePath, encoding);\n      return {\n        content,\n        size: content.length\n      };\n    }\n  )\n  .prop('file.write',\n    t.Function(\n      t.Object(\n        t.prop('path', t.str),\n        t.prop('content', t.str),\n        t.propOpt('encoding', t.str)\n      ),\n      t.Object(\n        t.prop('success', t.bool),\n        t.prop('bytesWritten', t.num)\n      )\n    ).options({\n      title: 'Write file content',\n      description: 'Writes content to a file'\n    }),\n    async ({ path: filePath, content, encoding = 'utf8' }) =\u003e {\n      fs.writeFileSync(filePath, content, encoding);\n      return {\n        success: true,\n        bytesWritten: Buffer.from(content, encoding).length\n      };\n    }\n  )\n  .prop('file.list',\n    t.Function(\n      t.Object(\n        t.prop('directory', t.str),\n        t.propOpt('pattern', t.str)\n      ),\n      t.Object(\n        t.prop('files', t.Array(t.str)),\n        t.prop('count', t.num)\n      )\n    ).options({\n      title: 'List directory files',\n      description: 'Lists files in a directory, optionally filtered by pattern'\n    }),\n    async ({ directory, pattern }) =\u003e {\n      let files = fs.readdirSync(directory);\n      \n      if (pattern) {\n        const regex = new RegExp(pattern);\n        files = files.filter(file =\u003e regex.test(file));\n      }\n      \n      return {\n        files,\n        count: files.length\n      };\n    }\n  );\n\nconst cli = createCli({\n  router,\n  version: 'v1.0.0',\n  cmd: 'file-cli'\n});\n\ncli.run();\n```\n\nUsage examples:\n\n```bash\n# Read a file\nfile-cli file.read --str/path=package.json --format=json4\n\n# Write content from STDIN\necho \"Hello World\" | file-cli file.write --str/path=output.txt --in/content\n\n# List JavaScript files  \nfile-cli file.list --str/directory=src --str/pattern='\\\\.js$' --out=/files\n\n# Chain operations: read -\u003e transform -\u003e write\nfile-cli file.read --str/path=input.json | \n  file-cli transform.data | \n  file-cli file.write --str/path=output.json --in/content --format=json:raw\n```\n\nThis example demonstrates the full power of JSON Type CLI for building robust, type-safe command-line tools that implement the JSON Rx RPC protocol with rich input/output capabilities.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstreamich%2Fjson-type-cli","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstreamich%2Fjson-type-cli","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstreamich%2Fjson-type-cli/lists"}