From 17b7a317a44f38c7ea44913b152ad1ba804bf025 Mon Sep 17 00:00:00 2001 From: Joe Martin Date: Mon, 3 Jun 2024 11:09:41 -0400 Subject: [PATCH] feat: Add support for enum key name prefix --- languages/c/src/types/NativeHelpers.mjs | 9 ++---- src/macrofier/types.mjs | 8 ++--- src/shared/json-schema.mjs | 41 +++++++++++++++---------- src/validate/index.mjs | 6 ++-- 4 files changed, 33 insertions(+), 31 deletions(-) diff --git a/languages/c/src/types/NativeHelpers.mjs b/languages/c/src/types/NativeHelpers.mjs index 061f30b8..57aab2dd 100644 --- a/languages/c/src/types/NativeHelpers.mjs +++ b/languages/c/src/types/NativeHelpers.mjs @@ -60,7 +60,7 @@ const getNativeType = (json, fireboltString = false) => { } else if (jsonType === 'null' ) { type = 'void' - } + } return type } @@ -125,18 +125,13 @@ const getArrayAccessors = (arrayName, propertyType, valueType) => { return res } -const enumValue = (val,prefix) => { - const keyName = getSafeEnumKeyName(val) - return ` ${prefix.toUpperCase()}_${keyName.toUpperCase()}` -} - const generateEnum = (schema, prefix)=> { if (!schema.enum) { return '' } else { let str = `typedef enum {\n` - str += schema.enum.map(e => enumValue(e, prefix)).join(',\n') + str += schema.enum.map(e => getSafeEnumKeyName(val, prefix)).join(',\n') str += `\n} ${prefix};\n` return str } diff --git a/src/macrofier/types.mjs b/src/macrofier/types.mjs index 55ef7b7e..d036cd97 100644 --- a/src/macrofier/types.mjs +++ b/src/macrofier/types.mjs @@ -226,8 +226,8 @@ const insertEnumMacros = (content, schema, module, name, suffix, templateDir = " schema.enum.map(value => { if (!value) { value = getTemplate(path.join(templateDir, 'unset' + suffix)) - } - value ? values.push(template[i].replace(/\$\{key\}/g, getSafeEnumKeyName(value)) + } + value ? values.push(template[i].replace(/\$\{key\}/g, getSafeEnumKeyName(value, schema.enumKeyPrefix)) .replace(/\$\{value\}/g, value)) : '' }) template[i] = values.map((value, id) => { @@ -543,7 +543,7 @@ function getSchemaShape(schema = {}, module = {}, { templateDir = 'types', paren const suffix = destination && ('.' + destination.split('.').pop()) || '' const theTitle = insertSchemaMacros(getTemplate(path.join(templateDir, 'title' + suffix)), schema, module, { name: schema.title, parent, property, required, recursive: false }) - let result = getTemplate(path.join(templateDir, 'default' + suffix)) || '${shape}' + let result = getTemplate(path.join(templateDir, 'default' + suffix)) || '${shape}' let genericTemplate = getTemplate(path.join(templateDir, 'generic' + suffix)) if (enums && level === 0 && Array.isArray(schema.enum) && ((schema.type === "string") || (schema.type[0] === "string"))) { @@ -852,7 +852,7 @@ function getSchemaType(schema, module, { destination, templateDir = 'types', lin const shape = insertAnyOfMacros(getTemplate(path.join(templateDir, 'anyOf' + suffix)), schema, module, theTitle) return insertSchemaMacros(shape, schema, module, { name: theTitle, recursive: false }) - + // if (event) { // return getSchemaType((schema.oneOf || schema.anyOf)[0], module, { destination, link, title, code, asPath, baseUrl }) // } diff --git a/src/shared/json-schema.mjs b/src/shared/json-schema.mjs index 5d1d3a27..7af03e3e 100644 --- a/src/shared/json-schema.mjs +++ b/src/shared/json-schema.mjs @@ -42,7 +42,7 @@ const objectPaths = obj => { return isObject(value) ? product.concat(paths(value, fullPath)) : product.concat(fullPath) - }, []) : [] + }, []) : [] } return paths(obj); } @@ -100,7 +100,7 @@ const replaceUri = (existing, replacement, schema) => { Object.keys(schema).forEach(key => { replaceUri(existing, replacement, schema[key]) }) - } + } } const replaceRef = (existing, replacement, schema) => { @@ -176,7 +176,7 @@ function getSchemaConstraints(schema, module, options = { delimiter: '\n' }) { typeof schema.exclusiveMinimum === 'number' ? constraints.push(`exclusiveMinimum: ${schema.exclusiveMinimum}`) : null typeof schema.multipleOf === 'number' ? constraints.push(`multipleOf: ${schema.multipleOf}`) : null - return constraints.join(options.delimiter) + return constraints.join(options.delimiter) } else if (schema.type === 'array' && schema.items) { let constraints = [] @@ -188,7 +188,7 @@ function getSchemaConstraints(schema, module, options = { delimiter: '\n' }) { constraints = [getSchemaConstraints(schema.items, module, options)] } - return constraints.join(options.delimiter) + return constraints.join(options.delimiter) } else if (schema.oneOf || schema.anyOf) { return '' //See OpenRPC Schema for `oneOf` and `anyOf` details' @@ -228,7 +228,7 @@ const localizeDependencies = (json, document, schemas = {}, options = defaultLoc if (!options.externalOnly) { while (refs.length > 0) { for (let i=0; i 1) { @@ -241,7 +241,7 @@ const localizeDependencies = (json, document, schemas = {}, options = defaultLoc resolvedSchema = { "$REF": ref} unresolvedRefs.push([...path]) } - + if (path.length) { // don't loose examples from original object w/ $ref // todo: should we preserve other things, like title? @@ -252,22 +252,22 @@ const localizeDependencies = (json, document, schemas = {}, options = defaultLoc else { delete definition['$ref'] Object.assign(definition, resolvedSchema) - } + } } } refs = getLocalSchemaPaths(definition) } } - + refs = getExternalSchemaPaths(definition) while (refs.length > 0) { for (let i=0; i value.split(':').pop() // use last portion of urn:style:values - .replace(/[\.\-]/g, '_') // replace dots and dashes - .replace(/\+/g, '_plus') // change + to _plus - .replace(/([a-z])([A-Z0-9])/g, '$1_$2') // camel -> snake case - .replace(/^([0-9]+(\.[0-9]+)?)/, 'v$1') // insert `v` in front of things that look like version numbers - .toUpperCase() +const getSafeEnumKeyName = function(value, keyPrefix = '') { + if (keyPrefix != '') { + value = keyPrefix + '_' + value + } + + let key = value.split(':').pop() // use last portion of urn:style:values + .replace(/\+/g, '_plus') // change + to _plus + .replace(/[\.\-\/\;]/g, '_') // replace special characters + .replace(/([a-z])([A-Z0-9])/g, '$1_$2') // camel -> snake case + .replace(/^([0-9]+\_([0-9]+)?)/, 'v$1') // insert `v` in front of things that look like version numbers + + return key.toUpperCase() +} export { getSchemaConstraints, @@ -450,4 +457,4 @@ export { removeIgnoredAdditionalItems, mergeAnyOf, mergeOneOf -} +} diff --git a/src/validate/index.mjs b/src/validate/index.mjs index f9002554..0b4d426a 100644 --- a/src/validate/index.mjs +++ b/src/validate/index.mjs @@ -108,7 +108,7 @@ const run = async ({ addFormats(ajv) // explicitly add our custom extensions so we can keep strict mode on (TODO: put these in a JSON config?) - ajv.addVocabulary(['x-method', 'x-this-param', 'x-additional-params', 'x-schemas', 'components', 'x-property']) + ajv.addVocabulary(['x-method', 'x-this-param', 'x-additional-params', 'x-schemas', 'components', 'x-property', 'enumKeyPrefix']) const firebolt = ajv.compile(fireboltOpenRpcSpec) const jsonschema = ajv.compile(jsonSchemaSpec) @@ -151,7 +151,7 @@ const run = async ({ } }) - const examples = ajv.compile(exampleSpec) + const examples = ajv.compile(exampleSpec) let result = validate(json, {}, ajv, jsonschema) let exampleResult = validate(json, {}, ajv, examples) @@ -301,4 +301,4 @@ const run = async ({ return Promise.resolve() } -export default run \ No newline at end of file +export default run