Skip to content

Commit 0d4902f

Browse files
committed
feature: update layering in schema utils
1 parent 377c5fa commit 0d4902f

File tree

5 files changed

+75
-14
lines changed

5 files changed

+75
-14
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@kickstartds/jsonschema-utils",
5+
"comment": "update layering of schemas to be more generic",
6+
"type": "minor"
7+
}
8+
],
9+
"packageName": "@kickstartds/jsonschema-utils"
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@kickstartds/jsonschema2storyblok",
5+
"comment": "update layering in utils",
6+
"type": "patch"
7+
}
8+
],
9+
"packageName": "@kickstartds/jsonschema2storyblok"
10+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@kickstartds/storyblok-example",
5+
"comment": "update layering in utils",
6+
"type": "patch"
7+
}
8+
],
9+
"packageName": "@kickstartds/storyblok-example"
10+
}

examples/storyblok/src/index.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,10 @@ async function convertDsAgency(): Promise<void> {
1919
const customGlob = `${packagePath}/(dist|cms)/**/*.(schema|definitions|interface).json`;
2020

2121
const ajv = getSchemaRegistry();
22-
await processSchemaGlob(customGlob, ajv);
22+
await processSchemaGlob(customGlob, ajv, {
23+
hideCmsFields: true,
24+
layerOrder: ['cms', 'schema', 'kickstartds']
25+
});
2326

2427
const convertedObjects = convert({
2528
schemaIds: [
@@ -72,7 +75,9 @@ async function convertKds(): Promise<void> {
7275
const customGlob = `${packagePath}/(dist|cms)/**/*.(schema|definitions|interface).json`;
7376

7477
const ajv = getSchemaRegistry();
75-
const schemaIds = await processSchemaGlob(customGlob, ajv, { hideCmsFields: true });
78+
const schemaIds = await processSchemaGlob(customGlob, ajv, {
79+
hideCmsFields: true
80+
});
7681
const customSchemaIds = getCustomSchemaIds(schemaIds);
7782

7883
const convertedObjects = convert({

tools/jsonschema-utils/src/helpers.ts

Lines changed: 38 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,37 @@ export function getSortedSchemas(graph: SchemaDirectedGraph): JSONSchema.Interfa
588588
return sortedVertices.map((vertex) => vertex.data || {}).reverse();
589589
}
590590

591+
export function layerSchemas(sortedSchemas: JSONSchema.Interface[], layerOrder: string[]): void {
592+
const schemasByLayer = sortedSchemas.reduce<Record<string, JSONSchema.Interface[]>>((acc, jsonSchema) => {
593+
const layerName = jsonSchema.$id?.includes('schema.kickstartds.com')
594+
? 'kickstartds'
595+
: jsonSchema.$id?.split('//')[1].split('.')[0];
596+
if (!layerName)
597+
throw new Error(`Failed to get layer name from schema $id ${jsonSchema.$id} for layering`);
598+
if (!layerOrder.includes(layerName))
599+
throw new Error(`Layer name ${layerName} not included in layer order: ${layerOrder}`);
600+
601+
if (!acc[layerName]) acc[layerName] = [];
602+
acc[layerName].push(jsonSchema);
603+
604+
return acc;
605+
}, {});
606+
607+
for (const layer of layerOrder) {
608+
if (layerOrder.indexOf(layer) === layerOrder.length - 1) continue;
609+
if (!schemasByLayer[layer] || schemasByLayer[layer].length < 1) continue;
610+
611+
for (const deeperLayer of layerOrder.slice(layerOrder.indexOf(layer) + 1).reverse()) {
612+
layerRefs(
613+
schemasByLayer[layer],
614+
schemasByLayer[deeperLayer].filter(
615+
(schema) => !schemasByLayer[layer].some((s) => s.$id === schema.$id)
616+
)
617+
);
618+
}
619+
}
620+
}
621+
591622
export interface IProcessingOptions {
592623
typeResolution: boolean;
593624
modules: string[];
@@ -600,6 +631,7 @@ export interface IProcessingOptions {
600631
addExplicitAnyOfs: boolean;
601632
replaceExamples: boolean;
602633
hideCmsFields: boolean;
634+
layerOrder: string[];
603635
}
604636

605637
export const defaultProcessingOptions: IProcessingOptions = {
@@ -613,7 +645,8 @@ export const defaultProcessingOptions: IProcessingOptions = {
613645
inlineReferences: true,
614646
addExplicitAnyOfs: true,
615647
replaceExamples: true,
616-
hideCmsFields: false
648+
hideCmsFields: false,
649+
layerOrder: ['cms', 'schema', 'kickstartds']
617650
};
618651

619652
export async function processSchemaGlob(
@@ -655,7 +688,8 @@ export async function processSchemas(
655688
inlineReferences: shouldInlineReferences,
656689
addExplicitAnyOfs: shouldAddExlicitAnyOfs,
657690
replaceExamples: shouldReplaceExamples,
658-
hideCmsFields: shouldHideCmsFields
691+
hideCmsFields: shouldHideCmsFields,
692+
layerOrder
659693
} = { ...defaultProcessingOptions, ...options };
660694
// Load all the schema files provided by `@kickstartDS` itself...
661695
const kdsSchemas =
@@ -684,20 +718,11 @@ export async function processSchemas(
684718
(value: JSONSchema.Interface, index, self) => self.findIndex((v) => v.$id === value.$id) === index
685719
);
686720
const sortedSchemas = getSortedSchemas(getSchemaGraph(allSchemas));
687-
const cmsSchemas = sortedSchemas.filter((sortedSchema) => sortedSchema.$id?.startsWith('http://cms.'));
688721

689722
// Processing consists of 5 steps currently, that need to be run in this
690723
// exact order, because every step builds on the one before it
691724
// 1. pre-process, before schemas enter `ajv`
692-
if (shouldLayerRefs) {
693-
layerRefs(cmsSchemas, kdsSchemas);
694-
layerRefs(
695-
cmsSchemas,
696-
jsonSchemas.filter((schema) => !cmsSchemas.some((cmsSchema) => cmsSchema.$id === schema.$id))
697-
);
698-
layerRefs(jsonSchemas, kdsSchemas);
699-
}
700-
725+
if (shouldLayerRefs) layerSchemas(sortedSchemas, layerOrder);
701726
if (typeResolution) addTypeInterfaces(sortedSchemas);
702727
if (shouldInlineReferences) inlineReferences(sortedSchemas, typeResolution);
703728
if (additionalProperties && additionalProperties !== 'keep')
@@ -728,6 +753,7 @@ export async function processSchemas(
728753
reduceSchemaAllOfs(schemaAnyOf, ajv, shouldReplaceExamples);
729754
});
730755
if (shouldHideCmsFields) hideCmsFields(sortedSchemas);
756+
if (shouldHideCmsFields) hideCmsFields(schemaAnyOfs);
731757

732758
// 5. return list of processed schema `$id`s.
733759
// Accessing the full schemas works through `ajv`

0 commit comments

Comments
 (0)