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

2.3.0 Release #166

Merged
merged 14 commits into from
Feb 8, 2024
Merged
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
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
# [2.3.0-next.1](https://github.com/rdkcentral/firebolt-openrpc/compare/v2.2.0...v2.3.0-next.1) (2024-01-12)


### Bug Fixes

* Insert 'v' in front of version enum names ([d8b9ada](https://github.com/rdkcentral/firebolt-openrpc/commit/d8b9ada1b624df29821b74679291d36167208470))
* Proper param handling for x-subscriber-type: global ([02204e5](https://github.com/rdkcentral/firebolt-openrpc/commit/02204e5f93d27a21086b4a9bbe5f586f969354f8))


### Features

* Support for context-free property subscribers ([9809273](https://github.com/rdkcentral/firebolt-openrpc/commit/980927309fa6efc7b03a490aa5fd7909f39ff4de))

# [2.2.0](https://github.com/rdkcentral/firebolt-openrpc/compare/v2.1.2...v2.2.0) (2023-11-30)


Expand Down
20 changes: 1 addition & 19 deletions languages/c/Types.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/

import deepmerge from 'deepmerge'
import { getPath } from '../../src/shared/json-schema.mjs'
import { getPath, getSafeEnumKeyName } from '../../src/shared/json-schema.mjs'
import { getTypeName, getModuleName, description, getObjectManagement, getNativeType, getPropertyAccessors, capitalize, isOptional, generateEnum, getMapAccessors, getArrayAccessors, getPropertyGetterSignature, getFireboltStringType } from './src/types/NativeHelpers.mjs'
import { getArrayAccessorsImpl, getMapAccessorsImpl, getObjectManagementImpl, getParameterInstantiation, getPropertyAccessorsImpl, getResultInstantiation, getCallbackParametersInstantiation, getCallbackResultInstantiation, getCallbackResponseInstantiation } from './src/types/ImplHelpers.mjs'
import { getJsonContainerDefinition, getJsonDataStructName, getJsonDataPrefix } from './src/types/JSONHelpers.mjs'
Expand Down Expand Up @@ -717,24 +717,6 @@ function getJsonTypeInfo(module = {}, json = {}, name = '', schemas, prefix = ''
return structure
}

function getTypeScriptType(jsonType) {
if (jsonType === 'integer') {
return 'number'
}
else {
return jsonType
}
}

const enumReducer = (acc, val, i, arr) => {
const keyName = val.split(':').pop().replace(/[\.\-]/g, '_').replace(/\+/g, '_plus').replace(/([a-z])([A-Z0-9])/g, '$1_$2').toUpperCase()
acc = acc + ` ${keyName} = '${val}'`
if (i < arr.length - 1) {
acc = acc.concat(',\n')
}
return acc
}

function getSchemaInstantiation(schema, module, name, { instantiationType = '', prefix = '' } = {}) {

if (instantiationType === 'params') {
Expand Down
4 changes: 2 additions & 2 deletions languages/c/src/types/NativeHelpers.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import safe from 'crocks/Maybe/safe.js'
import pointfree from 'crocks/pointfree/index.js'
const { chain, filter, reduce, option, map } = pointfree
import predicates from 'crocks/predicates/index.js'
import { getPath, getExternalSchemaPaths } from '../../../../src/shared/json-schema.mjs'
import { getPath, getExternalSchemaPaths, getSafeEnumKeyName } from '../../../../src/shared/json-schema.mjs'
import deepmerge from 'deepmerge'

const { isObject, isArray, propEq, pathSatisfies, hasProp, propSatisfies } = predicates
Expand Down Expand Up @@ -126,7 +126,7 @@ const getArrayAccessors = (arrayName, propertyType, valueType) => {
}

const enumValue = (val,prefix) => {
const keyName = val.replace(/[\.\-:]/g, '_').replace(/\+/g, '_plus').replace(/([a-z])([A-Z0-9])/g, '$1_$2').toUpperCase()
const keyName = getSafeEnumKeyName(val)
return ` ${prefix.toUpperCase()}_${keyName.toUpperCase()}`
}

Expand Down
3 changes: 3 additions & 0 deletions languages/javascript/src/shared/Prop/Router.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ export default function (params, callbackOrValue, contextParameterCount) {
} else if (numArgs === contextParameterCount && typeof callbackOrValue === 'function') {
// subscribe
return "subscriber"
} else if (numArgs === 0 && typeof callbackOrValue === 'function') {
// for x-subscriber-type: global
return "subscriber"
} else if (numArgs === (contextParameterCount) && callbackOrValue !== undefined) {
// setter
return "setter"
Expand Down
2 changes: 1 addition & 1 deletion languages/javascript/templates/declarations/property.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*
${method.params.annotations}${if.deprecated} * @deprecated ${method.deprecation}
${end.if.deprecated} */
function ${method.name}(): Promise<${method.result.type}>
function ${method.name}(${method.signature.params}): Promise<${method.result.type}>


${method.setter}
Expand Down
12 changes: 10 additions & 2 deletions languages/javascript/templates/methods/property.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,12 @@
function ${method.name}(${method.params.list}) {
const callbackOrValue = arguments[${method.params.count}]
return Prop.prop('${info.title}', '${method.name}', { ${method.params.list} }, callbackOrValue, ${method.property.immutable}, ${method.property.readonly}, ${method.params.count})
let callbackOrValue = arguments[${method.params.count}]
let params = { ${method.params.list} }

// x-subscriber-type: global
if (arguments.length === 1 && (typeof arguments[0] === 'function')) {
callbackOrValue = arguments[0]
params = {}
}

return Prop.prop('${info.title}', '${method.name}', params, callbackOrValue, ${method.property.immutable}, ${method.property.readonly}, ${method.params.count})
}
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@firebolt-js/openrpc",
"version": "2.2.0",
"version": "2.3.0-next.1",
"description": "The Firebolt SDK Code & Doc Generator",
"main": "languages/javascript/src/sdk.mjs",
"type": "module",
Expand Down
4 changes: 2 additions & 2 deletions src/macrofier/engine.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const { isObject, isArray, propEq, pathSatisfies, propSatisfies } = predicates

import { isRPCOnlyMethod, isProviderInterfaceMethod, getProviderInterface, getPayloadFromEvent, providerHasNoParameters, isTemporalSetMethod, isCallsMetricsMethod, isExcludedMethod, hasMethodAttributes, getMethodAttributes, isEventMethodWithContext, getSemanticVersion, getSetterFor, getProvidedCapabilities, isPolymorphicPullMethod, hasPublicAPIs, createPolymorphicMethods } from '../shared/modules.mjs'
import isEmpty from 'crocks/core/isEmpty.js'
import { getLinkedSchemaPaths, getSchemaConstraints, isSchema, localizeDependencies, isDefinitionReferencedBySchema } from '../shared/json-schema.mjs'
import { getLinkedSchemaPaths, getSchemaConstraints, isSchema, localizeDependencies, isDefinitionReferencedBySchema, getSafeEnumKeyName } from '../shared/json-schema.mjs'

// util for visually debugging crocks ADTs
const _inspector = obj => {
Expand Down Expand Up @@ -634,7 +634,7 @@ const convertEnumTemplate = (schema, templateName, templates) => {
for (var i = 0; i < template.length; i++) {
if (template[i].indexOf('${key}') >= 0) {
template[i] = enumSchema.enum.map(value => {
const safeName = value.split(':').pop().replace(/[\.\-]/g, '_').replace(/\+/g, '_plus').replace(/([a-z])([A-Z0-9])/g, '$1_$2').toUpperCase()
const safeName = getSafeEnumKeyName(value)
return template[i].replace(/\$\{key\}/g, safeName)
.replace(/\$\{value\}/g, value)
}).join('\n')
Expand Down
8 changes: 8 additions & 0 deletions src/shared/json-schema.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -355,8 +355,16 @@ const isDefinitionReferencedBySchema = (name = '', moduleJson = {}) => {
return (refs.length > 0)
}

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()

export {
getSchemaConstraints,
getSafeEnumKeyName,
getExternalSchemaPaths,
getLocalSchemas,
getLocalSchemaPaths,
Expand Down
75 changes: 73 additions & 2 deletions src/shared/modules.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,35 @@ const eventDefaults = event => {
return event
}

const createEventResultSchemaFromProperty = property => {
const subscriberType = property.tags.map(t => t['x-subscriber-type']).find(t => typeof t === 'string') || 'context'

if (property.tags.find(t => (t.name == 'property' || t.name.startsWith('property:')) && (subscriberType === 'global'))) {
// wrap the existing result and the params in a new result object
const schema = {
title: property.name.charAt(0).toUpperCase() + property.name.substring(1) + 'ChangedInfo',
type: "object",
properties: {

},
required: []
}

// add all of the params
property.params.filter(p => p.name !== 'listen').forEach(p => {
schema.properties[p.name] = p.schema
schema.required.push(p.name)
})

// add the result (which might override a param of the same name)
schema.properties[property.result.name] = property.result.schema
!schema.required.includes(property.result.name) && schema.required.push(property.result.name)


return schema
}
}

const createEventFromProperty = property => {
const event = eventDefaults(JSON.parse(JSON.stringify(property)))
event.name = 'on' + event.name.charAt(0).toUpperCase() + event.name.substr(1) + 'Changed'
Expand All @@ -388,6 +417,36 @@ const createEventFromProperty = property => {
'x-subscriber-for': property.name
})

const subscriberType = property.tags.map(t => t['x-subscriber-type']).find(t => typeof t === 'string') || 'context'

// if the subscriber type is global, zap all of the parameters and change the result type to the schema that includes them
if (old_tags.find(t => (t.name == 'property' || t.name.startsWith('property:')) && (subscriberType === 'global'))) {

// wrap the existing result and the params in a new result object
const result = {
name: "data",
schema: {
$ref: "#/components/schemas/" + event.name.substring(2) + 'Info'
}
}

event.examples.map(example => {
const result = {}
example.params.filter(p => p.name !== 'listen').forEach(p => {
result[p.name] = p.value
})
result[example.result.name] = example.result.value
example.params = example.params.filter(p => p.name === 'listen')
example.result.name = "data"
example.result.value = result
})

event.result = result

// remove the params
event.params = event.params.filter(p => p.name === 'listen')
}

old_tags.forEach(t => {
if (t.name !== 'property' && !t.name.startsWith('property:'))
{
Expand Down Expand Up @@ -750,8 +809,20 @@ const generatePropertyEvents = json => {
const properties = json.methods.filter( m => m.tags && m.tags.find( t => t.name == 'property')) || []
const readonlies = json.methods.filter( m => m.tags && m.tags.find( t => t.name == 'property:readonly')) || []

properties.forEach(property => json.methods.push(createEventFromProperty(property)))
readonlies.forEach(property => json.methods.push(createEventFromProperty(property)))
properties.forEach(property => {
json.methods.push(createEventFromProperty(property))
const schema = createEventResultSchemaFromProperty(property)
if (schema) {
json.components.schemas[schema.title] = schema
}
})
readonlies.forEach(property => {
json.methods.push(createEventFromProperty(property))
const schema = createEventResultSchemaFromProperty(property)
if (schema) {
json.components.schemas[schema.title] = schema
}
})

return json
}
Expand Down
6 changes: 3 additions & 3 deletions src/shared/typescript.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
*/

import deepmerge from 'deepmerge'
import { getPath, localizeDependencies } from './json-schema.mjs'
import { getPath, getSafeEnumKeyName, localizeDependencies } from './json-schema.mjs'

const isSynchronous = m => !m.tags ? false : m.tags.map(t => t.name).find(s => s === 'synchronous')

Expand Down Expand Up @@ -45,7 +45,7 @@ function getSchemaShape(schema = {}, module = {}, { name = '', level = 0, title,
let theTitle = (level === 0 ? schema.title || name : name)

if (enums && level === 0 && schema.type === "string" && Array.isArray(schema.enum)) {
return `enum ${schema.title || name} {\n\t` + schema.enum.map(value => value.split(':').pop().replace(/[\.\-]/g, '_').replace(/\+/g, '_plus').replace(/([a-z])([A-Z0-9])/g, '$1_$2').toUpperCase() + ` = '${value}'`).join(',\n\t') + '\n}\n'
return `enum ${schema.title || name} {\n\t` + schema.enum.map(value => getSafeEnumKeyName(value) + ` = '${value}'`).join(',\n\t') + '\n}\n'
}

if (!theTitle) {
Expand Down Expand Up @@ -338,7 +338,7 @@ function getSchemaShape(schema = {}, module = {}, { name = '', level = 0, title,
}

const enumReducer = (acc, val, i, arr) => {
const keyName = val.split(':').pop().replace(/[\.\-]/g, '_').replace(/\+/g, '_plus').replace(/([a-z])([A-Z0-9])/g, '$1_$2').toUpperCase()
const keyName = getSafeEnumKeyName(val)
acc = acc + ` ${keyName} = '${val}'`
if (i < arr.length-1) {
acc = acc.concat(',\n')
Expand Down