feat(cli-create): add mashup template (#372)

This commit is contained in:
Miralem Drek
2020-03-23 08:53:57 +01:00
committed by GitHub
parent 77bd9522de
commit f0aa186533
35 changed files with 1007 additions and 123 deletions

View File

@@ -80,13 +80,13 @@ jobs:
name: Test integration
command: APP_ID=$DOC_ID yarn run test:integration --chrome.browserWSEndpoint "ws://localhost:3000" --no-launch
- run:
name: Create a hello supernova project from latest release
command: |
set -e
npx nebula create temp/hello --pkgm yarn --picasso none
cd temp/hello
APP_ID=$DOC_ID yarn run test:integration --chrome.browserWSEndpoint "ws://localhost:3000" --no-launch
# - run:
# name: Create a hello supernova project from latest release
# command: |
# set -e
# npx nebula create temp/hello --pkgm yarn --picasso none
# cd temp/hello
# APP_ID=$DOC_ID yarn run test:integration --chrome.browserWSEndpoint "ws://localhost:3000" --no-launch
- run:
name: Create a picasso barchart supernova project from current commit

View File

@@ -21,9 +21,9 @@
"lint": "eslint src"
},
"dependencies": {
"@babel/cli": "7.8.3",
"@babel/core": "7.8.3",
"@babel/preset-env": "7.8.3",
"@babel/cli": "7.8.4",
"@babel/core": "7.9.0",
"@babel/preset-env": "7.9.0",
"@rollup/plugin-commonjs": "11.0.1",
"@rollup/plugin-node-resolve": "7.0.0",
"@rollup/plugin-replace": "2.3.0",

View File

@@ -1,17 +1,43 @@
#!/usr/bin/env node
const yargs = require('yargs');
const importCwd = require('import-cwd');
const build = require('@nebula.js/cli-build/command');
const create = require('@nebula.js/cli-create/command');
const serve = require('@nebula.js/cli-serve/command');
const sense = require('@nebula.js/cli-sense/command');
// const build = require('@nebula.js/cli-build/command');
// const create = require('@nebula.js/cli-create/command');
// const serve = require('@nebula.js/cli-serve/command');
// const sense = require('@nebula.js/cli-sense/command');
yargs.usage('nebula <command> [options]');
const tryAddCommand = m => {
let cmd;
try {
cmd = require(`${m}/command`); // eslint-disable-line
} catch (e) {
cmd = importCwd.silent(`${m}/command`);
}
if (cmd) {
yargs.command(cmd);
} else {
// add dummy command in order to instruct user how to install missing package
const comm = m.split('-')[1];
yargs.command({
command: comm,
handler() {
throw new Error(
`Command \x1b[36m${comm}\x1b[0m is missing, make sure to install \x1b[36m${m}\x1b[0m and then try again.`
);
},
});
}
};
['@nebula.js/cli-build', '@nebula.js/cli-create', '@nebula.js/cli-serve', '@nebula.js/cli-sense'].forEach(
tryAddCommand
);
yargs
.usage('nebula <command> [options]')
.command(build)
.command(create)
.command(serve)
.command(sense)
.demandCommand()
.alias('h', 'help')
.wrap(Math.min(80, yargs.terminalWidth())).argv;

View File

@@ -21,12 +21,14 @@
"scripts": {
"lint": "eslint src"
},
"peerDependencies": {
"@nebula.js/cli-build": "^0.x",
"@nebula.js/cli-sense": "^0.x",
"@nebula.js/cli-serve": "^0.x"
},
"dependencies": {
"@nebula.js/cli-build": "0.2.0",
"@nebula.js/cli-create": "0.2.0",
"@nebula.js/cli-sense": "0.2.0",
"@nebula.js/cli-serve": "0.2.0",
"chalk": "3.0.0",
"import-cwd": "3.0.0",
"yargs": "15.1.0"
}
}

View File

