diff --git a/README.md b/README.md index 1a80c3f..8ac63c6 100644 --- a/README.md +++ b/README.md @@ -123,38 +123,7 @@ interface BuiltinExample { /** Single Choice */ single_choice: "Choice 1" | "Choice 2" | "Choice 3"; /** Modular Blocks */ - modular_blocks?: ( - | { - block_1: { - /** Number */ - number?: number; - /** Single line textbox */ - single_line?: string; - }; - block_2: undefined; - seo_gf: undefined; - } - | { - block_2: { - /** Boolean */ - boolean?: boolean; - /** Date */ - date?: string; - }; - block_1: undefined; - seo_gf: undefined; - } - | { - seo_gf: { - /** Keywords */ - keywords?: string; - /** Description */ - description?: string; - }; - block_1: undefined; - block_2: undefined; - } - )[]; + modular_blocks?: ModularBlocks[]; /** Number */ number?: number; /** Link */ @@ -166,6 +135,27 @@ interface BuiltinExample { /** Date */ date?: string; } + +interface ModularBlocks { + block_1: { + /** Number */ + number?: number; + /** Single line textbox */ + single_line?: string; + }; + block_2: { + /** Boolean */ + boolean?: boolean; + /** Date */ + date?: string; + }; + seo_gf: { + /** Keywords */ + keywords?: string; + /** Description */ + description?: string; + }; +} ``` #### 2. `graphqlTS()` (Available only for NodeJS) diff --git a/package-lock.json b/package-lock.json index 66468c5..22d30e4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,15 @@ { "name": "@contentstack/types-generator", - "version": "1.0.0", + "version": "2.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@contentstack/types-generator", - "version": "1.0.0", + "version": "2.0.0", "license": "MIT", "dependencies": { - "@contentstack/delivery-sdk": "^4.0.5", + "@contentstack/delivery-sdk": "^4.1.0", "@gql2ts/from-schema": "^2.0.0-4", "axios": "^1.7.4", "lodash": "^4.17.21", @@ -599,23 +599,23 @@ "dev": true }, "node_modules/@contentstack/core": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@contentstack/core/-/core-1.0.3.tgz", - "integrity": "sha512-yZaZM/I5NWY1LskyXvvkMG6CIqQN92EFb5cB7jeA8ahZ8RSF/5pDBKRM6P3BcHRfQ8JQOWkFs4M5ZiDTadIHrA==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@contentstack/core/-/core-1.1.0.tgz", + "integrity": "sha512-yZZswNe8yw6hH+uAIsFTHL5/rP6jJ5oyjy6S1BPHiCaTc24osQrsMHzG3PxLjC1Z6F0976gEbBkquln+deRaXA==", "dependencies": { - "axios": "^1.6.8", + "axios": "^1.7.2", "axios-mock-adapter": "^1.22.0", "lodash": "^4.17.21", - "qs": "^6.12.1", - "tslib": "^2.6.2" + "qs": "^6.13.0", + "tslib": "^2.6.3" } }, "node_modules/@contentstack/delivery-sdk": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@contentstack/delivery-sdk/-/delivery-sdk-4.0.5.tgz", - "integrity": "sha512-sqNxOu8wXUS0caPa7PML+0c2HOoq0owX3XIWlvigFkTKLKTDJWAH+N7TdDnJAI4q0/JWLyGGvOKVIPuFh2SQMg==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@contentstack/delivery-sdk/-/delivery-sdk-4.1.0.tgz", + "integrity": "sha512-AlYRoRpkEI+AtSf5EKxoAOnfqycF1ji5WnW/3CdF6XOk3VtZmWD6dat3R8BNObo4vuVNq+hWYPMz29EgBiogsQ==", "dependencies": { - "@contentstack/core": "^1.0.3", + "@contentstack/core": "^1.1.0", "@contentstack/utils": "^1.3.8", "@types/humps": "^2.0.6", "axios": "^1.7.2", @@ -4772,9 +4772,9 @@ ] }, "node_modules/qs": { - "version": "6.12.3", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.12.3.tgz", - "integrity": "sha512-AWJm14H1vVaO/iNZ4/hO+HyaTehuy9nRqVdkTqlJt0HWvBiBIEXFmb4C0DGeYo3Xes9rrEW+TxHsaigCbN5ICQ==", + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", "dependencies": { "side-channel": "^1.0.6" }, @@ -5448,9 +5448,9 @@ } }, "node_modules/tslib": { - "version": "2.6.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", - "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==" + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==" }, "node_modules/tsup": { "version": "8.1.0", diff --git a/package.json b/package.json index 6ffc54b..b713c5a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@contentstack/types-generator", - "version": "1.0.4", + "version": "2.0.0", "description": "Contentstack type definition generation library", "private": false, "author": "Contentstack", @@ -42,7 +42,7 @@ "typescript": "^5.4.5" }, "dependencies": { - "@contentstack/delivery-sdk": "^4.0.5", + "@contentstack/delivery-sdk": "^4.1.0", "@gql2ts/from-schema": "^2.0.0-4", "axios": "^1.7.4", "lodash": "^4.17.21", diff --git a/src/generateTS/factory.ts b/src/generateTS/factory.ts index e6ef688..5f135d6 100644 --- a/src/generateTS/factory.ts +++ b/src/generateTS/factory.ts @@ -65,6 +65,7 @@ export default function (userOptions: TSGenOptions) { const visitedGlobalFields = new Set(); const visitedContentTypes = new Set(); const cachedGlobalFields: GlobalFieldCache = {}; + const modularBlockInterfaces = new Set(); const typeMap: TypeMap = { text: { func: type_text, track: true, flag: TypeFlags.BuiltinJS }, @@ -233,6 +234,8 @@ export default function (userOptions: TSGenOptions) { if (field.multiple) { fieldType += "[]"; } + } else if (field.data_type === "blocks") { + fieldType = type_modular_blocks(field); } return [ field.uid + op_required(field.mandatory) + ":", @@ -260,7 +263,8 @@ export default function (userOptions: TSGenOptions) { function visit_content_type( contentType: ContentstackTypes.ContentType | ContentstackTypes.GlobalField ) { - return [ + modularBlockInterfaces.clear(); + const contentTypeInterface = [ options.docgen.interface(contentType.description), define_interface(contentType, options.systemFields), "{", @@ -271,29 +275,34 @@ export default function (userOptions: TSGenOptions) { ] .filter((v) => v) .join("\n"); - } - function visit_modular_block( - field: ContentstackTypes.Field, - block: ContentstackTypes.Block - ) { - return ( - "{" + - [ - block.uid + ":", - block.reference_to - ? name_type(block.reference_to as string) + ";" - : "{" + visit_fields(block.schema || []) + "};", - ].join(" ") + - visit_block_names(field, block) + - "}" - ); + return [...modularBlockInterfaces, contentTypeInterface].join("\n\n"); } - function type_modular_blocks(field: ContentstackTypes.Field) { - return op_paren( - field.blocks.map((block) => visit_modular_block(field, block)).join(" | ") - ); + function type_modular_blocks(field: ContentstackTypes.Field): string { + const blockInterfaceName = name_type(field.uid); + const blockInterfaces = field.blocks.map((block) => { + const fieldType = + block.reference_to && cachedGlobalFields[name_type(block.reference_to)] + ? name_type(block.reference_to) + : visit_fields(block.schema || []); + + const schema = block.reference_to + ? `${fieldType};` + : `{\n ${fieldType} }`; + return `${block.uid}: ${schema}`; + }); + + const modularInterface = [ + `export interface ${blockInterfaceName} {`, + blockInterfaces.join("\n"), + "}", + ].join("\n"); + + // Store or track the generated block interface for later use + modularBlockInterfaces.add(modularInterface); + + return field.multiple ? `${blockInterfaceName}[]` : blockInterfaceName; } function type_group(field: ContentstackTypes.Field) { diff --git a/tests/unit/tsgen/modular.blocks.test.ts b/tests/unit/tsgen/modular.blocks.test.ts index 6414b55..5e85c7e 100644 --- a/tests/unit/tsgen/modular.blocks.test.ts +++ b/tests/unit/tsgen/modular.blocks.test.ts @@ -18,20 +18,26 @@ describe("modular blocks", () => { test("definition", () => { expect(result.definition).toMatchInlineSnapshot(` - "export interface ModularBlocks + "export interface ModularBlocks { + string_block: { + single_line?: string ; + multi_line?: string ; + markdown?: string ; + rich_text_editor?: string ; } + string_block_with_options: { + single_line_textbox_required: string ; + single_line_textbox_multiple?: string[] ; } + boolean_block: { + boolean?: boolean ; } + } + + export interface ModularBlocks { /** Version */ _version: 2 ; title: string ; url: string ; - modular_blocks?: ({string_block: {single_line?: string ; - multi_line?: string ; - markdown?: string ; - rich_text_editor?: string ;};string_block_with_options: undefined; - boolean_block: undefined;} | {string_block_with_options: {single_line_textbox_required: string ; - single_line_textbox_multiple?: string[] ;};string_block: undefined; - boolean_block: undefined;} | {boolean_block: {boolean?: boolean ;};string_block: undefined; - string_block_with_options: undefined;})[] ; + modular_blocks?: ModularBlocks[] ; }" `); });