Skip to content

Commit

Permalink
finos#486 clean up functions and split property instantiation
Browse files Browse the repository at this point in the history
  • Loading branch information
willosborne committed Oct 25, 2024
1 parent f39875b commit c67aa39
Show file tree
Hide file tree
Showing 7 changed files with 37 additions and 78 deletions.
8 changes: 6 additions & 2 deletions cli/src/commands/generate/components/instantiate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Logger } from "winston";
import { initLogger } from "../../helper.js";
import { SchemaDirectory } from "../schema-directory.js";
import { appendPath, logRequiredMessage, mergeSchemas, renderPath } from "../util.js";
import { getPropertyValue } from "./property.js";
import { getConstValue, getPropertyValue } from "./property.js";

export function instantiateGenericObject(definition: object, schemaDirectory: SchemaDirectory, objectType: string, path: string[], debug: boolean = false, instantiateAll: boolean = false): object {
const logger = initLogger(debug);
Expand All @@ -13,6 +13,7 @@ export function instantiateGenericObject(definition: object, schemaDirectory: Sc

fullDefinition = mergeSchemas(schemaDef, definition);
}
// TODO rework to properly separate 'verbose' from 'debug' level logging
// logger.debug('Generating ' + objectType + ' object from ' + JSON.stringify(fullDefinition));

if (!('properties' in fullDefinition)) {
Expand All @@ -28,11 +29,14 @@ export function instantiateGenericObject(definition: object, schemaDirectory: Sc
const renderedPath = renderPath(currentPath);

if (!instantiateAll && required && !required.includes(key)) { // TODO should we always do interfaces even if not required?
if (key === 'interfaces') {
logger.warn(`${renderedPath}: 'interfaces' property was not marked as required. You might be missing some values if this object has interfaces defined.`)
}
logger.debug(`${renderedPath}: Skipping property ${key} as it is not marked as required.`);
continue;
}
if (!!detail?.const) {
out[key] = getPropertyValue(key, detail);
out[key] = getConstValue(detail);
}
else if (detail?.type === 'object') {
// recursive instantiation
Expand Down
1 change: 0 additions & 1 deletion cli/src/commands/generate/components/metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { initLogger } from '../../helper.js';
import { SchemaDirectory } from '../schema-directory.js';
import { appendPath, logRequiredMessage, mergeSchemas } from '../util.js';
import { instantiateGenericObject } from './instantiate.js';
import { getPropertyValue } from './property.js';

export function instantiateMetadataObject(definition: object, schemaDirectory: SchemaDirectory, path: string[], debug: boolean = false, instantiateAll: boolean = false): object {
return instantiateGenericObject(definition, schemaDirectory, 'metadata', path, debug, instantiateAll);
Expand Down
2 changes: 1 addition & 1 deletion cli/src/commands/generate/components/node.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

import { SchemaDirectory } from '../schema-directory';
import { instantiateNodeInterfaces, instantiateNodes } from './node';
import { instantiateNodes } from './node';

jest.mock('../../helper', () => {
return {
Expand Down
54 changes: 0 additions & 54 deletions cli/src/commands/generate/components/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { initLogger } from '../../helper.js';
import { SchemaDirectory } from '../schema-directory.js';
import { appendPath, logRequiredMessage, mergeSchemas } from '../util.js';
import { instantiateGenericObject } from './instantiate.js';
import { getPropertyValue } from './property.js';

/**
* Instantiate an individual node from its definition, resolving $refs if appropriate.
Expand Down Expand Up @@ -41,57 +40,4 @@ export function instantiateNodes(pattern: any, schemaDirectory: SchemaDirectory,
outputNodes.push(instantiateNode(node, schemaDirectory, path, debug, instantiateAll));
}
return outputNodes;
}

// TODO remove all this
/**
* Instantiate an individual interface on a node.
* @param interfaceDef The definition of the interface.
* @param schemaDirectory The schema directory to resolve refs against.
* @param debug Whether to log debug detail.
* @returns An instantiated interface.
*/
export function instantiateInterface(interfaceDef: object, schemaDirectory: SchemaDirectory, debug: boolean = false, instantiateAll: boolean = false): object {
const logger = initLogger(debug);
let fullDefinition = interfaceDef;
if (interfaceDef['$ref']) {
const ref = interfaceDef['$ref'];
const schemaDef = schemaDirectory.getDefinition(ref);

fullDefinition = mergeSchemas(schemaDef, interfaceDef);
}

logger.debug('Generating interface from ' + JSON.stringify(fullDefinition, undefined, 2));

if (!('properties' in fullDefinition)) {
return {};
}

const required = fullDefinition['required'];
logRequiredMessage(logger, required, instantiateAll);

const out = {};
for (const [key, detail] of Object.entries(fullDefinition['properties'])) {
if (!instantiateAll && required && !required.includes(key)) {
logger.debug('Skipping property ' + key + ' as it is not marked as required.');
continue;
}
out[key] = getPropertyValue(key, detail);
}

return out;
}

export function instantiateNodeInterfaces(detail: any, schemaDirectory: SchemaDirectory, debug: boolean = false, instantiateAll: boolean = false): any[] {
const interfaces = [];
if (!('prefixItems' in detail)) {
return [];
}

const interfaceDefs = detail.prefixItems;
for (const interfaceDef of interfaceDefs) {
interfaces.push(instantiateInterface(interfaceDef, schemaDirectory, debug, instantiateAll));
}

return interfaces;
}
39 changes: 21 additions & 18 deletions cli/src/commands/generate/components/property.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */

import { getPropertyValue } from './property';
import { getConstValue, getPropertyValue } from './property';

jest.mock('../../helper', () => {
return {
Expand All @@ -13,30 +13,16 @@ jest.mock('../../helper', () => {
};
});

describe('getPropertyValue', () => {
it('generates string placeholder name from variable', () => {
expect(getPropertyValue('key-name', {
'type': 'string'
}))
.toBe('{{ KEY_NAME }}');
});

it('generates integer placeholder from variable', () => {
expect(getPropertyValue('key-name', {
'type': 'integer'
}))
.toBe(-1);
});

describe('getConstValue', () => {
it('generates const value if const is provided', () => {
expect(getPropertyValue('key-name', {
expect(getConstValue({
'const': 'Example value'
}))
.toBe('Example value');
});

it('generates const value with entire subtree if const is provided', () => {
expect(getPropertyValue('key-name', {
expect(getConstValue({
'const': {
'connects': {
'source': 'source',
Expand All @@ -51,6 +37,23 @@ describe('getPropertyValue', () => {
}
});
});
})

describe('getPropertyValue', () => {
it('generates string placeholder name from variable', () => {
expect(getPropertyValue('key-name', {
'type': 'string'
}))
.toBe('{{ KEY_NAME }}');
});

it('generates integer placeholder from variable', () => {
expect(getPropertyValue('key-name', {
'type': 'integer'
}))
.toBe(-1);
});


it('generates array with single string placeholder', () => {
expect(getPropertyValue('key-name', {
Expand Down
10 changes: 9 additions & 1 deletion cli/src/commands/generate/components/property.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,16 @@ interface Detail {
$ref?: string
}

/**
* Simply return the value of the const object when instantiating a const.
* @param detail The detail from the object to instantiate
* @returns Either the value or the object described by the 'const' property.
*/
export function getConstValue(detail: Detail) : string | object {
return detail.const;
}

export function getPropertyValue(keyName: string, detail: Detail): string | string[] | number | object {
// should be able to instantiate not just a simple enum type but also a whole sub-object
// if both const and type are defined, prefer const
if (detail.const) {
return detail.const;
Expand Down
1 change: 0 additions & 1 deletion cli/src/commands/generate/components/relationship.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { initLogger } from '../../helper.js';
import { SchemaDirectory } from '../schema-directory.js';
import { appendPath, logRequiredMessage, mergeSchemas } from '../util.js';
import { instantiateGenericObject } from './instantiate.js';
import { getPropertyValue } from './property.js';


/**
Expand Down

0 comments on commit c67aa39

Please sign in to comment.