From ebf85f77e0338635adc952b8c5b9024235013809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rebecca=20K=C3=B6nig?= Date: Wed, 26 Apr 2023 13:22:44 +0200 Subject: [PATCH] fix: import skeleton for links in v10 types (#251) --- src/property-imports.ts | 2 +- src/renderer/type/create-default-context.ts | 2 + src/renderer/type/create-v10-context.ts | 3 + .../type/default-content-type-renderer.ts | 4 ++ .../type/content-type-renderer.test.ts | 66 ++++++++++++++++++- test/renderer/type/js-doc-renderer.test.ts | 15 ++--- .../type/v10-content-type-renderer.test.ts | 62 +++++++++++++++++ 7 files changed, 140 insertions(+), 14 deletions(-) diff --git a/src/property-imports.ts b/src/property-imports.ts index 414f196..da06b28 100644 --- a/src/property-imports.ts +++ b/src/property-imports.ts @@ -13,7 +13,7 @@ export const propertyImports = ( const moduleImport = (module: string): OptionalKind => { return { moduleSpecifier: `./${context.moduleName(module)}`, - namedImports: [context.moduleFieldsName(module)], + namedImports: [context.moduleReferenceName(module)], isTypeOnly: true, }; }; diff --git a/src/renderer/type/create-default-context.ts b/src/renderer/type/create-default-context.ts index b14fc97..235d937 100644 --- a/src/renderer/type/create-default-context.ts +++ b/src/renderer/type/create-default-context.ts @@ -7,6 +7,7 @@ export type RenderContext = { getFieldRenderer: (fieldType: FType) => FieldRenderer; moduleName: (id: string) => string; moduleFieldsName: (id: string) => string; + moduleReferenceName: (id: string) => string; moduleSkeletonName: (id: string) => string; imports: Set>; }; @@ -16,6 +17,7 @@ export const createDefaultContext = (): RenderContext => { moduleName, moduleFieldsName, moduleSkeletonName, + moduleReferenceName: moduleFieldsName, getFieldRenderer: (fieldType: FType) => defaultRenderers[fieldType] as FieldRenderer, imports: new Set(), diff --git a/src/renderer/type/create-v10-context.ts b/src/renderer/type/create-v10-context.ts index 021d3cb..0efe083 100644 --- a/src/renderer/type/create-v10-context.ts +++ b/src/renderer/type/create-v10-context.ts @@ -2,11 +2,13 @@ import { ContentTypeFieldType } from 'contentful'; import { ImportDeclarationStructure, OptionalKind } from 'ts-morph'; import { FieldRenderer, v10Renderers } from '../field'; import { createDefaultContext } from './create-default-context'; +import { moduleSkeletonName } from '../../module-name'; export type RenderContext = { getFieldRenderer: (fieldType: FType) => FieldRenderer; moduleName: (id: string) => string; moduleFieldsName: (id: string) => string; + moduleReferenceName: (id: string) => string; moduleSkeletonName: (id: string) => string; imports: Set>; }; @@ -14,6 +16,7 @@ export type RenderContext = { export const createV10Context = (): RenderContext => { return { ...createDefaultContext(), + moduleReferenceName: moduleSkeletonName, getFieldRenderer: (fieldType: FType) => v10Renderers[fieldType] as FieldRenderer, }; diff --git a/src/renderer/type/default-content-type-renderer.ts b/src/renderer/type/default-content-type-renderer.ts index 013e219..3caf118 100644 --- a/src/renderer/type/default-content-type-renderer.ts +++ b/src/renderer/type/default-content-type-renderer.ts @@ -23,6 +23,10 @@ export class DefaultContentTypeRenderer extends BaseContentTypeRenderer { for (const structure of context.imports) { file.addImportDeclaration(structure); } + + file.organizeImports({ + ensureNewLineAtEndOfFile: true, + }); } protected renderFieldsInterface( diff --git a/test/renderer/type/content-type-renderer.test.ts b/test/renderer/type/content-type-renderer.test.ts index 1440d06..21b7fab 100644 --- a/test/renderer/type/content-type-renderer.test.ts +++ b/test/renderer/type/content-type-renderer.test.ts @@ -14,6 +14,66 @@ import { } from '../../../src'; import stripIndent = require('strip-indent'); +describe('The default content type renderer', () => { + let project: Project; + let testFile: SourceFile; + + beforeEach(() => { + project = new Project({ + useInMemoryFileSystem: true, + compilerOptions: { + target: ScriptTarget.ES5, + declaration: true, + }, + }); + testFile = project.createSourceFile('test.ts'); + }); + + it('adds import for field type', () => { + const renderer = new DefaultContentTypeRenderer(); + + const contentType: CFContentType = { + name: 'unused-name', + sys: { + id: 'test', + type: 'Symbol', + }, + fields: [ + { + id: 'linkFieldId', + name: 'Linked entry Field', + type: 'Link', + localized: false, + required: true, + validations: [ + { + linkContentType: ['linkedType'], + }, + ], + disabled: false, + omitted: false, + linkType: 'Entry', + }, + ], + }; + + renderer.render(contentType, testFile); + + expect('\n' + testFile.getFullText()).toEqual( + stripIndent(` + import type { Entry } from "contentful"; + import type { TypeLinkedTypeFields } from "./TypeLinkedType"; + + export interface TypeTestFields { + linkFieldId: Entry; + } + + export type TypeTest = Entry; + `), + ); + }); +}); + describe('A derived content type renderer class', () => { let project: Project; let testFile: SourceFile; @@ -39,6 +99,7 @@ describe('A derived content type renderer class', () => { return { moduleName, moduleFieldsName, + moduleReferenceName: moduleFieldsName, moduleSkeletonName, getFieldRenderer: (fieldType: FType) => { if (fieldType === 'Symbol') { @@ -139,8 +200,7 @@ describe('A derived content type renderer class', () => { expect('\n' + testFile.getFullText()).toEqual( stripIndent(` - import type { EntryFields } from "contentful"; - import type { Entry } from "contentful"; + import type { Entry, EntryFields } from "contentful"; export interface TypeTestFields { /** Field of type "Symbol" */ @@ -194,8 +254,8 @@ describe('A derived content type renderer class', () => { expect('\n' + testFile.getFullText()).toEqual( stripIndent(` - import type { EntryFields } from "contentful"; import type { IdScopedEntry } from "@custom"; + import type { EntryFields } from "contentful"; export interface TypeTestFields { field_id: EntryFields.Symbol; diff --git a/test/renderer/type/js-doc-renderer.test.ts b/test/renderer/type/js-doc-renderer.test.ts index 2744fbf..d981860 100644 --- a/test/renderer/type/js-doc-renderer.test.ts +++ b/test/renderer/type/js-doc-renderer.test.ts @@ -59,8 +59,7 @@ describe('A JSDoc content type renderer class', () => { expect('\n' + testFile.getFullText()).toEqual( stripIndent(` - import type { EntryFields } from "contentful"; - import type { Entry } from "contentful"; + import type { Entry, EntryFields } from "contentful"; /** * Fields type definition for content type 'TypeAnimal' @@ -148,8 +147,7 @@ describe('A JSDoc content type renderer class', () => { expect('\n' + testFile.getFullText()).toEqual( stripIndent(` - import type { EntryFields } from "contentful"; - import type { Entry } from "contentful"; + import type { Entry, EntryFields } from "contentful"; /** * Fields type definition for content type 'TypeAnimal' @@ -191,8 +189,7 @@ describe('A JSDoc content type renderer class', () => { expect('\n' + testFile.getFullText()).toEqual( stripIndent(` - import type { EntryFields } from "contentful"; - import type { Entry } from "contentful"; + import type { Entry, EntryFields } from "contentful"; /** * Fields type definition for content type 'TypeAnimal' @@ -234,8 +231,7 @@ describe('A JSDoc content type renderer class', () => { expect('\n' + testFile.getFullText()).toEqual( stripIndent(` - import type { EntryFields } from "contentful"; - import type { Entry } from "contentful"; + import type { Entry, EntryFields } from "contentful"; /** * Fields type definition for content type 'TypeAnimal' @@ -285,8 +281,7 @@ describe('A JSDoc content type renderer class', () => { expect('\n' + testFile.getFullText()).toEqual( stripIndent(` - import type { EntryFields } from "contentful"; - import type { Entry } from "contentful"; + import type { Entry, EntryFields } from "contentful"; /** * Fields type definition for content type 'TypeAnimal' diff --git a/test/renderer/type/v10-content-type-renderer.test.ts b/test/renderer/type/v10-content-type-renderer.test.ts index 896f197..0dde4b1 100644 --- a/test/renderer/type/v10-content-type-renderer.test.ts +++ b/test/renderer/type/v10-content-type-renderer.test.ts @@ -14,6 +14,67 @@ import { } from '../../../src'; import stripIndent = require('strip-indent'); +describe('The v10 content type renderer', () => { + let project: Project; + let testFile: SourceFile; + + beforeEach(() => { + project = new Project({ + useInMemoryFileSystem: true, + compilerOptions: { + target: ScriptTarget.ES5, + declaration: true, + }, + }); + testFile = project.createSourceFile('test.ts'); + }); + + it('adds import for skeleton type', () => { + const renderer = new V10ContentTypeRenderer(); + + const contentType: CFContentType = { + name: 'unused-name', + sys: { + id: 'test', + type: 'Symbol', + }, + fields: [ + { + id: 'linkFieldId', + name: 'Linked entry Field', + type: 'Link', + localized: false, + required: true, + validations: [ + { + linkContentType: ['linkedType'], + }, + ], + disabled: false, + omitted: false, + linkType: 'Entry', + }, + ], + }; + + renderer.render(contentType, testFile); + + expect('\n' + testFile.getFullText()).toEqual( + stripIndent(` + import type { ChainModifiers, Entry, EntryFieldTypes, EntrySkeletonType, LocaleCode } from "contentful"; + import type { TypeLinkedTypeSkeleton } from "./TypeLinkedType"; + + export interface TypeTestFields { + linkFieldId: EntryFieldTypes.EntryLink; + } + + export type TypeTestSkeleton = EntrySkeletonType; + export type TypeTest = Entry; + `), + ); + }); +}); + describe('A derived content type renderer class', () => { let project: Project; let testFile: SourceFile; @@ -39,6 +100,7 @@ describe('A derived content type renderer class', () => { return { moduleName, moduleFieldsName, + moduleReferenceName: moduleSkeletonName, moduleSkeletonName, getFieldRenderer: (fieldType: FType) => { if (fieldType === 'Symbol') {