Skip to content

Commit

Permalink
Merge branch 'next' into features/cpp
Browse files Browse the repository at this point in the history
  • Loading branch information
HaseenaSainul committed Mar 1, 2024
2 parents 50031be + 189eed2 commit f64fb6d
Show file tree
Hide file tree
Showing 12 changed files with 131 additions and 38 deletions.
25 changes: 23 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,38 @@
# [2.2.0-next.1](https://github.com/rdkcentral/firebolt-openrpc/compare/v2.1.1-next.3...v2.2.0-next.1) (2023-11-30)
# [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)


### Features

* Improve generated doc formatting ([#155](https://github.com/rdkcentral/firebolt-openrpc/issues/155)) ([4613281](https://github.com/rdkcentral/firebolt-openrpc/commit/46132810ac5e5b0a8b9baa22903cb8a367b46f63))

## [2.1.1-next.3](https://github.com/rdkcentral/firebolt-openrpc/compare/v2.1.1-next.2...v2.1.1-next.3) (2023-11-09)
## [2.1.2](https://github.com/rdkcentral/firebolt-openrpc/compare/v2.1.1...v2.1.2) (2023-11-09)


### Bug Fixes

* Provider openrpc response and error methods have a wrapper object ([#148](https://github.com/rdkcentral/firebolt-openrpc/issues/148)) ([373626e](https://github.com/rdkcentral/firebolt-openrpc/commit/373626ed598447bb670ac67e97ca8ed1bf32f28f))

## [2.1.1](https://github.com/rdkcentral/firebolt-openrpc/compare/v2.1.0...v2.1.1) (2023-11-01)


### Bug Fixes

* Errors thrown in async provider methods do not send the JSONRPC error response ([#143](https://github.com/rdkcentral/firebolt-openrpc/issues/143)) ([ec8e259](https://github.com/rdkcentral/firebolt-openrpc/commit/ec8e2599d530f9d2bd38fbb53b36e13c038edf2a))
* Macro not replaced for provider docs ([ef1aecd](https://github.com/rdkcentral/firebolt-openrpc/commit/ef1aecd0092a8652bc7b936604f9478b7b55df27))

## [2.1.1-next.2](https://github.com/rdkcentral/firebolt-openrpc/compare/v2.1.1-next.1...v2.1.1-next.2) (2023-11-01)


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-next.1",
"version": "2.3.0-next.1",
"description": "The Firebolt SDK Code & Doc Generator",
"main": "languages/javascript/src/sdk.mjs",
"type": "module",
Expand Down
6 changes: 3 additions & 3 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, hasMethodAttributes, getMethodAttributes, isEventMethodWithContext, getSemanticVersion, getSetterFor, getProvidedCapabilities, isPolymorphicPullMethod, hasPublicAPIs, createPolymorphicMethods, isExcludedMethod, isCallsMetricsMethod } from '../shared/modules.mjs'
import isEmpty from 'crocks/core/isEmpty.js'
import { getPath as getJsonPath, getLinkedSchemaPaths, getSchemaConstraints, isSchema, localizeDependencies, isDefinitionReferencedBySchema, mergeAnyOf, mergeOneOf } from '../shared/json-schema.mjs'
import { getPath as getJsonPath, getLinkedSchemaPaths, getSchemaConstraints, isSchema, localizeDependencies, isDefinitionReferencedBySchema, mergeAnyOf, mergeOneOf, getSafeEnumKeyName } from '../shared/json-schema.mjs'

// util for visually debugging crocks ADTs
const _inspector = obj => {
Expand Down Expand Up @@ -797,8 +797,8 @@ const convertEnumTemplate = (schema, templateName, templates) => {
const template = getTemplate(templateName, templates).split('\n')
for (var i = 0; i < template.length; i++) {
if (template[i].indexOf('${key}') >= 0) {
template[i] = enumSchema.enum.map((value, id) => {
const safeName = value.split(':').pop().replace(/[\.\-]/g, '_').replace(/\+/g, '_plus').replace(/([a-z])([A-Z0-9])/g, '$1_$2').toUpperCase()
template[i] = enumSchema.enum.map(value => {
const safeName = getSafeEnumKeyName(value)
return template[i].replace(/\$\{key\}/g, safeName)
.replace(/\$\{value\}/g, value)
.replace(/\$\{delimiter\}(.*?)\$\{end.delimiter\}/g, id === enumSchema.enum.length - 1 ? '' : '$1')
Expand Down
10 changes: 9 additions & 1 deletion src/shared/json-schema.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -426,8 +426,16 @@ 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()

export {
getSchemaConstraints,
getSafeEnumKeyName,
getExternalSchemaPaths,
getLocalSchemas,
getLocalSchemaPaths,
Expand All @@ -442,4 +450,4 @@ export {
removeIgnoredAdditionalItems,
mergeAnyOf,
mergeOneOf
}
}
75 changes: 73 additions & 2 deletions src/shared/modules.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -370,6 +370,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 @@ -382,6 +411,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 @@ -756,8 +815,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 @@ -340,7 +340,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

0 comments on commit f64fb6d

Please sign in to comment.