@@ -1,9 +1,25 @@
const create = require('./lib/create');
const mashup = {
command: 'mashup <name>',
desc: 'Create a mashup',
builder(yargs) {
yargs.positional('name', {
type: 'string',
description: 'name of the project',
});
},
handler(argv) {
create(argv);
},
};
module.exports = {
command: 'create <name>',
desc: 'Create a supernova',
builder(yargs) {
yargs.command(mashup);
yargs.positional('name', {
type: 'string',
description: 'name of the project',

View File

@@ -46,7 +46,7 @@ const parseAuthor = (str = '') => {
};
};
function cpy(root, destination) {
function copyFactory(root, destination) {
return (source, target, data) => {
if (data) {
const content = fs.readFileSync(path.resolve(root, ...source.split('/')), { encoding: 'utf8' });
@@ -61,6 +61,8 @@ function cpy(root, destination) {
const create = async argv => {
const { name } = argv;
const isMashup = argv._.includes('mashup');
const projectFolder = name;
const packageName = name.split('/').slice(-1)[0];
@@ -90,7 +92,7 @@ const create = async argv => {
message: 'Pick a picasso template',
default: 'none',
choices: ['none', 'minimal', 'barchart'],
when: !argv.picasso,
when: !isMashup && !argv.picasso,
},
]);
@@ -103,28 +105,30 @@ const create = async argv => {
const { picasso } = options;
fse.ensureDirSync(destination);
// ==== common files ====
// copy raw files
['editorconfig', 'eslintignore', 'gitignore', 'eslintrc.json'].forEach(filename =>
fs.copyFileSync(
path.resolve(templatesRoot, 'common', `_${filename}`), // copying dotfiles may not always work, so they are prefixed with an underline
path.resolve(destination, `.${filename}`)
)
);
const copy = cpy(templatesRoot, destination);
copy('common/README.md', 'README.md', { name: packageName });
const copy = copyFactory(templatesRoot, destination);
// ==== template files ====
const folders = [];
if (picasso !== 'none') {
folders.push('picasso/common');
folders.push(`picasso/${picasso}`);
const folders = ['common'];
if (isMashup) {
folders.push('mashup');
} else {
folders.push('none');
folders.push('sn/common');
if (picasso !== 'none') {
folders.push('sn/picasso/common');
folders.push(`sn/picasso/${picasso}`);
} else {
folders.push('sn/none');
}
}
const data = {
name: packageName,
description: '',
user: options.author.name,
email: options.author.email,
nebulaVersion: pkg.version,
};
const traverse = (sourceFolder, targetFolder = '') => {
const files = fs.readdirSync(path.resolve(templatesRoot, sourceFolder));
@@ -135,16 +139,11 @@ const create = async argv => {
if (stats.isDirectory()) {
fse.ensureDirSync(path.resolve(destination, next));
traverse(p, next);
} else if (file === '_package.json') {
copy(`${sourceFolder}/_package.json`, 'package.json', {
name: packageName,
description: '',
user: options.author.name,
email: options.author.email,
nebulaVersion: pkg.version,
});
} else if (file[0] === '_') {
const newFileName = file === '_package.json' ? 'package.json' : `.${file.substr(1)}`;
copy(`${sourceFolder}/${file}`, `${targetFolder}/${newFileName}`.replace(/^\//, ''), data);
} else {
copy(`${sourceFolder}/${file}`, next);
copy(`${sourceFolder}/${file}`, next, data);
}
});
};

View File

@@ -0,0 +1,19 @@
{
"name": "<%= name %>",
"version": "0.0.1",
"author": {
"name": "<%= user %>",
"email": "<%= email %>"
},
"keywords": ["qlik", "nebula"],
"scripts": {
"start": "parcel src/index.html"
},
"dependencies": {
"@nebula.js/nucleus": "<%= nebulaVersion %>",
"@nebula.js/sn-bar-chart": "^0.2.2",
"@nebula.js/supernova": "<%= nebulaVersion %>",
"enigma.js": "^2.6.3",
"parcel-bundler": "^1.12.4"
}
}

View File

@@ -0,0 +1,18 @@
import nucleus from '@nebula.js/nucleus/dist/nucleus';
import barchart from '@nebula.js/sn-bar-chart';
const n = nucleus.createConfiguration({
context: {
theme: 'light',
language: 'en-US',
},
types: [
{
name: 'barchart',
load: () => Promise.resolve(barchart),
},
],
});
export default n;

View File

@@ -0,0 +1,44 @@
import enigma from 'enigma.js';
import schema from 'enigma.js/schemas/12.170.2.json';
async function getQCSHeaders({ webIntegrationId, url }) {
const response = await fetch(`${url}/api/v1/csrf-token`, {
credentials: 'include',
headers: { 'qlik-web-integration-id': webIntegrationId },
});
if (response.status === 401) {
const loginUrl = new URL(`${url}/login`);
loginUrl.searchParams.append('returnto', window.location.href);
loginUrl.searchParams.append('qlik-web-integration-id', webIntegrationId);
window.location.href = loginUrl;
return undefined;
}
const csrfToken = new Map(response.headers).get('qlik-csrf-token');
return {
'qlik-web-integration-id': webIntegrationId,
'qlik-csrf-token': csrfToken,
};
}
async function getEnigmaApp({ host, appId, headers }) {
const params = Object.keys(headers)
.map(key => `${key}=${headers[key]}`)
.join('&');
const enigmaGlobal = await enigma
.create({
schema,
url: `wss://${host}/app/${appId}?${params}`,
})
.open();
return enigmaGlobal.openDoc(appId);
}
async function connect({ url, webIntegrationId, appId }) {
const host = url.replace(/^https?:\/\//, '').replace(/\/?/, '');
const headers = await getQCSHeaders({ url, webIntegrationId });
return getEnigmaApp({ host, headers, appId });
}
export default connect;

View File

@@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Nebula mashup</title>
<style>
body {
background: #eee;
}
.content {
margin: 0 auto;
width: 80%;
max-width: 800px;
}
.object {
position: relative;
height: 600px;
}
.toolbar {
margin: 12px 0px;
}
</style>
</head>
<body>
<div class="content">
<div class="toolbar"></div>
<div class="object"></div>
</div>
<script src="./index.js"></script>
</body>
</html>

View File

@@ -0,0 +1,19 @@
/* eslint-disable */
import nucleus from './configure';
import connect from './connect';
async function run() {
const app = await connect({
url: '<URL>',
webIntegrationId: '<Qlik web integration id>',
appId: '<App id>',
});
const n = nucleus(app);
(await n.selections()).mount(document.querySelector('.toolbar'));
// n.render({});
}
run();

View File

@@ -23,12 +23,14 @@
"devDependencies": {
"@after-work.js/aw": "6.0.10",
"@nebula.js/cli": "<%= nebulaVersion %>",
"@nebula.js/cli-build": "<%= nebulaVersion %>",
"@nebula.js/cli-serve": "<%= nebulaVersion %>",
"eslint": "5.12.1",
"eslint-config-airbnb-base": "13.1.0",
"eslint-plugin-import": "2.15.0",
"eslint-plugin-mocha": "5.2.1"
},
"peerDependencies": {
"@nebula.js/supernova": "^0.1.0-alpha.28"
"@nebula.js/supernova": "^0.x"
}
}

View File

@@ -23,6 +23,8 @@
"devDependencies": {
"@after-work.js/aw": "6.0.10",
"@nebula.js/cli": "<%= nebulaVersion %>",
"@nebula.js/cli-build": "<%= nebulaVersion %>",
"@nebula.js/cli-serve": "<%= nebulaVersion %>",
"eslint": "5.12.1",
"eslint-config-airbnb-base": "13.1.0",
"eslint-plugin-import": "2.15.0",

View File

@@ -27,9 +27,9 @@
"lint": "eslint src"
},
"dependencies": {
"@babel/cli": "7.8.3",
"@babel/core": "7.8.3",
"@babel/preset-env": "7.8.3",
"@babel/cli": "7.8.4",
"@babel/core": "7.9.0",
"@babel/preset-env": "7.9.0",
"@rollup/plugin-commonjs": "11.0.1",
"@rollup/plugin-node-resolve": "7.0.0",
"fs-extra": "8.1.0",

View File

@@ -46,15 +46,15 @@
"yargs": "15.1.0"
},
"devDependencies": {
"@babel/core": "7.8.3",
"@babel/preset-env": "7.8.3",
"@babel/preset-react": "7.8.3",
"@babel/core": "7.9.0",
"@babel/preset-env": "7.9.0",
"@babel/preset-react": "7.9.1",
"@material-ui/core": "4.9.0",
"@nebula.js/nucleus": "0.2.0",
"@nebula.js/supernova": "0.2.0",
"@nebula.js/ui": "0.2.0",
"autosuggest-highlight": "3.1.1",
"babel-loader": "8.0.6",
"babel-loader": "8.1.0",
"d3-require": "1.2.4",
"enigma.js": "2.6.3",
"monaco-editor": "0.19.3",

View File

@@ -35,12 +35,12 @@
},
"devDependencies": {
"@after-work.js/aw": "6.0.10",
"@babel/cli": "7.8.3",
"@babel/core": "7.8.3",
"@babel/cli": "7.8.4",
"@babel/core": "7.9.0",
"@babel/helper-plugin-utils": "7.8.3",
"@babel/plugin-transform-react-jsx": "7.8.3",
"@babel/preset-env": "7.8.3",
"@babel/preset-react": "7.8.3",
"@babel/plugin-transform-react-jsx": "7.9.1",
"@babel/preset-env": "7.9.0",
"@babel/preset-react": "7.9.1",
"@commitlint/cli": "8.3.5",
"@commitlint/config-conventional": "8.3.4",
"@rollup/plugin-commonjs": "11.0.1",
@@ -50,7 +50,7 @@
"@storybook/addon-docs": "5.3.9",
"@storybook/addon-knobs": "5.3.9",
"@storybook/react": "5.3.9",
"babel-loader": "8.0.6",
"babel-loader": "8.1.0",
"babel-plugin-istanbul": "6.0.0",
"body-parser": "1.19.0",
"cross-env": "6.0.3",

817
yarn.lock

File diff suppressed because it is too large Load Diff