From 2518a844ab78d22f86cf2c8ade0e33eada178b92 Mon Sep 17 00:00:00 2001 From: Abhinav Gupta Date: Mon, 9 Oct 2023 12:32:36 +0530 Subject: [PATCH 1/8] feat: added include-system-field flag --- src/commands/tsgen.ts | 8 ++++- src/lib/stack/builtins.ts | 72 +++++++++++++++++++++++++-------------- src/lib/stack/schema.ts | 1 + src/lib/tsgen/factory.ts | 13 +++++-- src/lib/tsgen/runner.ts | 5 +-- 5 files changed, 68 insertions(+), 31 deletions(-) diff --git a/src/commands/tsgen.ts b/src/commands/tsgen.ts index 674930f..a3434f5 100644 --- a/src/commands/tsgen.ts +++ b/src/commands/tsgen.ts @@ -51,6 +51,11 @@ export default class TypeScriptCodeGeneratorCommand extends Command { hidden: false, multiple: false, }), + + 'include-system-fields': flags.boolean({ + description: 'include system fields in generated types', + default: false + }) }; async run() { @@ -62,6 +67,7 @@ export default class TypeScriptCodeGeneratorCommand extends Command { const includeDocumentation = flags.doc const outputPath = flags.output const branch = flags.branch + const includeSystemFields = flags['include-system-fields'] if (token.type !== 'delivery') { this.warn('Possibly using a management token. You may not be able to connect to your Stack. Please use a delivery token.') @@ -91,7 +97,7 @@ export default class TypeScriptCodeGeneratorCommand extends Command { })) } schemas = schemas.concat(client.types) - const result = await tsgenRunner(outputPath, schemas, prefix, includeDocumentation) + const result = await tsgenRunner(outputPath, schemas, prefix, includeDocumentation, includeSystemFields) this.log(`Wrote ${result.definitions} Content Types to '${result.outputPath}'.`) } else { this.log('No Content Types exist in the Stack.') diff --git a/src/lib/stack/builtins.ts b/src/lib/stack/builtins.ts index 541dc80..a6b73b1 100644 --- a/src/lib/stack/builtins.ts +++ b/src/lib/stack/builtins.ts @@ -1,30 +1,52 @@ // File and Link fields are additional, non-scalar, data types within a stack. -export const defaultInterfaces = (prefix = '') => [ - `export interface ${prefix}File { - uid: string; - created_at: string; - updated_at: string; - created_by: string; - updated_by: string; - content_type: string; - file_size: string; - tags: string[]; - filename: string; - url: string; - ACL: any[]; - is_dir: boolean; - parent_uid: string; - _version: number; - title: string; - publish_details: { +export const defaultInterfaces = (prefix = '', systemFields: boolean = false) => { + const defaultInterfaces = [ + `export interface ${prefix}PublishDetails { environment: string; locale: string; time: string; user: string; - }; - }`, - `export interface ${prefix}Link { - title: string; - href: string; - }`, -] + }`, + `export interface ${prefix}File { + uid: string; + created_at: string; + updated_at: string; + created_by: string; + updated_by: string; + content_type: string; + file_size: string; + tags: string[]; + filename: string; + url: string; + ACL: any[]; + is_dir: boolean; + parent_uid: string; + _version: number; + title: string; + publish_details: ${prefix}PublishDetails; + }`, + `export interface ${prefix}Link { + title: string; + href: string; + }` + ] + if (systemFields) { + defaultInterfaces.push( + `export interface ${prefix}SystemFields { + uid?: string; + created_at?: string; + updated_at?: string; + created_by?: string; + updated_by?: string; + _content_type_uid?: string; + tags?: string[]; + ACL?: any[]; + _version?: number; + _in_progress?: boolean; + locale?: string; + publish_details?: ${prefix}PublishDetails[]; + title?: string; + }`) + } + return defaultInterfaces; +} diff --git a/src/lib/stack/schema.ts b/src/lib/stack/schema.ts index 0fa18a4..42f122e 100644 --- a/src/lib/stack/schema.ts +++ b/src/lib/stack/schema.ts @@ -27,6 +27,7 @@ export type Block = { export type GlobalField = { reference_to: string; schema: Schema; + schema_type?: string; } & FieldOptions; export type ReferenceField = { diff --git a/src/lib/tsgen/factory.ts b/src/lib/tsgen/factory.ts index e794d39..cbdb098 100644 --- a/src/lib/tsgen/factory.ts +++ b/src/lib/tsgen/factory.ts @@ -8,6 +8,7 @@ export type TSGenOptions = { naming?: { prefix: string; }; + systemFields?: boolean; }; export type TSGenResult = { @@ -54,6 +55,7 @@ const defaultOptions: TSGenOptions = { naming: { prefix: '', }, + systemFields: false } export default function (userOptions: TSGenOptions) { @@ -115,9 +117,14 @@ export default function (userOptions: TSGenOptions) { } function define_interface( - contentType: ContentstackTypes.ContentType | ContentstackTypes.GlobalField + contentType: ContentstackTypes.ContentType | ContentstackTypes.GlobalField, + systemFields: boolean = false ) { - return ['export interface', name_type(contentType.data_type === 'global_field' ? (contentType.reference_to as string) : contentType.uid)].join(' ') + const interface_declaration = ['export interface', name_type(contentType.data_type === 'global_field' ? (contentType.reference_to as string) : contentType.uid)] + if (systemFields && contentType.schema_type !== "global_field") { + interface_declaration.push('extends', name_type('SystemFields')) + } + return interface_declaration.join(' ') } function op_array(type: string, field: ContentstackTypes.Field) { @@ -226,7 +233,7 @@ export default function (userOptions: TSGenOptions) { ) { return [ options.docgen.interface(contentType.description), - define_interface(contentType), + define_interface(contentType, options.systemFields), '{', visit_fields(contentType.schema), '}', diff --git a/src/lib/tsgen/runner.ts b/src/lib/tsgen/runner.ts index ab4ce11..b6df89e 100644 --- a/src/lib/tsgen/runner.ts +++ b/src/lib/tsgen/runner.ts @@ -26,7 +26,7 @@ function createOutputPath(outputFile: string) { return outputPath } -export default async function tsgenRunner(outputFile: string, contentTypes: any[], prefix = '', includeDocumentation = true) { +export default async function tsgenRunner(outputFile: string, contentTypes: any[], prefix = '', includeDocumentation = true, systemFields: boolean = false) { const docgen: DocumentationGenerator = includeDocumentation ? new JSDocumentationGenerator() : new NullDocumentationGenerator() const outputPath = createOutputPath(outputFile) @@ -38,6 +38,7 @@ export default async function tsgenRunner(outputFile: string, contentTypes: any[ naming: { prefix, }, + systemFields }) for (const contentType of contentTypes) { @@ -56,7 +57,7 @@ export default async function tsgenRunner(outputFile: string, contentTypes: any[ const output = await format( [ - defaultInterfaces(prefix).join('\n\n'), + defaultInterfaces(prefix, systemFields).join('\n\n'), [...globalFields].join('\n\n'), definitions.join('\n\n'), ].join('\n\n') From 04093f8e956fb9f9c5b7e34f8eb76c34d9b43884 Mon Sep 17 00:00:00 2001 From: Abhinav Gupta Date: Mon, 9 Oct 2023 12:36:49 +0530 Subject: [PATCH 2/8] fix: updated package version --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3347c68..bc9e5fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "contentstack-cli-tsgen", - "version": "2.1.6", + "version": "2.1.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "contentstack-cli-tsgen", - "version": "2.1.6", + "version": "2.1.7", "license": "MIT", "dependencies": { "@contentstack/cli-command": "^1.2.9", diff --git a/package.json b/package.json index 4b3d351..fca5bc3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "contentstack-cli-tsgen", "description": "Generate TypeScript typings from a Stack.", - "version": "2.1.6", + "version": "2.1.7", "author": "Michael Davis", "bugs": "https://github.com/Contentstack-Solutions/contentstack-cli-tsgen/issues", "dependencies": { From 3295788e643f1f49a6dbfc80c11bf52f567f8c11 Mon Sep 17 00:00:00 2001 From: Abhinav Gupta Date: Mon, 9 Oct 2023 12:43:45 +0530 Subject: [PATCH 3/8] fix: fixed eslint issue --- src/commands/tsgen.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/commands/tsgen.ts b/src/commands/tsgen.ts index a3434f5..94f6aa9 100644 --- a/src/commands/tsgen.ts +++ b/src/commands/tsgen.ts @@ -54,8 +54,8 @@ export default class TypeScriptCodeGeneratorCommand extends Command { 'include-system-fields': flags.boolean({ description: 'include system fields in generated types', - default: false - }) + default: false, + }), }; async run() { From 0d2d498979fbc20c4e6eb0d4f7dfbce9959ab914 Mon Sep 17 00:00:00 2001 From: Abhinav Gupta Date: Tue, 10 Oct 2023 18:50:17 +0530 Subject: [PATCH 4/8] fix: removed boolean type for boolean literal --- src/lib/stack/builtins.ts | 2 +- src/lib/tsgen/factory.ts | 2 +- src/lib/tsgen/runner.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/stack/builtins.ts b/src/lib/stack/builtins.ts index a6b73b1..902aa88 100644 --- a/src/lib/stack/builtins.ts +++ b/src/lib/stack/builtins.ts @@ -1,5 +1,5 @@ // File and Link fields are additional, non-scalar, data types within a stack. -export const defaultInterfaces = (prefix = '', systemFields: boolean = false) => { +export const defaultInterfaces = (prefix = '', systemFields = false) => { const defaultInterfaces = [ `export interface ${prefix}PublishDetails { environment: string; diff --git a/src/lib/tsgen/factory.ts b/src/lib/tsgen/factory.ts index f90cd9e..7d9c3b6 100644 --- a/src/lib/tsgen/factory.ts +++ b/src/lib/tsgen/factory.ts @@ -118,7 +118,7 @@ export default function (userOptions: TSGenOptions) { function define_interface( contentType: ContentstackTypes.ContentType | ContentstackTypes.GlobalField, - systemFields: boolean = false + systemFields = false ) { const interface_declaration = ['export interface', name_type(contentType.data_type === 'global_field' ? (contentType.reference_to as string) : contentType.uid)] if (systemFields && contentType.schema_type !== "global_field") { diff --git a/src/lib/tsgen/runner.ts b/src/lib/tsgen/runner.ts index b6df89e..3bd902c 100644 --- a/src/lib/tsgen/runner.ts +++ b/src/lib/tsgen/runner.ts @@ -26,7 +26,7 @@ function createOutputPath(outputFile: string) { return outputPath } -export default async function tsgenRunner(outputFile: string, contentTypes: any[], prefix = '', includeDocumentation = true, systemFields: boolean = false) { +export default async function tsgenRunner(outputFile: string, contentTypes: any[], prefix = '', includeDocumentation = true, systemFields = false) { const docgen: DocumentationGenerator = includeDocumentation ? new JSDocumentationGenerator() : new NullDocumentationGenerator() const outputPath = createOutputPath(outputFile) From 787752c78fdb409758624a91b9b32a4092316ce4 Mon Sep 17 00:00:00 2001 From: Vikram Kalta Date: Wed, 11 Oct 2023 16:02:52 +0100 Subject: [PATCH 5/8] fix: handling for ref multiple flag --- src/lib/stack/schema.ts | 7 ++++++- src/lib/tsgen/factory.ts | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/lib/stack/schema.ts b/src/lib/stack/schema.ts index 0fa18a4..0b11501 100644 --- a/src/lib/stack/schema.ts +++ b/src/lib/stack/schema.ts @@ -49,7 +49,8 @@ export type Field = GlobalField & ReferenceField & GroupField & EnumField & - BlockField; + BlockField & + { field_metadata: FieldMetaData }; export type Schema = Array; export type ContentType = { @@ -60,3 +61,7 @@ export type ContentType = { data_type?: string; schema_type?: string; } & Identifier; + +export type FieldMetaData = { + ref_multiple?: boolean; +} diff --git a/src/lib/tsgen/factory.ts b/src/lib/tsgen/factory.ts index e794d39..43af655 100644 --- a/src/lib/tsgen/factory.ts +++ b/src/lib/tsgen/factory.ts @@ -300,7 +300,7 @@ export default function (userOptions: TSGenOptions) { references.push(name_type(field.reference_to)) } - return ['(', references.join(' | '), ')', '[]'].join('') + return ['(', references.join(' | '), ')', field.field_metadata?.ref_multiple ? '[]' : ''].join('') } return function (contentType: ContentstackTypes.ContentType): TSGenResult|any { From 2f019a786e2c00b10c41295a73e97574a11e1191 Mon Sep 17 00:00:00 2001 From: Vikram Kalta Date: Wed, 11 Oct 2023 16:04:32 +0100 Subject: [PATCH 6/8] fix: bumped version --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3347c68..bc9e5fa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "contentstack-cli-tsgen", - "version": "2.1.6", + "version": "2.1.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "contentstack-cli-tsgen", - "version": "2.1.6", + "version": "2.1.7", "license": "MIT", "dependencies": { "@contentstack/cli-command": "^1.2.9", diff --git a/package.json b/package.json index 4b3d351..fca5bc3 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "contentstack-cli-tsgen", "description": "Generate TypeScript typings from a Stack.", - "version": "2.1.6", + "version": "2.1.7", "author": "Michael Davis", "bugs": "https://github.com/Contentstack-Solutions/contentstack-cli-tsgen/issues", "dependencies": { From 750e6c5f2cab86febecf35149b4f00ef6ad0d303 Mon Sep 17 00:00:00 2001 From: Aman Kumar Date: Thu, 19 Oct 2023 10:44:29 +0530 Subject: [PATCH 7/8] refactor: version bump --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index bc9e5fa..f816be8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "contentstack-cli-tsgen", - "version": "2.1.7", + "version": "2.1.8", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "contentstack-cli-tsgen", - "version": "2.1.7", + "version": "2.1.8", "license": "MIT", "dependencies": { "@contentstack/cli-command": "^1.2.9", diff --git a/package.json b/package.json index 280593a..d9892fb 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "contentstack-cli-tsgen", "description": "Generate TypeScript typings from a Stack.", - "version": "2.1.7", + "version": "2.1.8", "author": "Michael Davis", "bugs": "https://github.com/Contentstack-Solutions/contentstack-cli-tsgen/issues", "dependencies": { From e69ace7f7d1892976b2475acea74da482ba2db1d Mon Sep 17 00:00:00 2001 From: Aman Kumar Date: Thu, 19 Oct 2023 13:16:13 +0530 Subject: [PATCH 8/8] fix: reference test cases --- tests/tsgen/references.test.ts | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/tests/tsgen/references.test.ts b/tests/tsgen/references.test.ts index 0d70a5d..acf9d7b 100644 --- a/tests/tsgen/references.test.ts +++ b/tests/tsgen/references.test.ts @@ -1,27 +1,27 @@ -const testData = require('./references.ct') +const testData = require("./references.ct"); -import NullDocumentationGenerator from '../../src/lib/tsgen/docgen/nulldoc' -import tsgenFactory from '../../src/lib/tsgen/factory' +import NullDocumentationGenerator from "../../src/lib/tsgen/docgen/nulldoc"; +import tsgenFactory from "../../src/lib/tsgen/factory"; const tsgen = tsgenFactory({ docgen: new NullDocumentationGenerator(), naming: { - prefix: 'I', + prefix: "I", }, -}) +}); -describe('references', () => { - const result = tsgen(testData.references) +describe("references", () => { + const result = tsgen(testData.references); - test('metadata', () => { - const contentTypes = [...result.metadata.dependencies.contentTypes] + test("metadata", () => { + const contentTypes = [...result.metadata.dependencies.contentTypes]; expect(contentTypes).toEqual( - expect.arrayContaining(['IReferenceChild', 'IBoolean', 'IBuiltinExample']) - ) - }) + expect.arrayContaining(["IReferenceChild", "IBoolean", "IBuiltinExample"]) + ); + }); - test('definition', () => { + test("definition", () => { expect(result.definition).toMatchInlineSnapshot(` "export interface IReferenceParent { @@ -29,9 +29,9 @@ describe('references', () => { version: 5 ; title: string; url: string; - single_reference: (IReferenceChild)[]; + single_reference: (IReferenceChild); multiple_reference?: (IReferenceChild | IBoolean | IBuiltinExample)[]; }" - `) - }) -}) + `); + }); +});