bcherny / json-schema-to-typescript

Compile JSON Schema to TypeScript type declarations
https://bcherny.github.io/json-schema-to-typescript-browser/
MIT License
2.92k stars 392 forks source link

Comments on individual enum values #611

Closed a0js closed 1 month ago

a0js commented 2 months ago

Hi! 👋

Firstly, thanks for your work on this project! 🙂

Today I used patch-package to patch json-schema-to-typescript@14.0.5 for the project I'm working on.

I needed a way to add JSDoc descriptions for each enum value in a named enum. I'd be happy to open a PR for adding this functionality, if you think it would be worth doing.

Here is the diff that solved my problem:

diff --git a/node_modules/json-schema-to-typescript/dist/src/generator.js b/node_modules/json-schema-to-typescript/dist/src/generator.js
index ec79bd0..3120d24 100644
--- a/node_modules/json-schema-to-typescript/dist/src/generator.js
+++ b/node_modules/json-schema-to-typescript/dist/src/generator.js
@@ -280,7 +280,10 @@ function generateStandaloneEnum(ast, options) {
         (options.enableConstEnums ? 'const ' : '') +
         `enum ${(0, utils_1.toSafeString)(ast.standaloneName)} {` +
         '\n' +
-        ast.params.map(({ ast, keyName }) => keyName + ' = ' + (0, exports.generateType)(ast, options)).join(',\n') +
+        ast.params.map(({ ast, keyName }) => (
+            ((0, AST_1.hasComment)(ast) ? generateComment(ast.comment, ast.deprecated) + '\n' : '') +
+            keyName + ' = ' + (0, exports.generateType)(ast, options)
+        )).join(',\n') +
         '\n' +
         '}');
 }
diff --git a/node_modules/json-schema-to-typescript/dist/src/parser.js b/node_modules/json-schema-to-typescript/dist/src/parser.js
index 2b44435..a4077ef 100644
--- a/node_modules/json-schema-to-typescript/dist/src/parser.js
+++ b/node_modules/json-schema-to-typescript/dist/src/parser.js
@@ -123,7 +123,7 @@ function parseNonLiteral(schema, type, options, keyName, processed, usedNames) {
                 keyName,
                 standaloneName: standaloneName(schema, keyNameFromDefinition !== null && keyNameFromDefinition !== void 0 ? keyNameFromDefinition : keyName, usedNames, options),
                 params: schema.enum.map((_, n) => ({
-                    ast: parseLiteral(_, undefined),
+                    ast: {...parseLiteral(_, undefined), comment: schema.tsEnumComments?.[n] },
                     keyName: schema.tsEnumNames[n],
                 })),
                 type: 'ENUM',
diff --git a/node_modules/json-schema-to-typescript/src/generator.ts b/node_modules/json-schema-to-typescript/src/generator.ts
index fb8d23b..9de2efb 100644
--- a/node_modules/json-schema-to-typescript/src/generator.ts
+++ b/node_modules/json-schema-to-typescript/src/generator.ts
@@ -335,7 +335,10 @@ function generateStandaloneEnum(ast: TEnum, options: Options): string {
     (options.enableConstEnums ? 'const ' : '') +
     `enum ${toSafeString(ast.standaloneName)} {` +
     '\n' +
-    ast.params.map(({ast, keyName}) => keyName + ' = ' + generateType(ast, options)).join(',\n') +
+    ast.params.map(({ast, keyName}) => (
+      (hasComment(ast) ? generateComment(ast.comment, ast.deprecated) + '\n' : '') +
+      keyName + ' = ' + generateType(ast, options)
+    )).join(',\n')} +
     '\n' +
     '}'
   )
diff --git a/node_modules/json-schema-to-typescript/src/parser.ts b/node_modules/json-schema-to-typescript/src/parser.ts
index 7e82d7f..7e92970 100644
--- a/node_modules/json-schema-to-typescript/src/parser.ts
+++ b/node_modules/json-schema-to-typescript/src/parser.ts
@@ -192,7 +192,7 @@ function parseNonLiteral(
         keyName,
         standaloneName: standaloneName(schema, keyNameFromDefinition ?? keyName, usedNames, options)!,
         params: schema.enum!.map((_, n) => ({
-          ast: parseLiteral(_, undefined),
+          ast: {...parseLiteral(_, undefined), comment: schema.tsEnumComments?.[n]},
           keyName: schema.tsEnumNames![n],
         })),
         type: 'ENUM',
diff --git a/node_modules/json-schema-to-typescript/src/types/JSONSchema.ts b/node_modules/json-schema-to-typescript/src/types/JSONSchema.ts
index 4c644f3..4e9f5db 100644
--- a/node_modules/json-schema-to-typescript/src/types/JSONSchema.ts
+++ b/node_modules/json-schema-to-typescript/src/types/JSONSchema.ts
@@ -37,7 +37,11 @@ export interface JSONSchema extends JSONSchema4 {
   /**
    * property exists at least in https://json-schema.org/draft/2019-09/json-schema-validation.html#rfc.section.9.3
    */
-  deprecated?: boolean
+  deprecated?: boolean,
+  /**
+   * schema extension to support enum value descriptions
+   */
+  tsEnumComments?: string[]
 }

 export const Parent = Symbol('Parent')

This issue body was partially generated by patch-package.

aloisklink commented 1 month ago

I like this idea (although I'm not a maintainer of this project).

Although, it might be cool to instead using the meta:enum syntax that the https://github.com/adobe/jsonschema2md library already supports for documenting enums.

It might help for projects that use both this library and that library!

For reference, the syntax is instead an object of enum value to enum description, e.g. (adapted from https://github.com/adobe/jsonschema2md/blob/e6c52a8e1d5806717f3070adda67bd9173613056/test/fixtures/enums/enum-meta-enum.schema.json):

{
      "type": "string",
      "enum": [
        "baa",
        "bad",
        "bag",
        "bah",
        "bam",
        "ban",
        "bap",
        "bas",
        "bat",
        "bay"
      ],
      "meta:enum": {
        "baa": "the sounds of sheeps",
        "bad": "German bathroom",
        "bag": "holding device",
        "bah": "humbug!",
        "bam": "a loud sound",
        "ban": "don't do this",
        "bap": "a British soft bread roll",
        "bas": "from ancient Egyptian religion, an aspect of the soul",
        "bat": "…out of hell",
        "bay": ", sitting by the dock of the"
      }
}
bcherny commented 1 month ago

Is there a reason you need enum comments specifically? JSON-Schema supports this today, you just need to express it a little differently, using anyOf and const. See https://stackoverflow.com/a/64296043/435124.