Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/key name prefix #189

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions languages/c/src/types/NativeHelpers.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const getNativeType = (json, fireboltString = false) => {
}
else if (jsonType === 'null' ) {
type = 'void'
}
}
return type
}

Expand Down Expand Up @@ -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
}
Expand Down
6 changes: 3 additions & 3 deletions src/macrofier/engine.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -424,7 +424,7 @@ const promoteAndNameSubSchemas = (obj) => {
}
})
if (isSubSchema(method.result.schema)) {
addContentDescriptorSubSchema(method.result, '', obj)
addContentDescriptorSubSchema(method.result, '', obj)
}
else if (isEventMethod(method) && isSubSchema(getPayloadFromEvent(method))) {
// TODO: the `1` below is brittle... should find the index of the non-ListenResponse schema
Expand Down Expand Up @@ -1319,7 +1319,7 @@ function insertMethodMacros(template, methodObj, json, templates, type = '', exa
const pullsForParamType = pullsParams ? types.getSchemaType(pullsParams, json, { destination: state.destination, section: state.section }) : ''
const pullsForJsonType = pullsResult ? types.getSchemaType(pullsResult, json, { templateDir: 'json-types' }) : ''
const pullsForParamJsonType = pullsParams ? types.getSchemaType(pullsParams, json, { templateDir: 'json-types' }) : ''

const pullsEventParamName = event ? types.getSchemaInstantiation(event.result, json, event.name, { instantiationType: 'pull.param.name' }) : ''

let seeAlso = ''
Expand Down Expand Up @@ -1603,7 +1603,7 @@ function generateResultParams(result, json, templates, { name = '' } = {}) {
return Object.entries(result.properties).map( ([name, type]) => template
.replace(/\$\{method\.param\.name\}/g, name)
.replace(/\$\{method\.param\.type\}/g, types.getSchemaType(type, json, { moduleTitle: moduleTitle, result: true, namespace: true}))
).join(', ') // most languages separate params w/ a comma, so leaving this here for now
).join(', ') // most languages separate params w/ a comma, so leaving this here for now
}
// tuples get unwrapped
else if (config.unwrapResultObjects && result.type && result.type === 'array' && Array.isArray(result.items)) {
Expand Down
14 changes: 7 additions & 7 deletions src/macrofier/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ const macrofy = async (

const outputFiles = Object.fromEntries(Object.entries(await readFiles( staticCodeList, staticContent))
.map( ([n, v]) => [path.join(output, n), v]))

let primaryOutput = []

Object.keys(templates).forEach(file => {
Expand Down Expand Up @@ -220,7 +220,7 @@ const macrofy = async (

if (!checked.includes(entry)) {
imports = importedFiles(code, base)
checked.push(entry)
checked.push(entry)
}

imports = imports.map(imp => Array.from(new Set([imp, ...treeShake(imp, path.dirname(imp).substring(output.length), checked)]))).flat()
Expand All @@ -244,7 +244,7 @@ const macrofy = async (
// Grab all schema groups w/ a URI string. These came from some external json-schema that was bundled into the OpenRPC
const externalSchemas = {}
openrpc['x-schemas']
&& Object.entries(openrpc['x-schemas']).forEach(([name, schema]) => {
&& Object.entries(openrpc['x-schemas']).forEach(([name, schema]) => {
if (schema.uri) {
const id = schema.uri
externalSchemas[id] = externalSchemas[id] || { $id: id, info: {title: name }, methods: []}
Expand Down Expand Up @@ -278,19 +278,19 @@ const macrofy = async (
}
})
})

// Output any schema templates for each bundled external schema document
Object.values(externalSchemas).forEach( document => {
if (templatesPerSchema) {
templatesPerSchema.forEach( t => {
const macros = engine.generateMacros(document, templates, exampleTemplates, {hideExcluded: hideExcluded, createPolymorphicMethods: createPolymorphicMethods, destination: t})
let content = getTemplate('/schemas', t, templates)

// NOTE: whichever insert is called first also needs to be called again last, so each phase can insert recursive macros from the other
content = engine.insertMacros(content, macros)

const location = createModuleDirectories ? path.join(output, document.info.title, t) : path.join(output, t.replace(/module/, document.info.title.toLowerCase()).replace(/index/, document.info.title))

outputFiles[location] = content
logSuccess(`Generated macros for schema ${path.relative(output, location)}`)
})
Expand Down
8 changes: 4 additions & 4 deletions src/macrofier/types.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down Expand Up @@ -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"))) {
Expand Down Expand Up @@ -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 })
// }
Expand Down
41 changes: 24 additions & 17 deletions src/shared/json-schema.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ const objectPaths = obj => {
return isObject(value) ?
product.concat(paths(value, fullPath))
: product.concat(fullPath)
}, []) : []
}, []) : []
}
return paths(obj);
}
Expand Down Expand Up @@ -100,7 +100,7 @@ const replaceUri = (existing, replacement, schema) => {
Object.keys(schema).forEach(key => {
replaceUri(existing, replacement, schema[key])
})
}
}
}

const replaceRef = (existing, replacement, schema) => {
Expand Down Expand Up @@ -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 = []
Expand All @@ -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'
Expand Down Expand Up @@ -228,7 +228,7 @@ const localizeDependencies = (json, document, schemas = {}, options = defaultLoc
if (!options.externalOnly) {
while (refs.length > 0) {
for (let i=0; i<refs.length; i++) {
let path = refs[i]
let path = refs[i]
const ref = getPathOr(null, path, definition)
path.pop() // drop ref
if (refToPath(ref).length > 1) {
Expand All @@ -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?
Expand All @@ -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<refs.length; i++) {
let path = refs[i]
let path = refs[i]
const ref = getPathOr(null, path, definition)

path.pop() // drop ref
let resolvedSchema

if (!resolvedSchema) {
resolvedSchema = { "$REF": ref}
unresolvedRefs.push([...path])
Expand Down Expand Up @@ -426,12 +426,19 @@ function mergeOneOf(schema) {
return union(schema.oneOf)
}

const getSafeEnumKeyName = (value) => 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,
Expand All @@ -450,4 +457,4 @@ export {
removeIgnoredAdditionalItems,
mergeAnyOf,
mergeOneOf
}
}
34 changes: 17 additions & 17 deletions src/shared/typescript.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ function getMethodSignature(method, module, { destination, isInterface = false }

typescript += getMethodSignatureParams(method, module, { destination })
typescript += '): ' + (isSynchronous(method) ? getSchemaType(method.result.schema, module, {title: true}) : 'Promise<' + getSchemaType(method.result.schema, module, {title: true}) + '>')

return typescript
}

Expand Down Expand Up @@ -80,9 +80,9 @@ function getSchemaShape(schema = {}, module = {}, { name = '', level = 0, title,
}
else if (schema.type === 'object') {
let suffix = '{'

structure.push(' '.repeat(level) + `${prefix}${theTitle}${operator} ${suffix}`)

if (schema.properties) {
Object.entries(schema.properties).forEach(([name, prop]) => {
if (!schema.required || !schema.required.includes(name)) {
Expand All @@ -100,7 +100,7 @@ function getSchemaShape(schema = {}, module = {}, { name = '', level = 0, title,

if (schema.additionalProperties && (typeof schema.additionalProperties === 'object')) {
type = getSchemaType(schema.additionalProperties, module)
}
}

if (schema.patternProperties) {
Object.entries(schema.patternProperties).forEach(([pattern, schema]) => {
Expand All @@ -110,7 +110,7 @@ function getSchemaShape(schema = {}, module = {}, { name = '', level = 0, title,
}
})
}

structure.push(getSchemaShape({type: type}, module, {name: safeName(prop), descriptions: descriptions, level: level+1}))
})
}
Expand All @@ -119,7 +119,7 @@ function getSchemaShape(schema = {}, module = {}, { name = '', level = 0, title,
let type = getSchemaType(schema.additionalProperties, module, { destination })
structure.push(getSchemaShape({type: type}, module, {name: '[property: string]', descriptions: descriptions, level: level+1}))
}

structure.push(' '.repeat(level) + '}')
}
else if (schema.anyOf) {
Expand Down Expand Up @@ -155,11 +155,11 @@ function getSchemaShape(schema = {}, module = {}, { name = '', level = 0, title,
else if (schema.type || schema.const) {
const isArrayWithSchemaForItems = schema.type === 'array' && schema.items && !Array.isArray(schema.items)
const isArrayWithSpecificItems = schema.type === 'array' && schema.items && Array.isArray(schema.items)

// TODO: deal with fixed sized arrays vs arbitrary arrays
let suffix
let summary = ''

if (schema.const) {
suffix = JSON.stringify(schema.const)
}
Expand All @@ -172,26 +172,26 @@ function getSchemaShape(schema = {}, module = {}, { name = '', level = 0, title,
else {
suffix = getSchemaType(schema, module, { title: level ? true : false }) // prefer schema title over robust descriptor
}

// if there's a summary or description, append it as a comment (description only gets first line)
if (level > 0 && (summary || schema.description)) {
summary = `\t// ${summary || schema.description.split('\n')[0]}`
}

if (suffix === 'array') {
suffix = '[]'
}

if (theTitle === suffix) {
return ' '.repeat(level) + `${prefix}${theTitle}`
}
else {
return ' '.repeat(level) + `${prefix}${theTitle}${operator} ${suffix}${summary}`
}
}

structure = structure.join('\n').split('\n')

if (level === 0) {
const length = str => str.length
let max = Math.max(...structure.map(l => l.split('\t//')[0]).map(length)) + 2
Expand All @@ -202,7 +202,7 @@ function getSchemaShape(schema = {}, module = {}, { name = '', level = 0, title,

function getSchemaType(schema, module, { destination, link = false, title = false, code = false, asPath = false, event = false, expandEnums = true, baseUrl = '' } = {}) {
const wrap = (str, wrapper) => wrapper + str + wrapper

if (schema['$ref']) {
if (schema['$ref'][0] === '#') {
return getSchemaType(getPath(schema['$ref'], module), module, {title: true, link: link, code: code, destination})
Expand Down Expand Up @@ -259,11 +259,11 @@ function getSchemaShape(schema = {}, module = {}, { name = '', level = 0, title,
else if (schema.type === 'array' && schema.items) {
if (Array.isArray(schema.items)) {
let type = '[' + schema.items.map(x => getSchemaType(x, module, { destination })).join(', ') + ']' // no links, no code

if (code) {
type = wrap(type, '`')
}

return type
}
else {
Expand Down Expand Up @@ -358,4 +358,4 @@ function getSchemaShape(schema = {}, module = {}, { name = '', level = 0, title,
getSchemaType,
getJsonType,
getSchemaInstantiation
}
}
6 changes: 3 additions & 3 deletions src/validate/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -301,4 +301,4 @@ const run = async ({
return Promise.resolve()
}

export default run
export default run
Loading