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

Thunder Support #1

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/template/js/sdk/Transport/index.js
Expand Up @@ -83,7 +83,6 @@ const getTransportLayer = () => {
// in 500ms, default to the mock FTL
// TODO: design a better way to load mock
timeout = setTimeout(() => {
console.log("Setting up mock transport layer")
setTransportLayer(mock)
}, 500)

Expand All @@ -92,6 +91,7 @@ const getTransportLayer = () => {
}

const setTransportLayer = tl => {

if (timeout) clearTimeout(timeout)

// remove handshake object
Expand All @@ -101,6 +101,8 @@ const setTransportLayer = tl => {
queue.flush(tl)
}

const getEventName = x => (x[3].match(/[A-Z]/) ? x[2] : x[2].toLowerCase()) + x.substr(3)

const send = (module, method, params) => {
let p = new Promise((resolve, reject) => {
promises[id] = {}
Expand All @@ -113,12 +115,12 @@ const send = (module, method, params) => {
if (method.match(/^on[A-Z]/)) {
//onEventName(true)
if (params.listen) {
event_map[id] = module.toLowerCase() + '.' + method[2].toLowerCase() + method.substr(3)
event_map[id] = module.toLowerCase() + '.' + getEventName(method)
}
//onEventName(false)
else {
Object.keys(event_map).forEach( key => {
if (event_map[key] === module.toLowerCase() + '.' + method[2].toLowerCase() + method.substr(3)) {
if (event_map[key] === module.toLowerCase() + '.' + getEventName(method)) {
delete event_map[key]
}
})
Expand Down
10 changes: 9 additions & 1 deletion src/template/js/sdk/Transport/mock.js
Expand Up @@ -57,7 +57,9 @@ function send(message) {
message: "Invalid params (this is a mock error from the mock transport layer)"
},
id: json.id
})))
})))

return
}

setTimeout(() => callback(JSON.stringify({
Expand All @@ -80,6 +82,7 @@ function receive(_callback) {

function event(module, event, value) {
const id = Object.entries(event_map).find(([k, v]) => v === module.toLowerCase() + '.' + event.toLowerCase())[0]

if (id) {
let message = JSON.stringify({
jsonrpc: '2.0',
Expand All @@ -100,6 +103,11 @@ function dotGrab(obj = {}, key) {
}

function getResult(method, params) {
let parts = method.toLowerCase().split('.')
parts.pop()
parts.push(method.split('.').pop())
method = parts.join('.')

let api = dotGrab(mock, method)

if (method.match(/^[a-zA-Z]+\.on[A-Za-z]+$/)) {
Expand Down
16 changes: 5 additions & 11 deletions util/declarations/generator/index.mjs
Expand Up @@ -18,22 +18,17 @@

import helpers from 'crocks/helpers/index.js'
const { tap, compose, getPathOr } = helpers
import safe from 'crocks/Maybe/safe.js'
import find from 'crocks/Maybe/find.js'
import getPath from 'crocks/Maybe/getPath.js'
import pointfree from 'crocks/pointfree/index.js'
const { chain, filter, option, map, reduce } = pointfree
import logic from 'crocks/logic/index.js'
const { and, not } = logic
import isString from 'crocks/core/isString.js'
import predicates from 'crocks/predicates/index.js'
const { isObject, isArray, propEq, pathSatisfies } = predicates

import { getMethods, getTypes, isEventMethod, isPublicEventMethod, getEnums } from '../../shared/modules.mjs'
import { getSchemaType, getSchemaShape, getMethodSignature, generateEnum } from '../../shared/typescript.mjs'
import { getEventName, getSafeName } from '../../shared/javascript.mjs'
import { getExternalSchemas } from '../../shared/json-schema.mjs'
import { getAllSchemas } from '../../shared/json-schema.mjs'
import { getExternalSchemaPaths } from '../../shared/json-schema.mjs'

const aggregateMacros = {
exports: '',
Expand All @@ -51,7 +46,6 @@ const inspector = obj => {
}

const getModuleName = getPathOr('missing', ['info', 'title'])
const makeEventName = x => x.name[2].toLowerCase() + x.name.substr(3) // onFooBar becomes fooBar

//import { default as platform } from '../Platform/defaults'
const generateAggregateMacros = obj => {
Expand Down Expand Up @@ -117,7 +111,7 @@ const generateEvents = (json) => compose(
acc += 'type Event = '
}

acc += `'${val.name[2].toLowerCase() + val.name.substr(3)}'`
acc += `'${getEventName(val.name)}'`
if (i < arr.length-1) {
acc += ' | '
}
Expand Down Expand Up @@ -155,14 +149,14 @@ const generateListeners = (json) => compose(
* @param {Event} event The Event to listen to.
* @param {Function} listener The listener function to handle the event.
*/
function listen(event: '${val.name[2].toLowerCase() + val.name.substr(3)}', listener: (data: ${getSchemaType(json, result, {title: true})}) => {})
function listen(event: '${getEventName(val.name)}', listener: (data: ${getSchemaType(json, result, {title: true})}) => {})

/**
* Listen to one and only one instance of a specific ${getModuleName(json)} event.
* @param {Event} event The Event to listen to.
* @param {Function} listener The listener function to handle the event.
*/
function once(event: '${val.name[2].toLowerCase() + val.name.substr(3)}', listener: (data: ${getSchemaType(json, result, {title: true})}) => {})
function once(event: '${getEventName(val.name)}', listener: (data: ${getSchemaType(json, result, {title: true})}) => {})

`
return acc
Expand All @@ -179,7 +173,7 @@ const generateMethods = json => compose(

if (val.params && val.params.length) {
val.params.forEach(p => acc += `
* @param {${getSchemaType(json, p.schema)}} ${p.name} ${p.summary}`)
* @param {${getSchemaType(json, p.schema)}} ${getSafeName(p.name)} ${p.summary}`)
}

acc += `
Expand Down
9 changes: 5 additions & 4 deletions util/docs/macros/index.mjs
Expand Up @@ -23,6 +23,7 @@ import { fsWriteFile, fsReadFile, bufferToString, getFilename, getDirectory, get
import { getMethodSignature, getMethodSignatureParams ,getSchemaType, getSchemaShape } from '../../shared/typescript.mjs'
import { getPath, getSchema, getExternalSchemaPaths, getSchemaConstraints, isDefinitionReferencedBySchema, hasTitle, localizeDependencies } from '../../shared/json-schema.mjs'
import { getTemplate, getAllTemplateNames } from '../../shared/template.mjs'
import { getEventName } from '../../shared/javascript.mjs'
import path from 'path'

/**
Expand Down Expand Up @@ -168,7 +169,7 @@ function insertMacros(data, json) {
if (json.methods) {
data = data
.replace(/\$\{toc.methods\}/g, json.methods.filter(m => !m.name.match(/^on[A-Z]/)).map(m => ' - [' + m.name + '](#' + m.name.toLowerCase() + ')').join('\n'))
.replace(/\$\{toc.events\}/g, json.methods.filter(m => m.name.match(/^on[A-Z]/)).map(m => ' - [' + m.name[2].toLowerCase() + m.name.substr(3) + '](#' + m.name.substr(3).toLowerCase() + ')').join('\n'))
.replace(/\$\{toc.events\}/g, json.methods.filter(m => m.name.match(/^on[A-Z]/)).map(m => ' - [' + getEventName(m.name) + '](#' + getEventName(m.name).toLowerCase() + ')').join('\n'))
}

data = data
Expand Down Expand Up @@ -206,7 +207,7 @@ function insertMethodMacros(data, method, module) {

method_data = method_data
.replace(/\$\{method.name\}/g, method.name)
.replace(/\$\{event.name\}/g, method.name.length > 3 ? method.name[2].toLowerCase() + method.name.substr(3): method.name)
.replace(/\$\{event.name\}/g, method.name.length > 3 ? getEventName(method.name): method.name)
.replace(/\$\{method.summary\}/g, method.summary)
.replace(/\$\{method.description\}/g, method.description || method.summary)
.replace(/\$\{module\}/g, module)
Expand Down Expand Up @@ -401,7 +402,7 @@ function insertEventMacros(data, methods, module) {
lines = lines.split('\n')

let method_data = lines.join('\n')
.replace(/\$\{event.name\}/, method.name[2].toLowerCase() + method.name.substr(3))
.replace(/\$\{event.name\}/, getEventName(method.name))
.replace(/\$\{event.summary\}/, method.summary)
.replace(/\$\{event.description\}/, method.description)
.replace(/\$\{event.result.name\}/, method.result.name)
Expand Down Expand Up @@ -614,7 +615,7 @@ function generateRPCCallbackExampleResult(example, m, module) {

function generateEventExample(example, m, module) {
let typescript = `import { ${module} } from '@firebolt-js/sdk'\n\n`
typescript += `${module}.listen('${m.name[2].toLowerCase() + m.name.substr(3)}', ${m.result.name} => {\n`
typescript += `${module}.listen('${getEventName(m.name)}', ${m.result.name} => {\n`
typescript += ` console.log(${m.result.name})\n`
typescript += '})'

Expand Down
20 changes: 9 additions & 11 deletions util/sdk/macros/index.mjs
Expand Up @@ -31,7 +31,7 @@ const { isObject, isArray, propEq, pathSatisfies } = predicates

import { isExcludedMethod, isRPCOnlyMethod } from '../../shared/modules.mjs'
import { getTemplate, getTemplateForMethod } from '../../shared/template.mjs'
import { getMethodSignatureParams } from '../../shared/javascript.mjs'
import { getMethodSignatureParams, getEventName, getSafeName } from '../../shared/javascript.mjs'

const staticModules = []

Expand Down Expand Up @@ -136,8 +136,8 @@ const eventsOrEmptyArray = compose(
// Maintain the side effect of process.exit here if someone is violating the rules
map(map(e => {
if (!e.name.match(/on[A-Z]/)) {
console.error(`ERROR: ${e.name} method is tagged as an event, but does not match the pattern "on[A-Z]"`)
process.exit(1) // Non-zero exit since we don't want to continue. Useful for CI/CD pipelines.
console.log(`WARNING: '${e.name}' method is tagged as an event, but does not match the pattern "on[A-Z]"`)
// process.exit(1) // Non-zero exit since we don't want to continue. Useful for CI/CD pipelines.
}
return e
})),
Expand All @@ -155,8 +155,6 @@ const getModuleName = json => {
return json ? (json.title || (json.info ? json.info.title : 'Unknown')) : 'Unknown'
}

const makeEventName = x => x.name[2].toLowerCase() + x.name.substr(3) // onFooBar becomes fooBar

//import { default as platform } from '../Platform/defaults'
const generateAggregateMacros = obj => {
aggregateMacros.exports += `export { default as ${getModuleName(obj)} } from './${getModuleName(obj)}'\n`
Expand Down Expand Up @@ -233,7 +231,7 @@ const insertMacros = ([file, fContents, macros, obj]) => {
}

const enumReducer = (acc, val, i, arr) => {
const keyName = val.replace(/[\.\-]/g, '_').replace(/\+/g, '_plus').replace(/([a-z])([A-Z0-9])/g, '$1_$2').toUpperCase()
const keyName = val.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')
Expand Down Expand Up @@ -277,7 +275,7 @@ const generateEvents = compose(
}
return acc
}, ''),
map(makeEventName),
map(e => getEventName(e.name)),
eventsOrEmptyArray
)

Expand Down Expand Up @@ -315,7 +313,7 @@ const generateInitialization = json => compose(
if (i === 0) {
acc = []
}
acc.push(makeEventName(method))
acc.push(getEventName(method.name))
if (i < arr.length-1) {
return acc
}
Expand All @@ -335,7 +333,7 @@ function generateMethodList(json = {}) {
)(json)
const eventMethods = eventsOrEmptyArray(json)

let result = notEventMethods.map(m => m.name).join(',\n ')
let result = notEventMethods.map(m => getSafeName(m.name)).join(',\n ')
if (eventMethods.length) {
result += ',\n listen,\n once,\n clear'
}
Expand All @@ -344,7 +342,7 @@ function generateMethodList(json = {}) {
}

function generateMethods(json = {}, onlyEvents = false) {
const moduleName = getModuleName(json).toLowerCase()
const moduleName = getModuleName(json)//.toLowerCase()

// Two arrays that represent two codegen flows
const eventMethods = eventsOrEmptyArray(json)
Expand Down Expand Up @@ -385,7 +383,7 @@ function generateMethods(json = {}, onlyEvents = false) {
title: moduleName
}
const method = {
name: methodObj.name,
name: getSafeName(methodObj.name),
params: getMethodSignatureParams(moduleName, methodObj, { isInterface: false })
}

Expand Down
62 changes: 58 additions & 4 deletions util/shared/javascript.mjs
Expand Up @@ -17,7 +17,7 @@
*/

const enumReducer = (acc, val, i, arr) => {
const keyName = val.replace(/[\.\-]/g, '_').replace(/\+/g, '_plus').replace(/([a-z])([A-Z0-9])/g, '$1_$2').toUpperCase()
const keyName = getSafeName(val.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')
Expand All @@ -37,20 +37,74 @@ const generateEnum = schema => {
}
}

const reserved = [
'break',
'case',
'catch',
'class',
'const',
'continue',
'debugger',
'default',
'delete',
'do',
'else',
'export',
'extends',
'finally',
'for',
'function',
'if',
'import',
'in',
'instanceof',
'new',
'return',
'super',
'switch',
'this',
'throw',
'try',
'typeof',
'var',
'void',
'while',
'with',
'yield'
]

function getSafeName(name) {
name = name .replace(/\ /g, '_')
.replace(/\-/g, '_')

if (reserved.includes(name)) {
name = '_' + name
}

return name
}

function getMethodSignature(module, method, options={ isInterface: false }) {
let javascript = (isInterface ? '' : 'function ') + method.name + '('
let javascript = (isInterface ? '' : 'function ') + getSafeName(method.name) + '('
javascript += getMethodSignatureParams(module, method)
javascript += ')'

return javascript
}

function getMethodSignatureParams(module, method) {
return method.params.map( param => param.name ).join(', ')
if (method.params)
return method.params.map( param => param.name ).join(', ')
else
return ''
}

const getEventName = x => (x[3].match(/[A-Z]/) ? x[2] : x[2].toLowerCase()) + x.substr(3) // onFooBar becomes fooBar, onFOOBar becomes FOOBar

export {
generateEnum,
getMethodSignature,
getMethodSignatureParams
getMethodSignatureParams,
getEventName,
getSafeName
}
15 changes: 14 additions & 1 deletion util/shared/json-schema.mjs
Expand Up @@ -17,6 +17,7 @@
*/

import crocks from 'crocks'
import { read } from 'fs'
import fs from 'fs/promises'
import path from 'path'
import url from 'url'
Expand Down Expand Up @@ -51,7 +52,7 @@ const getRef = (ref, json) => {

const refToPath = ref => {
let path = ref.split('#').pop().substr(1).split('/')
return path.map(x => x.match(/[0-9]+/) ? parseInt(x) : x)
return path.map(x => x.match(/^[0-9]+$/) ? parseInt(x) : x)
}

const objectPaths = obj => {
Expand Down Expand Up @@ -151,11 +152,23 @@ const replaceUri = (existing, replacement, schema) => {
}

const replaceRef = (existing, replacement, schema) => {
if (existing.endsWith('/')) {
existing = existing.slice(0, -1)
}

if (schema) {
if (schema.hasOwnProperty('$ref') && (typeof schema['$ref'] === 'string')) {
if (schema['$ref'] === existing) {
schema['$ref'] = replacement
}
else if (schema['$ref'].startsWith(existing + '/')) {
schema['$ref'] = replacement + schema['$ref'].substr(existing.length)
}
}
else if (Array.isArray(schema)) {
schema.forEach(item => {
replaceRef(existing, replacement, item)
})
}
else if (typeof schema === 'object') {
Object.keys(schema).forEach(key => {
Expand Down