diff --git a/package.json b/package.json index 127abc1..f90c335 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@contentstack/types-generator", - "version": "2.0.3", + "version": "2.1.0", "description": "Contentstack type definition generation library", "private": false, "author": "Contentstack", diff --git a/src/generateTS/factory.ts b/src/generateTS/factory.ts index 9b5a7b4..d681267 100644 --- a/src/generateTS/factory.ts +++ b/src/generateTS/factory.ts @@ -217,29 +217,57 @@ export default function (userOptions: TSGenOptions) { function visit_field(field: ContentstackTypes.Field) { let fieldType = ""; - if ( - field.data_type === "global_field" && - cachedGlobalFields[name_type(field.reference_to)] - ) { - fieldType = name_type(field.reference_to); + // Check if the field is a global field + if (field.data_type === "global_field") { + // Check if the field is cached + const isCached = cachedGlobalFields[name_type(field.reference_to)]; + + // Generate the referred_content_types array + const referredContentTypes = [ + { + title: name_type(field.reference_to), + uid: field.reference_to, + }, + ]; + + // Assign the new structure for the global field + fieldType = `referred_content_types: ${JSON.stringify( + referredContentTypes + )}`; + // If it's a multiple field, append '[]' to the fieldType if (field.multiple) { fieldType += "[]"; } + + // If the field is not cached and there is a reference, update fieldType accordingly + if (!isCached && field.reference_to) { + fieldType = type_reference(field); + } } else if (field.data_type === "blocks") { + // Handle blocks type (unchanged) fieldType = type_modular_blocks(field); + } else { + // Default handling if fieldType is still empty + fieldType = visit_field_type(field); } - return [ - field.uid + op_required(field.mandatory) + ":", - fieldType || visit_field_type(field), + + // Build and return the final string in the required format + const requiredFlag = op_required(field.mandatory); + const typeModifier = ["isodate", "file", "number"].includes(field.data_type) || ["radio", "dropdown"].includes(field.display_type) ? field.mandatory ? "" - : "| null" - : "", - ";", - ].join(" "); + : " | null" + : ""; + + if (fieldType.startsWith("referred_content_types")) { + // For global_field or referred_content_types, omit field.uid in output + return `${fieldType}`; + } + // Ensure the formatting is correct, and avoid concatenating field.uid directly to a string + return `${field.uid}${requiredFlag}: ${fieldType}${typeModifier};`; } function visit_fields(schema: ContentstackTypes.Schema) { @@ -275,10 +303,9 @@ export default function (userOptions: TSGenOptions) { let 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 fieldType = block.reference_to + ? name_type(block.reference_to) + : visit_fields(block.schema || []); const schema = block.reference_to ? `${fieldType};` @@ -341,13 +368,11 @@ export default function (userOptions: TSGenOptions) { function type_global_field(field: ContentstackTypes.GlobalField) { if (!field.schema) { throw new Error( - `Schema not found for global field '${field.uid}. Did you forget to include it?` + `Schema not found for global field '${field.uid}'. Did you forget to include it?` ); } - const name = name_type(field.reference_to); - - return name; + return name_type(field.reference_to); } function type_reference(field: ContentstackTypes.Field) { diff --git a/src/generateTS/index.ts b/src/generateTS/index.ts index b38d2cf..bd1c99f 100644 --- a/src/generateTS/index.ts +++ b/src/generateTS/index.ts @@ -145,7 +145,6 @@ export const generateTSFromContentTypes = async ({ }); } } - const output = await format( [ defaultInterfaces(prefix, systemFields).join("\n\n"), diff --git a/src/types/schema.ts b/src/types/schema.ts index 3098836..c8c19d2 100644 --- a/src/types/schema.ts +++ b/src/types/schema.ts @@ -30,6 +30,7 @@ export type GlobalField = { schema: Schema; schema_type?: string; _version?: number; + referred_content_types: Array<{ uid: string; title: string }>; } & FieldOptions; export type ReferenceField = { diff --git a/tests/unit/generateTS/generateTS.test.ts b/tests/unit/generateTS/generateTS.test.ts index 0f3fe6d..ccb1612 100644 --- a/tests/unit/generateTS/generateTS.test.ts +++ b/tests/unit/generateTS/generateTS.test.ts @@ -333,7 +333,7 @@ describe("generateTS function with errors", () => { }); } catch (err: any) { expect(err.error_message).toEqual( - "Something went wrong, Schema not found for global field 'global_field. Did you forget to include it?" + "Something went wrong, Schema not found for global field 'global_field'. Did you forget to include it?" ); } }); diff --git a/tests/unit/tsgen/boolean.test.ts b/tests/unit/tsgen/boolean.test.ts index 91b14ce..ef5621f 100644 --- a/tests/unit/tsgen/boolean.test.ts +++ b/tests/unit/tsgen/boolean.test.ts @@ -26,8 +26,8 @@ describe("builtin boolean field", () => { { /** Version */ _version: number; - title: string ; - boolean?: boolean ; + title: string; + boolean?: boolean; }" `); }); diff --git a/tests/unit/tsgen/defaults.test.ts b/tests/unit/tsgen/defaults.test.ts index 2dea8f6..8b840b7 100644 --- a/tests/unit/tsgen/defaults.test.ts +++ b/tests/unit/tsgen/defaults.test.ts @@ -19,7 +19,7 @@ describe("default single content block", () => { { /** Version */ _version: number; - title: string ; + title: string; }" `); }); @@ -45,8 +45,8 @@ describe("default single webpage", () => { { /** Version */ _version: number; - title: string ; - url: string ; + title: string; + url: string; }" `); }); diff --git a/tests/unit/tsgen/global.fields.ct.js b/tests/unit/tsgen/global.fields.ct.js index 842f1b6..e1235c2 100644 --- a/tests/unit/tsgen/global.fields.ct.js +++ b/tests/unit/tsgen/global.fields.ct.js @@ -1,168 +1,280 @@ -const globalFields = { - created_at: "2020-07-12T15:48:42.629Z", - updated_at: "2020-07-12T15:48:52.343Z", - title: "Global Fields", - uid: "global_fields", - _version: "number", - inbuilt_class: false, - schema: [ - { - display_name: "Title", - uid: "title", - data_type: "text", - mandatory: true, - unique: true, - field_metadata: { - _default: true, - version: 3, +const globalFields = [ + { + created_at: "2025-01-30T06:12:44.368Z", + updated_at: "2025-01-30T06:12:44.368Z", + title: "new global", + uid: "new_global", + _version: 1, + inbuilt_class: false, + schema: [ + { + data_type: "text", + display_name: "Single Line Textbox", + uid: "single_line_textbox", + field_metadata: { + description: "", + default_value: "", + version: 3, + }, + format: "", + error_messages: { + format: "", + }, + mandatory: false, + multiple: false, + non_localizable: false, + unique: false, }, - multiple: false, - non_localizable: false, + ], + last_activity: { }, - { - data_type: "global_field", - display_name: "SEO", - reference_to: "seo", - field_metadata: { - description: "", + maintain_revisions: true, + description: "", + schema_type: "global_field", + }, + { + created_at: "2024-12-23T12:57:30.467Z", + updated_at: "2025-01-29T08:10:28.956Z", + title: "global test", + uid: "global_test", + _version: 9, + inbuilt_class: false, + schema: [ + { + data_type: "text", + display_name: "Single Line Text", + uid: "single_line_text", + field_metadata: { + description: "", + default_value: "", + version: 3, + }, + format: "", + error_messages: { + format: "", + }, + mandatory: false, + multiple: false, + non_localizable: false, + unique: false, + }, + { + data_type: "reference", + display_name: "SEO", + reference_to: [ + "testing", + ], + field_metadata: { + ref_multiple: false, + ref_multiple_content_types: true, + }, + uid: "seo", + mandatory: false, + multiple: false, + non_localizable: false, + unique: false, }, - uid: "seo", - multiple: false, - mandatory: false, - unique: false, - non_localizable: false, - schema: [ - { - data_type: "text", - display_name: "Keywords", - uid: "keywords", - field_metadata: { - description: "", - default_value: "", - version: 3, + ], + last_activity: { + }, + maintain_revisions: true, + description: "", + schema_type: "global_field", + }, + { + title: "home", + description: "", + options: { + is_page: false, + singleton: false, + sub_title: [ + ], + title: "title", + }, + schema: [ + { + data_type: "text", + display_name: "Title", + field_metadata: { + _default: true, + version: 3, + }, + mandatory: true, + uid: "title", + unique: true, + multiple: false, + non_localizable: false, + }, + { + data_type: "taxonomy", + display_name: "Taxonomy", + uid: "taxonomies", + taxonomies: [ + { + taxonomy_uid: "tax_1", + max_terms: 8, + mandatory: false, + multiple: true, + non_localizable: false, }, - format: "", - error_messages: { - format: "", + { + taxonomy_uid: "tax_2", + max_terms: 8, + mandatory: false, + multiple: true, + non_localizable: false, }, - multiple: false, - mandatory: false, - unique: false, - indexed: false, - inbuilt_model: false, - non_localizable: false, + ], + field_metadata: { + description: "", + default_value: "", }, - { - data_type: "text", - display_name: "Description", - uid: "description", - field_metadata: { - description: "", - default_value: "", - multiline: true, - version: 3, - }, + format: "", + error_messages: { format: "", - error_messages: { - format: "", - }, - multiple: false, - mandatory: false, - unique: false, - indexed: false, - inbuilt_model: false, - non_localizable: false, }, + mandatory: false, + multiple: true, + non_localizable: false, + unique: false, + }, + ], + uid: "home", + DEFAULT_ACL: { + others: { + read: false, + create: false, + }, + users: [ ], }, - ], - last_activity: {}, - maintain_revisions: true, - description: "", - DEFAULT_ACL: { - others: { - read: false, - create: false, - }, - users: [ - { - uid: "blta1a106c13958e89d", - read: true, + SYS_ACL: { + others: { + read: false, + create: false, + update: false, + delete: false, sub_acl: { - read: true, + read: false, + create: false, + update: false, + delete: false, + publish: false, }, }, - ], + roles: [ + ], + }, + created_at: "2025-01-10T09:18:20.450Z", + updated_at: "2025-01-27T13:05:20.998Z", + inbuilt_class: false, + abilities: { + get_one_object: true, + get_all_objects: true, + create_object: true, + update_object: true, + delete_object: true, + delete_all_objects: true, + }, + last_activity: { + }, + maintain_revisions: true, + _version: 4, }, - SYS_ACL: { - roles: [ + { + title: "testing", + description: "", + options: { + is_page: false, + singleton: true, + sub_title: [ + ], + title: "title", + }, + schema: [ { - uid: "blt127263b8951e2542", - read: true, - sub_acl: { - create: true, - read: true, - update: true, - delete: true, - publish: true, + data_type: "text", + display_name: "Title", + field_metadata: { + _default: true, + version: 3, }, - update: true, - delete: true, + mandatory: true, + uid: "title", + unique: true, + multiple: false, + non_localizable: false, }, { - uid: "blt7e69bb0e63cc5fb6", - read: true, - sub_acl: { - create: true, - read: true, - update: true, - delete: true, - publish: true, + data_type: "json", + display_name: "JSON Rich Text Editor", + uid: "json_rte", + field_metadata: { + allow_json_rte: true, + embed_entry: false, + description: "", + default_value: "", + multiline: false, + rich_text_type: "advanced", + options: [ + ], }, - }, - { - uid: "bltb442c49a50c5804d", - read: true, - sub_acl: { - create: true, - read: true, - update: true, - delete: true, - publish: true, + format: "", + error_messages: { + format: "", }, - update: true, - delete: true, + reference_to: [ + "sys_assets", + ], + multiple: false, + non_localizable: false, + unique: false, + mandatory: false, }, ], - others: { - read: false, - create: false, - update: false, - delete: false, - sub_acl: { + uid: "testing", + DEFAULT_ACL: { + others: { + read: false, + create: false, + }, + users: [ + ], + }, + SYS_ACL: { + others: { read: false, create: false, update: false, delete: false, - publish: false, + sub_acl: { + read: false, + create: false, + update: false, + delete: false, + publish: false, + }, }, + roles: [ + ], }, + created_at: "2025-01-09T09:32:22.764Z", + updated_at: "2025-01-29T10:56:40.919Z", + inbuilt_class: false, + abilities: { + get_one_object: true, + get_all_objects: true, + create_object: true, + update_object: true, + delete_object: true, + delete_all_objects: true, + }, + last_activity: { + }, + maintain_revisions: true, + _version: 4, }, - options: { - is_page: false, - singleton: true, - title: "title", - sub_title: [], - }, - abilities: { - get_one_object: true, - get_all_objects: true, - create_object: true, - update_object: true, - delete_object: true, - delete_all_objects: true, - }, -}; +] module.exports = { globalFields, diff --git a/tests/unit/tsgen/global.fields.test.ts b/tests/unit/tsgen/global.fields.test.ts index 77d1512..59f92dc 100644 --- a/tests/unit/tsgen/global.fields.test.ts +++ b/tests/unit/tsgen/global.fields.test.ts @@ -11,35 +11,49 @@ const tsgen = tsgenFactory({ }); describe("global fields", () => { - const result = tsgen(testData.globalFields); + let result: any; + const globalFields: Array = []; + const definitions: Array = []; - test("metadata", () => { - const types = result.metadata.types; + for (const contentType of testData.globalFields) { + const tsgenResult = tsgen(contentType); + + if (tsgenResult.isGlobalField) { + globalFields.push(tsgenResult.definition); + } else { + definitions.push(tsgenResult.definition); - expect([...types.globalFields]).toEqual(expect.arrayContaining(["ISeo"])); + tsgenResult.metadata.types.globalFields.forEach((field: string) => { + globalFields.push( + tsgenResult.metadata.dependencies.globalFields[field].definition + ); + }); + } + } + + test("metadata", () => { + expect(globalFields[0]).toEqual(expect.stringContaining("INewGlobal")); }); test("global field definition", () => { - const globalField = result.metadata.dependencies.globalFields.ISeo; - expect(globalField.definition).toMatchInlineSnapshot(` - "export interface ISeo + expect(globalFields[0]).toMatchInlineSnapshot(` + "export interface INewGlobal { /** Version */ _version: number; - keywords?: string ; - description?: string ; + single_line_textbox?: string; }" `); }); test("content type definition", () => { - expect(result.definition).toMatchInlineSnapshot(` - "export interface IGlobalFields + expect(definitions[0]).toMatchInlineSnapshot(` + "export interface IHome { /** Version */ _version: number; - title: string ; - seo?: ISeo ; + title: string; + taxonomies?: ITaxonomy[]; }" `); }); diff --git a/tests/unit/tsgen/group.test.ts b/tests/unit/tsgen/group.test.ts index e1f0a2e..c6a6456 100644 --- a/tests/unit/tsgen/group.test.ts +++ b/tests/unit/tsgen/group.test.ts @@ -25,31 +25,31 @@ describe("group", () => { { /** Version */ _version: number; - title: string ; + title: string; multiple_group_max_limit?: [{ - number?: number | null ; + number?: number | null; }, { - number?: number | null ; + number?: number | null; }, { - number?: number | null ; + number?: number | null; }, { - number?: number | null ; + number?: number | null; }, { - number?: number | null ; - }] ; + number?: number | null; + }]; multiple_group?: { - single_line?: string ; - }[] ; + single_line?: string; + }[]; parent_group?: { - rich_text_editor?: string ; - multi_line?: string ; - single_line?: string ; + rich_text_editor?: string; + multi_line?: string; + single_line?: string; child_group?: { - number?: number | null ; - boolean?: boolean ; - date?: string | null ; - } ; - } ; + number?: number | null; + boolean?: boolean; + date?: string | null; + }; + }; }" `); }); diff --git a/tests/unit/tsgen/isodate.test.ts b/tests/unit/tsgen/isodate.test.ts index d53eb0f..478764e 100644 --- a/tests/unit/tsgen/isodate.test.ts +++ b/tests/unit/tsgen/isodate.test.ts @@ -26,12 +26,12 @@ describe("builtin isodate field", () => { { /** Version */ _version: number; - title: string ; - date?: string | null ; - date_required: string ; - date_multiple?: string[] | null ; - date_multiple_maxlength?: [string, string, string, string, string] | null ; - date_required_multiple_maxlength: [string, string, string, string, string, string, string, string] ; + title: string; + date?: string | null; + date_required: string; + date_multiple?: string[] | null; + date_multiple_maxlength?: [string, string, string, string, string] | null; + date_required_multiple_maxlength: [string, string, string, string, string, string, string, string]; }" `); }); diff --git a/tests/unit/tsgen/jsdoc.test.ts b/tests/unit/tsgen/jsdoc.test.ts index fe9df6f..92b3b62 100644 --- a/tests/unit/tsgen/jsdoc.test.ts +++ b/tests/unit/tsgen/jsdoc.test.ts @@ -18,13 +18,13 @@ describe("jsdoc", () => { /** Version */ _version: number; /** Name */ - title: string ; + title: string; /** Age */ - current_age?: number | null ; + current_age?: number | null; /** City */ - current_city?: string ; + current_city?: string; /** State */ - current_state?: string ; + current_state?: string; }" `); }); diff --git a/tests/unit/tsgen/modular.blocks.test.ts b/tests/unit/tsgen/modular.blocks.test.ts index 6846df1..04648f5 100644 --- a/tests/unit/tsgen/modular.blocks.test.ts +++ b/tests/unit/tsgen/modular.blocks.test.ts @@ -20,24 +20,24 @@ describe("modular blocks", () => { expect(result.definition).toMatchInlineSnapshot(` "export interface ModularBlocks { string_block: { - single_line?: string ; - multi_line?: string ; - markdown?: string ; - rich_text_editor?: string ; } + 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[] ; } + single_line_textbox_required: string; + single_line_textbox_multiple?: string[]; } boolean_block: { - boolean?: boolean ; } + boolean?: boolean; } } export interface ModularBlocks { /** Version */ _version: number; - title: string ; - url: string ; - modular_blocks?: ModularBlocks[] ; + title: string; + url: string; + modular_blocks?: ModularBlocks[]; }" `); }); diff --git a/tests/unit/tsgen/number.test.ts b/tests/unit/tsgen/number.test.ts index bf21fbf..71f2bde 100644 --- a/tests/unit/tsgen/number.test.ts +++ b/tests/unit/tsgen/number.test.ts @@ -23,13 +23,13 @@ describe("builtin number field", () => { { /** Version */ _version: number; - title: string ; - url: string ; - number?: number | null ; - number_required: number ; - number_multiple?: number[] | null ; - number_multiple_max_limit?: [number, number, number, number, number, number, number, number, number, number] | null ; - number_required_multiple_max_limit: [number, number, number] ; + title: string; + url: string; + number?: number | null; + number_required: number; + number_multiple?: number[] | null; + number_multiple_max_limit?: [number, number, number, number, number, number, number, number, number, number] | null; + number_required_multiple_max_limit: [number, number, number]; }" `); }); diff --git a/tests/unit/tsgen/options.test.ts b/tests/unit/tsgen/options.test.ts index dd0c475..abafa8d 100644 --- a/tests/unit/tsgen/options.test.ts +++ b/tests/unit/tsgen/options.test.ts @@ -16,12 +16,12 @@ describe("all options", () => { { /** Version */ _version: number; - title: string ; - url: string ; - single_line_textbox_not_required?: string ; - single_line_textbox_required: string ; - single_line_textbox_multiple?: string[] ; - single_line_textbox_multiple_max_limit?: [string, string, string, string, string] ; + title: string; + url: string; + single_line_textbox_not_required?: string; + single_line_textbox_required: string; + single_line_textbox_multiple?: string[]; + single_line_textbox_multiple_max_limit?: [string, string, string, string, string]; }" `); }); diff --git a/tests/unit/tsgen/references.test.ts b/tests/unit/tsgen/references.test.ts index cffc400..187a6c7 100644 --- a/tests/unit/tsgen/references.test.ts +++ b/tests/unit/tsgen/references.test.ts @@ -27,10 +27,10 @@ describe("references", () => { { /** Version */ _version: number; - title: string ; - url: string ; - single_reference: (IReferenceChild)[] ; - multiple_reference?: (IReferenceChild | IBoolean | IBuiltinExample)[] ; + title: string; + url: string; + single_reference: (IReferenceChild)[]; + multiple_reference?: (IReferenceChild | IBoolean | IBuiltinExample)[]; }" `); }); diff --git a/tests/unit/tsgen/select.test.ts b/tests/unit/tsgen/select.test.ts index 4b89505..76989ab 100644 --- a/tests/unit/tsgen/select.test.ts +++ b/tests/unit/tsgen/select.test.ts @@ -22,13 +22,13 @@ describe("select (dropdown)", () => { { /** Version */ _version: number; - title: string ; - select_single_value?: ("Option 1" | "Option 2" | "Option 3") | null ; - select_single_value_required: ("Test 1" | "Test 2" | "Test 3") ; - select_single_value_with_quotes?: ("\\"ABC\\"" | "A\'B\'C" | "\`A\`B\`C") | null ; - select_multi_value?: ("Multi 1" | "Multi 2" | "Multi 3")[] | null ; - select_multi_value_required: ("Multi Req 1" | "Multi Req 2" | "Multi Req 3")[] ; - select_number_values?: (1 | 2 | 3 | 4) | null ; + title: string; + select_single_value?: ("Option 1" | "Option 2" | "Option 3") | null; + select_single_value_required: ("Test 1" | "Test 2" | "Test 3"); + select_single_value_with_quotes?: ("\\"ABC\\"" | "A\'B\'C" | "\`A\`B\`C") | null; + select_multi_value?: ("Multi 1" | "Multi 2" | "Multi 3")[] | null; + select_multi_value_required: ("Multi Req 1" | "Multi Req 2" | "Multi Req 3")[]; + select_number_values?: (1 | 2 | 3 | 4) | null; }" `); }); diff --git a/tests/unit/tsgen/string.test.ts b/tests/unit/tsgen/string.test.ts index a928146..c894c79 100644 --- a/tests/unit/tsgen/string.test.ts +++ b/tests/unit/tsgen/string.test.ts @@ -23,11 +23,11 @@ describe("builtin string fields", () => { { /** Version */ _version: number; - title: string ; - single_line?: string ; - multi_line?: string ; - rich_text_editor?: string ; - markdown?: string ; + title: string; + single_line?: string; + multi_line?: string; + rich_text_editor?: string; + markdown?: string; }" `); }); diff --git a/tests/unit/tsgen/taxonomies.test.ts b/tests/unit/tsgen/taxonomies.test.ts index d166017..6fad2e1 100644 --- a/tests/unit/tsgen/taxonomies.test.ts +++ b/tests/unit/tsgen/taxonomies.test.ts @@ -28,9 +28,9 @@ describe("builtin taxonomies field", () => { { /** Version */ _version: number; - title: string ; - boolean?: boolean ; - taxonomies?: ITaxonomy[] ; + title: string; + boolean?: boolean; + taxonomies?: ITaxonomy[]; }" `); });