From 296b4f16a5ff73328e5e09ff5ac152b89fa7a0bc Mon Sep 17 00:00:00 2001 From: Dipankar Maikap <45673791+dipankarmaikap@users.noreply.github.com> Date: Fri, 7 Nov 2025 17:57:43 +0530 Subject: [PATCH 1/8] feat(cli): add datasources types to the cli types generate command --- .../src/commands/types/generate/actions.ts | 41 +++++++++++++++++-- .../cli/src/commands/types/generate/index.ts | 29 +++++++++---- packages/cli/src/types/schemas.ts | 1 + 3 files changed, 61 insertions(+), 10 deletions(-) diff --git a/packages/cli/src/commands/types/generate/actions.ts b/packages/cli/src/commands/types/generate/actions.ts index 1189a20ab..11c3a9afd 100644 --- a/packages/cli/src/commands/types/generate/actions.ts +++ b/packages/cli/src/commands/types/generate/actions.ts @@ -21,6 +21,8 @@ const DEFAULT_TYPEDEFS_HEADER = [ '// This file was generated by the storyblok CLI.', '// DO NOT MODIFY THIS FILE BY HAND.', ]; +const getDatasourceTypeTitle = (slug: string) => + `${toPascalCase(slug)}DataSource`; const getPropertyTypeAnnotation = (property: ComponentPropertySchema, prefix?: string, suffix?: string) => { // If a property type is one of the ones provided by Storyblok, return that type @@ -191,7 +193,13 @@ const getComponentPropertiesTypeAnnotations = async ( const componentType = toPascalCase(propertyType); propertyTypeAnnotation[key].tsType = `Storyblok${componentType}`; } + if (spaceData.datasources.length > 0 && schema.source === 'internal' && schema?.datasource_slug) { + const type = getDatasourceTypeTitle(schema.datasource_slug); + // Assign type based on whether it's single or multiple selection + propertyTypeAnnotation[key].tsType + = propertyType === 'options' ? `${type}[]` : type; + } if (propertyType === 'multilink') { const excludedLinktypes: string[] = [ ...(!schema.email_link_type ? ['{ linktype?: "email" }'] : []), @@ -306,6 +314,7 @@ export const generateTypes = async ( try { const typeDefs = [...DEFAULT_TYPEDEFS_HEADER]; const storyblokPropertyTypes = new Set(); + const contentTypeBloks = new Set(); let customFieldsParser: ((key: string, value: Record) => Record) | undefined; let compilerOptions: Record | undefined; // Custom fields parser @@ -317,10 +326,13 @@ export const generateTypes = async ( if (options.compilerOptions) { compilerOptions = await loadCompilerOptions(options.compilerOptions); } - - const schemas = await Promise.all(spaceData.components.map(async (component) => { + const componentsSchema = spaceData.components.map(async (component) => { // Get the component type name with proper handling of numbers at the start const type = getComponentType(component.name, options); + // Add all the Content Type and Universial Blok to contentTypeBloks + if (component.is_root) { + contentTypeBloks.add(type); + } const componentPropertiesTypeAnnotations = await getComponentPropertiesTypeAnnotations(component, options, spaceData, customFieldsParser); const requiredFields = Object.entries(component?.schema || {}).reduce( (acc: string[], [key, value]) => { @@ -363,7 +375,30 @@ export const generateTypes = async ( }; return componentSchema; - })); + }); + const datasourcesSchema = spaceData.datasources.map(async (datasource) => { + const enumValues: string[] | undefined = datasource.entries + ?.filter(d => d.value) + .map(d => d.value!); + const datasourceSchema: JSONSchema = { + $id: `#/${datasource.slug}`, + title: getDatasourceTypeTitle(datasource.slug), + type: 'string', + enum: enumValues, + }; + return datasourceSchema; + }); + const contentTypeSchema: JSONSchema = { + $id: `#/ContentType`, + title: 'ContentType', + type: 'string', + tsType: `${Array.from(contentTypeBloks).join(' | ')}`, + }; + const schemas = await Promise.all([ + ...componentsSchema, + ...datasourcesSchema, + contentTypeSchema, + ]); const result = await Promise.all(schemas.map(async (schema) => { // Use the title as the interface name diff --git a/packages/cli/src/commands/types/generate/index.ts b/packages/cli/src/commands/types/generate/index.ts index 8e9c54fea..8fc03239a 100644 --- a/packages/cli/src/commands/types/generate/index.ts +++ b/packages/cli/src/commands/types/generate/index.ts @@ -7,6 +7,9 @@ import type { GenerateTypesOptions } from './constants'; import type { ReadComponentsOptions } from '../../components/push/constants'; import { typesCommand } from '../command'; import { generateStoryblokTypes, generateTypes, saveTypesToComponentsFile } from './actions'; +import { readDatasourcesFiles } from '../../datasources/push/actions'; +import type { SpaceDatasourcesData } from '../../../commands/datasources/constants'; +import type { ReadDatasourcesOptions } from './../../datasources/push/constants'; const program = getProgram(); @@ -38,23 +41,35 @@ typesCommand try { spinner.start(`Generating types...`); - const spaceData = await readComponentsFiles({ - ...options as ReadComponentsOptions, + const componentsData = await readComponentsFiles({ + ...(options as ReadComponentsOptions), from: space, path, }); - + // Try to read datasources, but make it optional + let dataSourceData: SpaceDatasourcesData; + try { + dataSourceData = await readDatasourcesFiles({ + ...(options as ReadDatasourcesOptions), + from: space, + path, + }); + } + catch { + // If no datasources found, use empty array + dataSourceData = { datasources: [] }; + } await generateStoryblokTypes({ path, }); // Add empty datasources array to match expected type for generateTypes - const spaceDataWithDatasources: ComponentsData & { datasources: [] } = { - ...spaceData, - datasources: [], + const spaceDataWithComponentsAndDatasources: ComponentsData & SpaceDatasourcesData = { + ...componentsData, + ...dataSourceData, }; - const typedefString = await generateTypes(spaceDataWithDatasources, { + const typedefString = await generateTypes(spaceDataWithComponentsAndDatasources, { ...options, path, }); diff --git a/packages/cli/src/types/schemas.ts b/packages/cli/src/types/schemas.ts index 6abf6064e..cf2d49f53 100644 --- a/packages/cli/src/types/schemas.ts +++ b/packages/cli/src/types/schemas.ts @@ -35,6 +35,7 @@ export interface ComponentPropertySchema { restrict_components?: boolean; restrict_type?: 'groups' | 'components' | 'tags' | ''; source?: 'internal' | 'external' | 'internal_stories' | 'internal_languages'; + datasource_slug?: string; type: ComponentPropertySchemaType; use_uuid?: boolean; }; From a2b420e8fc191aba06d2e70e0ad2a619a645c036 Mon Sep 17 00:00:00 2001 From: Dipankar Maikap <45673791+dipankarmaikap@users.noreply.github.com> Date: Wed, 12 Nov 2025 11:54:55 +0530 Subject: [PATCH 2/8] chore(cli): cleanup generate type test file reuses the mock data --- .../src/commands/types/generate/index.test.ts | 186 ++---------------- 1 file changed, 20 insertions(+), 166 deletions(-) diff --git a/packages/cli/src/commands/types/generate/index.test.ts b/packages/cli/src/commands/types/generate/index.test.ts index e49847458..ba447a45c 100644 --- a/packages/cli/src/commands/types/generate/index.test.ts +++ b/packages/cli/src/commands/types/generate/index.test.ts @@ -9,6 +9,26 @@ import '../index'; import { typesCommand } from '../command'; import { readComponentsFiles } from '../../components/push/actions'; +const mockResponse = [{ + name: 'component-name', + display_name: 'Component Name', + created_at: '2021-08-09T12:00:00Z', + updated_at: '2021-08-09T12:00:00Z', + id: 12345, + schema: { type: 'object' }, + color: undefined, + internal_tags_list: [], + internal_tag_ids: [], +}]; + +const mockSpaceData = { + components: mockResponse, + groups: [], + presets: [], + internalTags: [], + datasources: [], +}; + vi.mock('./actions', () => ({ generateStoryblokTypes: vi.fn(), generateTypes: vi.fn(), @@ -75,26 +95,6 @@ describe('types generate', () => { describe('default mode', () => { it('should prompt the user if the operation was sucessfull', async () => { - const mockResponse = [{ - name: 'component-name', - display_name: 'Component Name', - created_at: '2021-08-09T12:00:00Z', - updated_at: '2021-08-09T12:00:00Z', - id: 12345, - schema: { type: 'object' }, - color: null, - internal_tags_list: [], - internal_tag_ids: [], - }]; - - const mockSpaceData = { - components: mockResponse, - groups: [], - presets: [], - internalTags: [], - datasources: [], - }; - session().state = { isLoggedIn: true, password: 'valid-token', @@ -120,26 +120,6 @@ describe('types generate', () => { }); it('should pass strict mode option to generateTypes when --strict flag is used', async () => { - const mockResponse = [{ - name: 'component-name', - display_name: 'Component Name', - created_at: '2021-08-09T12:00:00Z', - updated_at: '2021-08-09T12:00:00Z', - id: 12345, - schema: { type: 'object' }, - color: null, - internal_tags_list: [], - internal_tag_ids: [], - }]; - - const mockSpaceData = { - components: mockResponse, - groups: [], - presets: [], - internalTags: [], - datasources: [], - }; - session().state = { isLoggedIn: true, password: 'valid-token', @@ -161,26 +141,6 @@ describe('types generate', () => { }); it('should pass typePrefix option to generateTypes when --type-prefix flag is used', async () => { - const mockResponse = [{ - name: 'component-name', - display_name: 'Component Name', - created_at: '2021-08-09T12:00:00Z', - updated_at: '2021-08-09T12:00:00Z', - id: 12345, - schema: { type: 'object' }, - color: null, - internal_tags_list: [], - internal_tag_ids: [], - }]; - - const mockSpaceData = { - components: mockResponse, - groups: [], - presets: [], - internalTags: [], - datasources: [], - }; - session().state = { isLoggedIn: true, password: 'valid-token', @@ -202,32 +162,6 @@ describe('types generate', () => { }); it('should pass typeSuffix option to generateTypes when --type-suffix flag is used', async () => { - const mockResponse = [{ - name: 'component-name', - display_name: 'Component Name', - created_at: '2021-08-09T12:00:00Z', - updated_at: '2021-08-09T12:00:00Z', - id: 12345, - schema: { type: 'object' }, - color: null, - internal_tags_list: [], - internal_tag_ids: [], - }]; - - const mockSpaceData = { - components: mockResponse, - groups: [], - presets: [], - internalTags: [], - datasources: [], - }; - - session().state = { - isLoggedIn: true, - password: 'valid-token', - region: 'eu', - }; - vi.mocked(readComponentsFiles).mockResolvedValue(mockSpaceData); vi.mocked(generateStoryblokTypes).mockResolvedValue(true); vi.mocked(generateTypes).mockResolvedValue('// Generated types'); @@ -243,26 +177,6 @@ describe('types generate', () => { }); it('should pass suffix option to generateTypes when --suffix flag is used', async () => { - const mockResponse = [{ - name: 'component-name', - display_name: 'Component Name', - created_at: '2021-08-09T12:00:00Z', - updated_at: '2021-08-09T12:00:00Z', - id: 12345, - schema: { type: 'object' }, - color: null, - internal_tags_list: [], - internal_tag_ids: [], - }]; - - const mockSpaceData = { - components: mockResponse, - groups: [], - presets: [], - internalTags: [], - datasources: [], - }; - session().state = { isLoggedIn: true, password: 'valid-token', @@ -284,26 +198,6 @@ describe('types generate', () => { }); it('should pass separateFiles option to generateTypes when --separate-files flag is used', async () => { - const mockResponse = [{ - name: 'component-name', - display_name: 'Component Name', - created_at: '2021-08-09T12:00:00Z', - updated_at: '2021-08-09T12:00:00Z', - id: 12345, - schema: { type: 'object' }, - color: null, - internal_tags_list: [], - internal_tag_ids: [], - }]; - - const mockSpaceData = { - components: mockResponse, - groups: [], - presets: [], - internalTags: [], - datasources: [], - }; - session().state = { isLoggedIn: true, password: 'valid-token', @@ -325,26 +219,6 @@ describe('types generate', () => { }); it('should pass customFieldsParser option to generateTypes when --custom-fields-parser flag is used', async () => { - const mockResponse = [{ - name: 'component-name', - display_name: 'Component Name', - created_at: '2021-08-09T12:00:00Z', - updated_at: '2021-08-09T12:00:00Z', - id: 12345, - schema: { type: 'object' }, - color: null, - internal_tags_list: [], - internal_tag_ids: [], - }]; - - const mockSpaceData = { - components: mockResponse, - groups: [], - presets: [], - internalTags: [], - datasources: [], - }; - session().state = { isLoggedIn: true, password: 'valid-token', @@ -366,26 +240,6 @@ describe('types generate', () => { }); it('should pass compilerOptions option to generateTypes when --compiler-options flag is used', async () => { - const mockResponse = [{ - name: 'component-name', - display_name: 'Component Name', - created_at: '2021-08-09T12:00:00Z', - updated_at: '2021-08-09T12:00:00Z', - id: 12345, - schema: { type: 'object' }, - color: null, - internal_tags_list: [], - internal_tag_ids: [], - }]; - - const mockSpaceData = { - components: mockResponse, - groups: [], - presets: [], - internalTags: [], - datasources: [], - }; - session().state = { isLoggedIn: true, password: 'valid-token', From 2032d03c5237b4cac9df80715783ea7944fe18e9 Mon Sep 17 00:00:00 2001 From: Dipankar Maikap <45673791+dipankarmaikap@users.noreply.github.com> Date: Mon, 17 Nov 2025 14:03:07 +0530 Subject: [PATCH 3/8] fix(cli): resolve component schema before generating content type schema --- packages/cli/src/commands/types/generate/actions.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/commands/types/generate/actions.ts b/packages/cli/src/commands/types/generate/actions.ts index 11c3a9afd..b25a6d1ca 100644 --- a/packages/cli/src/commands/types/generate/actions.ts +++ b/packages/cli/src/commands/types/generate/actions.ts @@ -388,17 +388,19 @@ export const generateTypes = async ( }; return datasourceSchema; }); + const resolvedComponentsSchema = await Promise.all(componentsSchema); + const resolvedDatasourcesSchema = await Promise.all(datasourcesSchema); const contentTypeSchema: JSONSchema = { $id: `#/ContentType`, title: 'ContentType', type: 'string', tsType: `${Array.from(contentTypeBloks).join(' | ')}`, }; - const schemas = await Promise.all([ - ...componentsSchema, - ...datasourcesSchema, + const schemas = [ + ...resolvedComponentsSchema, + ...resolvedDatasourcesSchema, contentTypeSchema, - ]); + ]; const result = await Promise.all(schemas.map(async (schema) => { // Use the title as the interface name From 450d1afe386ba1a41946a02c0e2d249666796d9d Mon Sep 17 00:00:00 2001 From: Dipankar Maikap <45673791+dipankarmaikap@users.noreply.github.com> Date: Mon, 17 Nov 2025 15:47:40 +0530 Subject: [PATCH 4/8] test(cli): datasource type generation test added --- .../commands/types/generate/actions.test.ts | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/packages/cli/src/commands/types/generate/actions.test.ts b/packages/cli/src/commands/types/generate/actions.test.ts index f62cc495c..faa295918 100644 --- a/packages/cli/src/commands/types/generate/actions.test.ts +++ b/packages/cli/src/commands/types/generate/actions.test.ts @@ -747,6 +747,73 @@ describe('component property type annotations', () => { expect(result).toContain('colorPicker?:'); expect(result).toContain('color: string'); }); + it('should handle datasource property type', async () => { + // Create a component with boolean property type + const componentWithDatasourceeType: SpaceComponent = { + name: 'test_component', + display_name: 'Test Component', + created_at: '2023-01-01T00:00:00Z', + updated_at: '2023-01-01T00:00:00Z', + id: 1, + schema: { + sex: { + type: 'option', + pos: 1, + use_uuid: true, + source: 'internal', + datasource_slug: 'garden-325', + id: '679gCtyCRbKrTlUkXBHw7w', + }, + }, + internal_tags_list: [], + internal_tag_ids: [], + }; + + // Create a space data with this component + const spaceData: SpaceComponentsData = { + components: [componentWithDatasourceeType], + datasources: [{ + id: 109556769159015, + name: 'Garden-325', + slug: 'garden-325', + dimensions: [], + created_at: '2025-11-06T13:47:38.095Z', + updated_at: '2025-11-06T13:47:38.095Z', + entries: [ + { + id: 109556771421284, + datasource_id: 109556769159015, + name: 'deform-206', + value: 'deform-206', + dimension_value: '', + }, + { + id: 109556773588069, + datasource_id: 109556769159015, + name: 'because-854', + value: 'because-854', + dimension_value: '', + }, + { + id: 109556775738470, + datasource_id: 109556769159015, + name: 'even-218', + value: 'even-218', + dimension_value: '', + }, + ], + }], + groups: [], + presets: [], + internalTags: [], + }; + + // Generate types + const result = await generateTypes(spaceData, { strict: false }); + // Verify that the result contains the expected property type + expect(result).toContain('sex?: Garden325DataSource'); + expect(result).toContain('export type Garden325DataSource = "deform-206" | "because-854" | "even-218";'); + }); }); describe('generateStoryblokTypes', () => { From 171daf4faa65fbc7b2f0e92cdcbc926774cd5962 Mon Sep 17 00:00:00 2001 From: Dipankar Maikap <45673791+dipankarmaikap@users.noreply.github.com> Date: Mon, 17 Nov 2025 16:00:08 +0530 Subject: [PATCH 5/8] fix(cli): when there is no content type bloks generate never as type --- packages/cli/src/commands/types/generate/actions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cli/src/commands/types/generate/actions.ts b/packages/cli/src/commands/types/generate/actions.ts index b25a6d1ca..6bd50b7bd 100644 --- a/packages/cli/src/commands/types/generate/actions.ts +++ b/packages/cli/src/commands/types/generate/actions.ts @@ -394,7 +394,7 @@ export const generateTypes = async ( $id: `#/ContentType`, title: 'ContentType', type: 'string', - tsType: `${Array.from(contentTypeBloks).join(' | ')}`, + tsType: contentTypeBloks.size > 0 ? `${Array.from(contentTypeBloks).join(' | ')}` : 'never', }; const schemas = [ ...resolvedComponentsSchema, From f92b169559a2de8098e4ee5bceaac93dbb888cda Mon Sep 17 00:00:00 2001 From: Dipankar Maikap <45673791+dipankarmaikap@users.noreply.github.com> Date: Mon, 17 Nov 2025 16:10:28 +0530 Subject: [PATCH 6/8] fix(cli): if the local datasources does not have the value dont use the datasource type --- .../cli/src/commands/types/generate/actions.ts | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/packages/cli/src/commands/types/generate/actions.ts b/packages/cli/src/commands/types/generate/actions.ts index 6bd50b7bd..3a4043009 100644 --- a/packages/cli/src/commands/types/generate/actions.ts +++ b/packages/cli/src/commands/types/generate/actions.ts @@ -194,11 +194,16 @@ const getComponentPropertiesTypeAnnotations = async ( propertyTypeAnnotation[key].tsType = `Storyblok${componentType}`; } if (spaceData.datasources.length > 0 && schema.source === 'internal' && schema?.datasource_slug) { - const type = getDatasourceTypeTitle(schema.datasource_slug); - - // Assign type based on whether it's single or multiple selection - propertyTypeAnnotation[key].tsType - = propertyType === 'options' ? `${type}[]` : type; + // Check if the datasource actually exists in spaceData.datasources + const datasourceExists = spaceData.datasources.some(ds => ds.slug === schema.datasource_slug); + if (datasourceExists) { + const type = getDatasourceTypeTitle(schema.datasource_slug); + // Assign type based on whether it's single or multiple selection + propertyTypeAnnotation[key].tsType + = propertyType === 'options' ? `${type}[]` : type; + } + // If datasource doesn't exist, fall back to default number | string union type + // The type annotation already has the correct fallback from getPropertyTypeAnnotation } if (propertyType === 'multilink') { const excludedLinktypes: string[] = [ From 9b0085b8908ee19731251cd3a80326d035080d67 Mon Sep 17 00:00:00 2001 From: Dipankar Maikap <45673791+dipankarmaikap@users.noreply.github.com> Date: Tue, 18 Nov 2025 11:26:33 +0530 Subject: [PATCH 7/8] fix(cli): fix typo in variable name and add warning when datasource have same typename as componnet --- .../cli/src/commands/types/generate/actions.test.ts | 4 ++-- packages/cli/src/commands/types/generate/actions.ts | 7 ++++++- packages/cli/src/commands/types/generate/index.ts | 13 +++++++++---- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/packages/cli/src/commands/types/generate/actions.test.ts b/packages/cli/src/commands/types/generate/actions.test.ts index faa295918..c08c9e4e5 100644 --- a/packages/cli/src/commands/types/generate/actions.test.ts +++ b/packages/cli/src/commands/types/generate/actions.test.ts @@ -749,7 +749,7 @@ describe('component property type annotations', () => { }); it('should handle datasource property type', async () => { // Create a component with boolean property type - const componentWithDatasourceeType: SpaceComponent = { + const componentWithDatasourceType: SpaceComponent = { name: 'test_component', display_name: 'Test Component', created_at: '2023-01-01T00:00:00Z', @@ -771,7 +771,7 @@ describe('component property type annotations', () => { // Create a space data with this component const spaceData: SpaceComponentsData = { - components: [componentWithDatasourceeType], + components: [componentWithDatasourceType], datasources: [{ id: 109556769159015, name: 'Garden-325', diff --git a/packages/cli/src/commands/types/generate/actions.ts b/packages/cli/src/commands/types/generate/actions.ts index 3a4043009..0a93b48ff 100644 --- a/packages/cli/src/commands/types/generate/actions.ts +++ b/packages/cli/src/commands/types/generate/actions.ts @@ -385,9 +385,14 @@ export const generateTypes = async ( const enumValues: string[] | undefined = datasource.entries ?.filter(d => d.value) .map(d => d.value!); + const type = getDatasourceTypeTitle(datasource.slug); + // Check for conflicts with existing component types + if (storyblokPropertyTypes.has(type)) { + console.warn(`Warning: Datasource type "${type}" conflicts with existing component type`); + } const datasourceSchema: JSONSchema = { $id: `#/${datasource.slug}`, - title: getDatasourceTypeTitle(datasource.slug), + title: type, type: 'string', enum: enumValues, }; diff --git a/packages/cli/src/commands/types/generate/index.ts b/packages/cli/src/commands/types/generate/index.ts index 8fc03239a..71506350b 100644 --- a/packages/cli/src/commands/types/generate/index.ts +++ b/packages/cli/src/commands/types/generate/index.ts @@ -1,5 +1,5 @@ import { colorPalette, commands } from '../../../constants'; -import { handleError, isVitest, konsola } from '../../../utils'; +import { FileSystemError, handleError, isVitest, konsola } from '../../../utils'; import { getProgram } from '../../../program'; import { Spinner } from '@topcli/spinner'; import { type ComponentsData, readComponentsFiles } from '../../components/push/actions'; @@ -55,9 +55,14 @@ typesCommand path, }); } - catch { - // If no datasources found, use empty array - dataSourceData = { datasources: [] }; + catch (error) { + // Only catch the specific case where datasources don't exist + if (error instanceof FileSystemError && error.errorId === 'file_not_found') { + dataSourceData = { datasources: [] }; + } + else { + throw error; + } } await generateStoryblokTypes({ path, From 43b109e21aa856ca0894ca0ffbdd09995e9e5ba2 Mon Sep 17 00:00:00 2001 From: Dipankar Maikap <45673791+dipankarmaikap@users.noreply.github.com> Date: Tue, 18 Nov 2025 11:44:04 +0530 Subject: [PATCH 8/8] fix(cli): get all generated componnets types and compare with datasource type --- packages/cli/src/commands/types/generate/actions.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/cli/src/commands/types/generate/actions.ts b/packages/cli/src/commands/types/generate/actions.ts index 0a93b48ff..bd8923a8e 100644 --- a/packages/cli/src/commands/types/generate/actions.ts +++ b/packages/cli/src/commands/types/generate/actions.ts @@ -381,13 +381,17 @@ export const generateTypes = async ( return componentSchema; }); + const resolvedComponentsSchema = await Promise.all(componentsSchema); + const datasourcesSchema = spaceData.datasources.map(async (datasource) => { + const allComponentTypes = resolvedComponentsSchema.map(schema => schema.title); + const enumValues: string[] | undefined = datasource.entries ?.filter(d => d.value) .map(d => d.value!); const type = getDatasourceTypeTitle(datasource.slug); // Check for conflicts with existing component types - if (storyblokPropertyTypes.has(type)) { + if (allComponentTypes.includes(type)) { console.warn(`Warning: Datasource type "${type}" conflicts with existing component type`); } const datasourceSchema: JSONSchema = { @@ -398,8 +402,8 @@ export const generateTypes = async ( }; return datasourceSchema; }); - const resolvedComponentsSchema = await Promise.all(componentsSchema); const resolvedDatasourcesSchema = await Promise.all(datasourcesSchema); + const contentTypeSchema: JSONSchema = { $id: `#/ContentType`, title: 'ContentType',