-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(koa): koa integration to provide middleware for signal network a…
…s an http interface affects: patois.api, @tao.js/koa expose a signal network over http using koa as the app server
- Loading branch information
Showing
9 changed files
with
286 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
lib | ||
dist | ||
bundles |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
node_modules | ||
src | ||
test | ||
.babelrc | ||
package-lock.json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import resolve from 'rollup-plugin-node-resolve'; | ||
import commonjs from 'rollup-plugin-commonjs'; | ||
import babel from 'rollup-plugin-babel'; | ||
import external from 'rollup-plugin-peer-deps-external'; | ||
import pkg from './package.json'; | ||
|
||
export default [ | ||
// CommonJS (for Node) and ES module (for bundlers) build. | ||
// (We could have three entries in the configuration array | ||
// instead of two, but it's quicker to generate multiple | ||
// builds from a single configuration where possible, using | ||
// an array for the `output` option, where we can specify | ||
// `file` and `format` for each target) | ||
{ | ||
input: { | ||
index: 'src/index.js' | ||
}, | ||
output: [ | ||
{ | ||
dir: pkg.main, | ||
format: 'cjs', | ||
sourcemap: true | ||
}, | ||
{ | ||
dir: pkg.module, | ||
format: 'esm', | ||
sourcemap: true | ||
} | ||
], | ||
plugins: [ | ||
external(), | ||
babel({ | ||
runtimeHelpers: true, | ||
exclude: ['node_modules/**'] | ||
}), | ||
resolve(), | ||
commonjs() | ||
] | ||
} | ||
]; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
export const noop = () => {}; | ||
|
||
export function normalizeAC({ t, term, a, action, o, orient }) { | ||
return { | ||
term: term || t, | ||
action: action || a, | ||
orient: orient || o | ||
}; | ||
} | ||
|
||
export const cleanInput = ({ term, action, orient }) => { | ||
const incoming = { term, action, orient }; | ||
Object.keys(incoming).forEach(k => incoming[k] == null && delete incoming[k]); | ||
return incoming; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
import { AppCtx } from '@tao.js/core'; | ||
import cartesian from 'cartesian'; | ||
import { Channel, Transponder } from '@tao.js/utils'; | ||
import { noop, normalizeAC, cleanInput } from './helpers'; | ||
|
||
// const noop = () => {}; | ||
|
||
const DEFAULT_ROOT = 'tao'; | ||
const ROUTE_POSITION = 1; | ||
const ROUTE_RESPONSES = 'responses'; | ||
const ROUTE_CONTEXT = 'context'; | ||
|
||
async function getBodyData(ctx, bodyProp) { | ||
let data = null; | ||
if (bodyProp && ctx.request[bodyProp]) { | ||
if (typeof ctx.request[bodyProp] === 'function') { | ||
data = await ctx.request[bodyProp](); | ||
} else { | ||
data = ctx.request[bodyProp]; | ||
} | ||
} | ||
if (!data && ctx.request.json) { | ||
if (typeof ctx.request.json === 'function') { | ||
data = await ctx.request.json(); | ||
} else { | ||
data = ctx.request.json; | ||
} | ||
} | ||
if (!data && ctx.request.body) { | ||
if (typeof ctx.request.body === 'function') { | ||
data = await ctx.request.body(); | ||
} else { | ||
data = ctx.request.body; | ||
} | ||
} | ||
return data; | ||
} | ||
|
||
function handleResponsesRequest(responseTrigrams, ctx, next) { | ||
// const out = Array.from(responseTrigrams.values()); | ||
ctx.body = { | ||
// out, | ||
responses: Array.from(responseTrigrams.values()) | ||
.filter(r => r.count > 0) | ||
.map(r => r.ac.unwrapCtx()) | ||
}; | ||
return next(); | ||
} | ||
|
||
async function handleContext(transponder, bodyProp, ctx, next) { | ||
const { tao, data } = await getBodyData(ctx, bodyProp); | ||
try { | ||
const ac = await transponder.setCtx(tao, data); | ||
ctx.body = { | ||
tao: ac.unwrapCtx(), | ||
data: ac.data | ||
}; | ||
} catch (err) { | ||
console.error('Error:', err); | ||
ctx.status = 404; | ||
} | ||
return next(); | ||
} | ||
|
||
export default function taoMiddleware(TAO, opt = {}) { | ||
const responseTrigrams = new Map(); | ||
const bodyProp = opt.json; | ||
const rootPath = opt.root || DEFAULT_ROOT; | ||
const rootTest = new RegExp(`/${rootPath}/([^/]+)/?(.*)?`, 'i'); | ||
const transponder = new Transponder(TAO, opt.name, 3000); | ||
transponder.addInlineHandler({}, (tao, data) => | ||
console.log('taoMiddleware::hitting the first with:', tao, data) | ||
); | ||
|
||
return { | ||
middleware() { | ||
return async (ctx, next) => { | ||
const path = ctx.path.match(rootTest); | ||
if (!path) { | ||
return next(); | ||
} | ||
const route = path[ROUTE_POSITION]; | ||
if (!route) { | ||
ctx.status = 404; | ||
return next(); | ||
} | ||
// change if routes start accepting additional path parameters | ||
if (path[ROUTE_POSITION + 1]) { | ||
ctx.status = 400; | ||
ctx.body = { message: 'extra path parameters are not supported' }; | ||
return next(); | ||
} | ||
switch (route) { | ||
case ROUTE_RESPONSES: | ||
if (ctx.method !== 'GET') { | ||
ctx.status = 405; | ||
return next(); | ||
} | ||
return handleResponsesRequest(responseTrigrams, ctx, next); | ||
case ROUTE_CONTEXT: | ||
if (ctx.method !== 'POST') { | ||
ctx.status = 405; | ||
return next(); | ||
} | ||
return handleContext(transponder, bodyProp, ctx, next); | ||
default: | ||
ctx.status = 404; | ||
return next(); | ||
} | ||
}; | ||
}, | ||
addResponseHandler({ t, term, a, action, o, orient }, handler = noop) { | ||
const trigrams = cleanInput( | ||
normalizeAC({ t, term, a, action, o, orient }) | ||
); | ||
const permutations = cartesian(trigrams); | ||
for (let trigram of permutations) { | ||
console.log('@tao.js/koa::addResponseHandler::trigram:', trigram); | ||
transponder.addInlineHandler(trigram, handler); | ||
let ac = new AppCtx(trigram.term, trigram.action, trigram.orient); | ||
if (!responseTrigrams.has(ac.key)) { | ||
responseTrigrams.set(ac.key, { ac, count: 0 }); | ||
} | ||
responseTrigrams.get(ac.key).count += 1; | ||
console.log( | ||
'@tao.js/koa::addResponseHandler::responseTrigrams:', | ||
responseTrigrams | ||
); | ||
} | ||
}, | ||
removeResponseHandler({ t, term, a, action, o, orient }, handler = noop) { | ||
const trigrams = cleanInput( | ||
normalizeAC({ t, term, a, action, o, orient }) | ||
); | ||
const permutations = cartesian(trigrams); | ||
for (let trigram of permutations) { | ||
transponder.removeInlineHandler(trigram, handler); | ||
let ac = new AppCtx(trigram.term, trigram.action, trigram.orient); | ||
let count = !responseTrigrams.has(ac.key) | ||
? 0 | ||
: responseTrigrams.get(ac.key).count; | ||
if (count) { | ||
responseTrigrams.get(ac.key).count -= 1; | ||
} | ||
} | ||
} | ||
}; | ||
} |