diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index 0a038dc5..f70d1930 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -814,6 +814,7 @@ importers: '@types/uuid': ~9.0.2 '@typescript-eslint/parser': ~5.59.2 ajv: ^8.12.0 + es-toolkit: ^1.26.1 eslint: ^8.40.0 eslint-import-resolver-typescript: ~3.5.5 eslint-plugin-import: ~2.27.5 @@ -827,6 +828,7 @@ importers: dependencies: '@kickstartds/jsonschema-utils': link:../jsonschema-utils ajv: 8.12.0 + es-toolkit: 1.26.1 object-traversal: 1.0.1 uuid: 9.0.1 devDependencies: @@ -4593,6 +4595,10 @@ packages: is-symbol: 1.0.4 dev: true + /es-toolkit/1.26.1: + resolution: {integrity: sha512-E3H14lHWk8JpupVpIRA1gfNF4r953abHTFW+X1Rp7zl7eG37ksuthfEA4FinyVF/Y807vzzfQS1nubeZk2LTVA==} + dev: false + /es5-ext/0.10.62: resolution: {integrity: sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==} engines: {node: '>=0.10'} diff --git a/examples/storyblok/src/index.ts b/examples/storyblok/src/index.ts index 99646599..8c910af6 100644 --- a/examples/storyblok/src/index.ts +++ b/examples/storyblok/src/index.ts @@ -1,4 +1,4 @@ -import { mkdirSync, writeFileSync } from 'node:fs'; +import { mkdirSync, readFileSync, writeFileSync } from 'node:fs'; import { default as path } from 'node:path'; import { fileURLToPath } from 'node:url'; @@ -58,9 +58,11 @@ async function convertDsAgency(): Promise { } }); + const existingConfig = JSON.parse(readFileSync(`resources/config.json`, 'utf-8')); + mkdirSync('dist/agency', { recursive: true }); - const configString = configuration(convertedObjects); + const configString = configuration(convertedObjects, existingConfig); writeFileSync(`dist/agency/components.123456.json`, configString); } diff --git a/tools/jsonschema2storyblok/package.json b/tools/jsonschema2storyblok/package.json index a179bdbd..30523f42 100644 --- a/tools/jsonschema2storyblok/package.json +++ b/tools/jsonschema2storyblok/package.json @@ -20,6 +20,7 @@ "dependencies": { "@kickstartds/jsonschema-utils": "workspace:*", "ajv": "^8.12.0", + "es-toolkit": "^1.26.1", "object-traversal": "^1.0.1", "uuid": "~9.0.0" }, diff --git a/tools/jsonschema2storyblok/src/@types/index.ts b/tools/jsonschema2storyblok/src/@types/index.ts index bede5ef1..da29ca81 100644 --- a/tools/jsonschema2storyblok/src/@types/index.ts +++ b/tools/jsonschema2storyblok/src/@types/index.ts @@ -2,6 +2,7 @@ // Storyblok types stem from here: https://github.com/dohomi/storyblok-generate-ts/blob/master/src/typings.ts // Related Storyblok docs: // - https://www.storyblok.com/docs/api/management#core-resources/components/components +// - https://www.storyblok.com/docs/api/management/core-resources/components/the-component-schema-field-object // - https://www.storyblok.com/docs/schema-configuration export type GenericType = diff --git a/tools/jsonschema2storyblok/src/index.ts b/tools/jsonschema2storyblok/src/index.ts index 17dd6cad..9516056f 100644 --- a/tools/jsonschema2storyblok/src/index.ts +++ b/tools/jsonschema2storyblok/src/index.ts @@ -10,7 +10,9 @@ import { IConvertParams, getSchemaName } from '@kickstartds/jsonschema-utils'; +import { mergeWith } from 'es-toolkit'; import { type JSONSchema, TypeName } from 'json-schema-typed/draft-07'; +import { traverse } from 'object-traversal'; import { v4 as uuidv4 } from 'uuid'; import { GenericType, ITypeMapping, IStoryblokSchemaElement, IStoryblokBlock } from './@types/index.js'; @@ -87,13 +89,44 @@ export function configuration( components: [], templates: [], globals: [] - } + }, + existingConfig?: { components: IStoryblokBlock[] } ): string { - return JSON.stringify( - { components: [...converted.components, ...converted.templates, ...converted.globals] }, - null, - 2 - ); + const config = { components: [...converted.components, ...converted.templates, ...converted.globals] }; + + if (existingConfig) { + traverse(existingConfig, ({ key, parent }) => { + if (key?.startsWith('tab-') && parent) { + delete parent[key]; + } + }); + + for (const component of config.components) { + const existingComponent = existingConfig.components.find((c) => c.name === component.name); + if (existingComponent) { + mergeWith(existingComponent, component, (targetValue, sourceValue, key) => { + if (['id', '_uid', 'pos', 'component_group_uuid', 'image', 'created_at'].includes(key)) + return targetValue ?? sourceValue; + + if (key === 'options' && Array.isArray(targetValue) && Array.isArray(sourceValue)) { + return sourceValue.map((option) => { + const existingOption = targetValue.find((o) => o.name === option.name); + if (existingOption) { + return { ...option, _uid: existingOption._uid }; + } + return option; + }); + } + }); + } else { + existingConfig.components.push(component); + } + } + + return JSON.stringify(existingConfig, null, 2); + } + + return JSON.stringify(config, null, 2); } /** diff --git a/tools/jsonschema2storyblok/tsconfig.json b/tools/jsonschema2storyblok/tsconfig.json index b2c69eeb..93c08f96 100644 --- a/tools/jsonschema2storyblok/tsconfig.json +++ b/tools/jsonschema2storyblok/tsconfig.json @@ -1,7 +1,7 @@ { "extends": "./node_modules/@rushstack/heft-node-rig/profiles/default/tsconfig-base.json", "compilerOptions": { - "lib": ["es2021"], + "lib": ["es2021", "dom"], "target": "es2021", "module": "node16", "moduleResolution": "node16",