Last active
October 7, 2018 15:02
-
-
Save PotOfCoffee2Go/7433f0b7b5479c57bd8a4f3688e6f8ce to your computer and use it in GitHub Desktop.
Load classes stored in ObservableHq into nodejs
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
/* | |
Create empty directory | |
From command line | |
* note to self: nvm use 10 | |
npm init -y | |
npm i fs-extra --save | |
npm i node-fetch --save | |
npm i download-cli --save | |
node node_modules/download-cli/cli.js -e --out notebooks 'https://api.observablehq.com/@potofcoffee2go/01-data-managment-toolbox.tgz' | |
node node_modules/download-cli/cli.js --out ./ 'https://gist.github.com/PotOfCoffee2Go/7433f0b7b5479c57bd8a4f3688e6f8ce/raw/479f7bc87ed1983408d18483d59c8c96b3ef6a3b/observable-to-nodejs.js' | |
node observable-to-nodejs.js | |
*/ | |
'use strict'; | |
const fs = require('fs-extra'), | |
fetch = require('node-fetch'); | |
/* Load {notebook}.js into Nodejs (CJS) | |
* Note: requires nodejs >= v10 due to generator functions in notebook | |
* Changes line 'export default notebook;' to 'module.exports = notebook;' | |
* leaving the original unmodified so can still be used by the browser | |
* Returns loaded module | |
*/ | |
function requireNotebook(notebookPath) { | |
let es = fs.readFileSync(notebookPath, 'utf8'); | |
let cjs = es.replace(/\nexport default notebook;\n/, 'module.exports = notebook;'); | |
fs.writeFileSync('./notebooks/temp.js', cjs); | |
let module = require('./notebooks/temp.js'); | |
fs.unlinkSync('./notebooks/temp.js'); | |
return module; | |
} | |
/* Get a cell from notebook */ | |
function getCell(cellname, ...args) { | |
return notebook.modules[0].variables | |
.find(variable => variable.name === cellname) | |
.value(...args); | |
} | |
const notebook = requireNotebook('./notebooks/01-data-managment-toolbox.js'); | |
// A utilities class defined in notebook 'Util' cell - this cell requires no params | |
// but... since do not have the browsers 'fetch()' need to use node-fetch | |
const Util = getCell('Util'); | |
const util = new Util; // instantiate | |
util.getJson = async(url) => { return await (await fetch(url)).json() } | |
// Classes in other cells use an object 'cf' as a lookup table | |
let cf = getCell('cf'); | |
// or could just do a : | |
//let cf = {}; | |
// Clerk is a base class to the other classes | |
const Clerk = getCell('Clerk', cf, util); | |
// Classes that will be instantiated later by our data surrogate class | |
const | |
Meta = getCell('Meta', cf, Clerk, util), | |
Edge = getCell('Edge', cf, Clerk, util), | |
Feed = getCell('Feed', cf, Clerk, util), | |
Eyes = getCell('Eyes', cf, Clerk, util); | |
// Instantiates and use all the classes above | |
const Surrogate = getCell('Surrogate', cf, Meta, Edge, Feed, Eyes, Clerk); | |
const surrogate = new Surrogate({ [cf.data]: 'A new surrogate' }); | |
// Watch for when surrogate data updates | |
async function watchUpdates() { | |
console.log(`At ${surrogate[cf.meta].updated} ` + | |
`got ${JSON.stringify({data: surrogate[cf.data]},null,2)}\n`); | |
await surrogate[cf.eyes].watch(); // Eyes promise resolves when data updated | |
watchUpdates(); | |
} | |
watchUpdates(); | |
// Watch for feed href changes | |
async function watchFeedHref() { | |
await surrogate[cf.feed].watch(); // Feed promise resolves when href updated | |
console.log(`--> Feed url changed: ${surrogate[cf.feed].href}\n`); | |
watchFeedHref(); | |
} | |
watchFeedHref(); | |
// Go out and get some data off the web | |
let counter = 0; | |
setInterval(() => { | |
surrogate[cf.feed].href = `https://jsonplaceholder.typicode.com/todos/${++counter}`; | |
surrogate[cf.feed].fetch(); | |
}, 3000); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment