feat: readonly modifier in json schema

This commit is contained in:
Lukas Obermann
2023-06-07 21:51:42 +02:00
parent 7cff942ccf
commit 1d2be4103e
3 changed files with 32 additions and 9 deletions
+3 -2
View File
@@ -86,8 +86,8 @@ Description | all | `markdown` | `description` keyword | Description
`@markdown` | `string` | `boolean` | — | Type: Markdown-formatted text
`@minLength` | `string` | `number` | `minLength` keyword | Minimum Length
`@maxLength` | `string` | `number` | `maxLength` keyword | Maximum Length
`@pattern` | `string` | `string` | `maxLength` keyword | Pattern
`@format` | `string` | `string` | `maxLength` keyword | Format
`@pattern` | `string` | `string` | `pattern` keyword | Pattern
`@format` | `string` | `string` | `format` keyword | Format
`@integer` | `number` | `boolean` | `"type": "integer"` instead of `"type": "number"` | Type: Integer
`@minimum` | `number` | `number` | `minimum` keyword | Minimum
`@maximum` | `number` | `number` | `maximum` keyword | Maximum
@@ -100,6 +100,7 @@ Description | all | `markdown` | `description` keyword | Description
`@minProperties` | `object` | `number` | `minProperties` keyword | Minimum Properties
`@maxProperties` | `object` | `number` | `maxProperties` keyword | Maximum Properties
`@patternProperties` | `object` | `string` | `patternProperties` keyword | Values matching pattern
`readonly` modifier | property | `boolean` | `readOnly` keyword | Read-only property
#### Boolean tags
+7 -1
View File
@@ -67,6 +67,11 @@ export type RecordNode = {
* The property value.
*/
value: ChildNode
/**
* Is the property read-only?
*/
isReadOnly: boolean
}
}
}
@@ -493,7 +498,8 @@ const nodeToAst = (node: ts.Node, file: ts.SourceFile, checker: ts.TypeChecker,
{
jsDoc: parseNodeDoc(member),
isRequired: member.questionToken === undefined,
value: resolveTempChildNode(nodeToAst(member.type!, file, checker, program, typeArguments))
value: resolveTempChildNode(nodeToAst(member.type!, file, checker, program, typeArguments)),
isReadOnly: member.modifiers?.some(modifier => modifier.kind === ts.SyntaxKind.ReadonlyKeyword) ?? false
}
]
]
+22 -6
View File
@@ -13,6 +13,7 @@ interface Annotated {
title?: string
description?: string
default?: unknown
readOnly?: boolean
}
interface ObjectConstraints {
@@ -198,7 +199,9 @@ const toConstraints = <T extends keyof ConstraintsByType>(jsDoc: Doc | undefined
: []
)
const nodeToDefinition = (spec: JsonSchemaSpec, node: ChildNode): Definition => {
const nodeToDefinition = (spec: JsonSchemaSpec, node: ChildNode, options: { isReadOnly?: boolean } = {}): Definition => {
const { isReadOnly } = options
switch (node.kind) {
case NodeKind.Record: {
return {
@@ -207,11 +210,12 @@ const nodeToDefinition = (spec: JsonSchemaSpec, node: ChildNode): Definition =>
...toDefault(node.jsDoc),
properties: Object.fromEntries(
Object.entries(node.elements)
.map(([key, config]) => [key, nodeToDefinition(spec, config.value)])),
.map(([key, config]) => [key, nodeToDefinition(spec, config.value, { isReadOnly: config.isReadOnly })])),
required: Object.entries(node.elements)
.filter(([_, config]) => config.isRequired)
.map(([key]) => key),
...toConstraints(node.jsDoc, "object"),
...(isReadOnly ? { readOnly: false } : {}),
additionalProperties: false
}
}
@@ -225,6 +229,7 @@ const nodeToDefinition = (spec: JsonSchemaSpec, node: ChildNode): Definition =>
[node.pattern]: nodeToDefinition(spec, node.elements)
},
...toConstraints(node.jsDoc, "object"),
...(isReadOnly ? { readOnly: false } : {}),
additionalProperties: false
}
}
@@ -234,7 +239,8 @@ const nodeToDefinition = (spec: JsonSchemaSpec, node: ChildNode): Definition =>
type: "object",
...toDefault(node.jsDoc),
additionalProperties: nodeToDefinition(spec, node.elements),
...toConstraints(node.jsDoc, "object")
...toConstraints(node.jsDoc, "object"),
...(isReadOnly ? { readOnly: false } : {}),
}
}
}
@@ -244,7 +250,8 @@ const nodeToDefinition = (spec: JsonSchemaSpec, node: ChildNode): Definition =>
type: "array",
...toDefault(node.jsDoc),
items: nodeToDefinition(spec, node.elements),
...toConstraints(node.jsDoc, "array")
...toConstraints(node.jsDoc, "array"),
...(isReadOnly ? { readOnly: false } : {}),
}
}
case NodeKind.Enumeration: {
@@ -252,6 +259,7 @@ const nodeToDefinition = (spec: JsonSchemaSpec, node: ChildNode): Definition =>
...toAnnotations(node.jsDoc),
enum: node.cases.map(({ value }) => value),
...toDefault(node.jsDoc),
...(isReadOnly ? { readOnly: false } : {}),
}
}
case NodeKind.Tuple: {
@@ -265,6 +273,7 @@ const nodeToDefinition = (spec: JsonSchemaSpec, node: ChildNode): Definition =>
minItems: node.elements.length,
maxItems: node.elements.length,
additionalItems: false,
...(isReadOnly ? { readOnly: false } : {}),
}
case "Draft_2020_12": return {
...toAnnotations(node.jsDoc),
@@ -274,6 +283,7 @@ const nodeToDefinition = (spec: JsonSchemaSpec, node: ChildNode): Definition =>
minItems: node.elements.length,
maxItems: node.elements.length,
items: false,
...(isReadOnly ? { readOnly: false } : {}),
}
default: throw TypeError("invalid spec")
}
@@ -283,6 +293,7 @@ const nodeToDefinition = (spec: JsonSchemaSpec, node: ChildNode): Definition =>
...toAnnotations(node.jsDoc),
oneOf: node.cases.map(element => nodeToDefinition(spec, element)),
...toDefault(node.jsDoc),
...(isReadOnly ? { readOnly: false } : {}),
}
}
case NodeKind.Group: {
@@ -296,6 +307,7 @@ const nodeToDefinition = (spec: JsonSchemaSpec, node: ChildNode): Definition =>
...toAnnotations(node.jsDoc),
const: node.value,
...toDefault(node.jsDoc),
...(isReadOnly ? { readOnly: false } : {}),
}
}
case NodeKind.Reference: {
@@ -306,6 +318,7 @@ const nodeToDefinition = (spec: JsonSchemaSpec, node: ChildNode): Definition =>
...toAnnotations(node.jsDoc),
$ref: `${externalFilePath}#/${defsKey(spec)}/${qualifiedName}`,
...toDefault(node.jsDoc),
...(isReadOnly ? { readOnly: false } : {}),
}
}
case NodeKind.Token: {
@@ -315,7 +328,8 @@ const nodeToDefinition = (spec: JsonSchemaSpec, node: ChildNode): Definition =>
...toAnnotations(node.jsDoc),
type: node.jsDoc?.tags.integer ? "integer" : "number",
...toDefault(node.jsDoc),
...toConstraints(node.jsDoc, "number")
...toConstraints(node.jsDoc, "number"),
...(isReadOnly ? { readOnly: false } : {}),
}
}
@@ -324,7 +338,8 @@ const nodeToDefinition = (spec: JsonSchemaSpec, node: ChildNode): Definition =>
...toAnnotations(node.jsDoc),
type: "string",
...toDefault(node.jsDoc),
...toConstraints(node.jsDoc, "string")
...toConstraints(node.jsDoc, "string"),
...(isReadOnly ? { readOnly: false } : {}),
}
}
@@ -333,6 +348,7 @@ const nodeToDefinition = (spec: JsonSchemaSpec, node: ChildNode): Definition =>
...toAnnotations(node.jsDoc),
type: "boolean",
...toDefault(node.jsDoc),
...(isReadOnly ? { readOnly: false } : {}),
}
}
}