redis-doc
redis-doc copied to clipboard
feat: json-schema commands format
@itamarhaber this is an idea following the discussion over the DSL in https://github.com/antirez/redis-doc/pull/1231
This PR consists of a small js script, which parses commands.json
to produce a json file in a slightly different format. Each command has the same root-level properties, except for arguments
, which is now in the format:
Array<{
name: string;
optional: boolean;
schema: JSONSchema7;
}>
This allows redis to avoid re-inventing the wheel for any of the undifferentiated schema-description parts of the documentation, instead relying on json-schema, which is well established, widely used, unambiguous, flexible enough to cover edge-cases, and a good balance of human- and machine-readable.
It's worth taking a look at the generated json-schema file, since it's large, so github suppresses the diff.
Note:
Each argument is represented by JSON-schema, but conceptually the schemas are "flattened" when passed as CLI arguments. For example, DEL
. This has one argument, key
, which is of type array
, meaning it would be valid for inputs like ['foo', 'bar']
, corresponding to redis del foo bar
. So to go from arguments valid per the schema to a CLI call, clients would have to do something like redis ${command} ${flatten(arguments).join(' ')}
.
I also wrote a simple function that parses the .md
documentation for each command to extract the return type and convert to json-schema, so that type can be kept alongside the arguments. Going forward, this json file could become the source of truth for return types, so that this repo could document not just basic return types like @array-reply
, but specify the type of the items in the array too, easily and unambiguously with json-schema (e.g. { "type": "array", "items": { "type": "string" } }
).
This will make client generation much easier, because existing json-schema tooling can be used rather than each client library having to write a custom parser which reverse-engineers the custom DSL currently in commands.json
. (The library I maintain does exactly this reverse-engineering, and has a lot of hacks and pieces of difficult-to-maintain code. I have held off adding it to clients.json so far because of this).
My thought was that if this accepted, the generated commands.json-schema.json
acts as a starting point, and would eventually take the place of commands.json
. it would then be manually edited, as the source of truth, going forwards. The js file shouldn't need to hang around, it's just for generating the "starter" json-schema file. This will allow taking advantage of json-schema's API to go further with type specificity. For example, the problem highlighted in https://github.com/antirez/redis-doc/pull/1231 would go away, because SET
could become (using yaml for conciseness):
summary: Set the string value of a key
complexity: O(1)
arguments:
- name: key
schema:
type: string
- name: value
schema:
type: string
- name: expiration
optional: true
schema:
type: array
items:
- type: enum
enum: [EX, PX]
- type: integer
- name: condition
optional: true
schema:
type: string
enum: [NX, XX]
since: 1.0.0
group: string
return:
anyOf:
- type: string
- type: 'null'
I'd be interested to learn what is currently using commands.json
in the existing format - if you think the idea has legs, I could see what it would take for whatever's downstream (if anything) to switch over to json-schema.
@itamarhaber - any thoughts on this?