From 759d03c1f75badf6459a406b20a37d456d71f27f Mon Sep 17 00:00:00 2001 From: Tobias Winkler Date: Wed, 26 Feb 2020 16:58:47 +0100 Subject: [PATCH] fix libs structure; add working systemjs plugins; use better dapp-browser structure - [CORE-635] --- .gitignore | 3 - package.json | 16 +- src/app/ens.ts | 11 +- src/app/start.ts | 58 +++++++ src/index.ts | 72 ++------- src/libs/bs58.bundle.js | 2 +- src/static/dev.html | 7 + src/systemjs/plugins/dapp-content.ts | 221 +++++++++++++++++++++++++++ src/systemjs/plugins/ens.ts | 116 ++++++++++++++ src/systemjs/plugins/index.ts | 34 +++++ src/systemjs/plugins/ipfs.ts | 68 +++++++++ src/systemjs/plugins/json.ts | 34 +++++ src/systemjs/plugins/text.ts | 38 +++++ tsconfig.json | 1 - webpack.config.js | 49 ++++-- 15 files changed, 640 insertions(+), 90 deletions(-) create mode 100644 src/app/start.ts create mode 100644 src/systemjs/plugins/dapp-content.ts create mode 100644 src/systemjs/plugins/ens.ts create mode 100644 src/systemjs/plugins/index.ts create mode 100644 src/systemjs/plugins/ipfs.ts create mode 100644 src/systemjs/plugins/json.ts create mode 100644 src/systemjs/plugins/text.ts diff --git a/.gitignore b/.gitignore index f9e478e..c703c3d 100644 --- a/.gitignore +++ b/.gitignore @@ -26,9 +26,6 @@ temp/ hooks/ platforms/ !platforms/android/build.gradle -plugins/ -plugins/android.json -plugins/ios.json www/ $RECYCLE.BIN/ diff --git a/package.json b/package.json index c75c960..314bba3 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,6 @@ "dependencies": { "@evan.network/api-blockchain-core": "^2.3.0", "console.table": "^0.9.1", - "copy-webpack-plugin": "^5.1.1", "css-loader": "^3.4.2", "del": "^2.2.2", "express": "^4.16.2", @@ -11,6 +10,7 @@ "gulp-minify": "^3.1.0", "inquirer": "^5.1.0", "ipfs-api": "^26.1.2", + "minimist": "^1.2.0", "node-sass": "^4.13.1", "request": "^2.83.0", "sass-loader": "^8.0.2", @@ -20,6 +20,8 @@ }, "description": "evan dapp root project for loading sub dapps, that can also be compiled as a mobile application", "devDependencies": { + "terser-webpack-plugin": "^2.3.5", + "copy-webpack-plugin": "^5.1.1", "eslint": "^6.8.0", "eslint-config-airbnb-base": "^14.0.0", "eslint-config-prettier": "^6.9.0", @@ -27,8 +29,10 @@ "eslint-plugin-prettier": "^3.1.2", "ts-loader": "^6.2.1", "typescript": "^3.8.2", + "uglifyjs-webpack-plugin": "^2.2.0", "webpack": "^4.41.6", - "webpack-cli": "^3.3.11" + "webpack-cli": "^3.3.11", + "webpack-node-externals": "^1.7.2" }, "homepage": "https://evannetwork.github.io/", "keywords": [ @@ -39,7 +43,7 @@ "SASS" ], "license": "AGPL-3.0-only", - "main": "dist/app.js", + "main": "dist/dapp-browser.js", "name": "@evan.network/ui-dapp-browser", "repository": { "type": "git", @@ -48,11 +52,9 @@ "scripts": { "build": "npx webpack --mode=production", "build-dev": "npx webpack --mode=development", - "watch": "npx webpack --mode=development --watch", "deploy": "gulp --gulpfile gulp/deployment.js deploy --config", - "doc": "gulp --gulpfile gulp/documentation.js", - "postinstall": "npm rebuild node-sass", - "serve": "gulp --cwd . --gulpfile gulp/serve.js serve && npm run watch" + "serve": "gulp --cwd . --gulpfile gulp/serve.js serve && npm run watch", + "watch": "npx webpack --mode=development --watch" }, "types": "runtime/build/main.d.ts", "version": "2.17.0" diff --git a/src/app/ens.ts b/src/app/ens.ts index 5776489..8d59e2f 100644 --- a/src/app/ens.ts +++ b/src/app/ens.ts @@ -20,12 +20,13 @@ import config from './config'; import { ipfsCatPromise } from './ipfs'; import { devLog } from './utils'; +import bs58Bundle from '../libs/bs58.bundle'; +import sha3Bundle from '../libs/js-sha3.min'; +import BufferPolyFill from '../libs/buffer.polyfill'; -import * as stuff from '../libs/bs58.bundle'; - -console.log(stuff) -const bs58: any = {}; -const keccak256: any = {}; +const Buffer = (BufferPolyFill as any).Buffer; +const bs58 = (bs58Bundle as any); +const keccak256 = (sha3Bundle as any).keccak256; // const bs58 = (window as any).bs58; let ensCache: any = { }; diff --git a/src/app/start.ts b/src/app/start.ts new file mode 100644 index 0000000..88a9322 --- /dev/null +++ b/src/app/start.ts @@ -0,0 +1,58 @@ +/* + Copyright (C) 2018-present evan GmbH. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ +*/ + +import * as loading from './loading'; +import * as routing from './routing'; +import * as utils from './utils'; +import System from '../systemjs/index'; + +/** + * Starts the whole dapp-browser. + * + * @param {boolean} enableRouting dapp-browser watch for url changes and automatically starts + * dapps with ens addresses that were passed to the location + * hash + */ +export default async function(): Promise { + delete (window as any).System; + delete (window as any).SystemJS; + + // add page load performance tracking + (window as any).evanloadTime = Date.now(); + + // check if we are running in dev mode, load dev mode available modules + await Promise.all([ + utils.setUpDevMode(System), + utils.getBrowserName(), + utils.getIsPrivateMode(), + ]); + + try { + routing.initialize(); + await utils.onDeviceReady(); + + // update build number to enable ens cache + if ((window as any).dappBrowserBuild) { + window.localStorage['evan-dapp-browser-build'] = (window as any).dappBrowserBuild || ''; + } + } catch (ex) { + console.error(ex); + utils.showError(); + } +} \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index cfa0906..91a6c6b 100644 --- a/src/index.ts +++ b/src/index.ts @@ -23,76 +23,22 @@ import * as loading from './app/loading'; import * as routing from './app/routing'; import * as utils from './app/utils'; import config from './app/config'; - -import './index.scss'; - -// import libs import System from './systemjs/index'; +import start from './app/start'; +import './index.scss'; -/** - * is inserted when the application was bundled, used to prevent window usage - */ -let evanGlobals: any = { }; - -/** - * add page load performance tracking - */ -(window as any).evanloadTime = Date.now(); - -/**************************************************************************************************/ -const getDomainName = utils.getDomainName; -let web3; - -// prefill bcc for systemjs plugin usage -evanGlobals.ipfsCatPromise = ipfs.ipfsCatPromise; -evanGlobals.restIpfs = ipfs.restIpfs; -evanGlobals.System = System; -evanGlobals.queryParams = routing.getQueryParameters(); - -/** - * Starts the whole dapp-browser. - * - * @param {boolean} enableRouting dapp-browser watch for url changes and automatically starts - * dapps with ens addresses that were passed to the location - * hash - */ -async function startEvan(): Promise { - // check if we are running in dev mode, load dev mode available modules - await Promise.all([ - utils.setUpDevMode(System), - utils.getBrowserName(), - utils.getIsPrivateMode(), - ]); - - // set initial loadin step - loading.raiseProgress(5); - - // load smart-contracts and blockchain-core minimal setup for accessing ens from ipfs - try { - routing.initialize(); - await utils.onDeviceReady(); - - // update build number to enable ens cache - if ((window as any).dappBrowserBuild) { - window.localStorage['evan-dapp-browser-build'] = (window as any).dappBrowserBuild || ''; - } - } catch (ex) { - console.error(ex); - utils.showError(); - } -} - -startEvan(); - -export { +const DAppBrowser = { config, dapp, - evanGlobals, - getDomainName, + getDomainName: utils.getDomainName, ipfs, loading, routing, + start, System, utils, -} +}; + +System.amdDefine('@evan.network/ui-dapp-browser', DAppBrowser); +export default DAppBrowser; diff --git a/src/libs/bs58.bundle.js b/src/libs/bs58.bundle.js index 98d1e06..48196f9 100644 --- a/src/libs/bs58.bundle.js +++ b/src/libs/bs58.bundle.js @@ -1,4 +1,4 @@ -(function(f){debugger;if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.bs58 = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i + diff --git a/src/systemjs/plugins/dapp-content.ts b/src/systemjs/plugins/dapp-content.ts new file mode 100644 index 0000000..58f94a2 --- /dev/null +++ b/src/systemjs/plugins/dapp-content.ts @@ -0,0 +1,221 @@ +/* + Copyright (C) 2018-present evan GmbH. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ +*/ + +import * as utils from '../../app/utils'; +import browserIpfs from '../../libs/browser-ipfs'; +import { restIpfs } from '../../app/ipfs'; + +const importCache: any = { }; + +export default function(System: any) { + /** + * add css from ipfs to the current browser + * + * @param {string} origin ifps folder path + * @param {string} file file name + * @param {string} isIpns Indicates if ipns should be used + */ + function addCSS(origin: string, file: string, isIpns?: boolean) { + const fileID = (origin + file).replace(/^[^a-z]+|[^\w:.-]+/gi, ''); + + // add the css only if it was not applied before + if (file.indexOf('.css') !== -1 && !document.getElementById(fileID)) { + var head = document.getElementsByTagName('head')[0]; + var link = document.createElement('link'); + + link.id = fileID; + link.rel = 'stylesheet'; + + // dev mode checks + if (utils.isDevAvailable(origin.replace('dapps/', '')) && origin.indexOf('Qm') !== 0) { + link.href = origin + '/' + file; + } else { + link.href = browserIpfs.api_url('/' + (isIpns ? 'ipns' : 'ipfs') + '/' + origin + '/' + file); + } + + head.appendChild(link); + } + } + + /** + * load file content including dev switch + * + * @param {any} dbcp dbcp description of the dapp + * @param {string} file file to load from the description + * @return {any} return value of the imported ipfs hash, if css, + * returns nothing + */ + function importIpfs(dbcp: any, file: any) { + let dappName = dbcp.ensAddress; + + try { + dappName = /^(.*)\.[^.]+$/.exec(dappName)[1]; + } catch (ex) { } + + if (utils.isDevAvailable(dappName) && dappName.indexOf('0x') !== 0) { + if (file.indexOf('.css') !== -1) { + addCSS('dapps/' + dappName, file); + } + + // load js files + return 'dapps/' + dappName + '/' + file; + } else { + if (file.indexOf('.css') === -1) { + return restIpfs.api_url('/' + (dbcp.dapp.isIpns ? 'ipns' : 'ipfs') + '/' + dbcp.dapp.origin + '/' + file); + } else { + addCSS(dbcp.dapp.origin, file, dbcp.dapp.isIpns); + } + } + }; + + /** + * Loads a predefined library. (bcc / smart-contracts) using a specific + * pattern. + * + * @param {string} ensAddress ens address of the DApp + * @param {string} fileOrigin ipfs folder hash + * @param {Function} originalFetch SystemJS original fetch + * @return {any} result of the ipfs import + */ + function loadPredefinedLib(ensAddress: string, fileOrigin: string, originalFetch: Function) { + const origin = fileOrigin.split('/')[0]; + const file = fileOrigin.split('/')[1]; + + // bccsystemjs will replace with correct ipfs hash before prod deployment + return importIpfs({ + ensAddress: ensAddress, + dapp: { + origin: origin, + isIpns: true + } + }, + file, + ); + } + + /** + * Handle data handling for requested files params. + * + * @param {any} params SystemJS parameters + * @param {Function} originalFetch SystemJS original fetch function + * @return {Promise} resolved when everything is loaded + */ + async function locateDAppContent(params: any, originalFetch: Function) { + // concadinate the window.location. origin with the correctly SystemJS parsed base url (=> remove + // index.html / dev.html) + const baseUrl = window.location.origin + (window.location.pathname + .split('/') + .slice(0, -1) + .join('/')); + + // remove the origin and leading slashes / #/ + const clearAddress = params.address + .replace(baseUrl, '') + .replace(/^(#\/|\/)/g, '') + .split('#')[0]; + const requiredFile = clearAddress.split('/').pop(); + const ensAddress = clearAddress.split('/')[0]; + + let dbcpAddressToLoad = ensAddress + '!ens'; + + // if it was already loaded, return it instantly + const importCacheKey = dbcpAddressToLoad !== requiredFile ? dbcpAddressToLoad + requiredFile : + dbcpAddressToLoad; + if (importCache[importCacheKey]) { + return importCache[importCacheKey]; + } + + // load dbcp configuration from ens address + const dbcp = await System.import(dbcpAddressToLoad); + const promises = [ ]; + + dbcp.ensAddress = ensAddress; + + // check for valid dbcp dapp configuration + if (dbcp && dbcp.dapp) { + // use the default entrypoint if + // - import dapp content was opened without an file parameter + // - an required file should be loaded but not no files array exists or the file is not + // included into the dbcp configuration + if (requiredFile === ensAddress || + !dbcp.dapp.files || + (dbcp.dapp.files && dbcp.dapp.files.indexOf(requiredFile) === -1)) { + // load entrypoint js + promises.push(importIpfs(dbcp, dbcp.dapp.entrypoint)); + } else { + promises.push(importIpfs(dbcp, requiredFile)); + } + + // iterate through all files to check for css files to load + if (dbcp.dapp.files) { + dbcp.dapp.files.forEach((file: string) => { + if (file.endsWith('.css')) { + importIpfs(dbcp, file); + } + }); + } + + // wait for css and ens content to be resolved + return Promise + .all(promises) + .then(results => { + importCache[importCacheKey] = results.pop() || { }; + + return importCache[importCacheKey]; + }); + } else { + console.error('dbcp invalid dapp'); + throw new Error('dbcp invalid dapp'); + } + }; + + /** + Overwrites the fetch function to enable js loading over script tags, that will reduce memory usage + + @param {any} params SystemJS parameters + @param {Function} originalFetch SystemJS original fetch function + */ + function fetchDAppContent(params: any, originalFetch: Function) { + if (typeof params.address !== 'string' || params.address.endsWith('.css')) { + return ''; + } else { + params.metadata.scriptLoad = true; + + return originalFetch(params); + } + } + + /** + * Use translate to return an fake object when loading only css dapp libraries. + * + * @param {params} params systemjs translate params + */ + function translate(params: any) { + if (typeof params.address !== 'string' || params.address.endsWith('.css')) { + params.metadata.format = 'cjs'; + return 'module.exports = {}'; + } + }; + + return { + locate: locateDAppContent, + fetch: fetchDAppContent, + translate, + }; +} diff --git a/src/systemjs/plugins/ens.ts b/src/systemjs/plugins/ens.ts new file mode 100644 index 0000000..bc4b658 --- /dev/null +++ b/src/systemjs/plugins/ens.ts @@ -0,0 +1,116 @@ +/* + Copyright (C) 2018-present evan GmbH. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ +*/ + +import * as utils from '../../app/utils'; +import System from '../index'; +import { getQueryParameters } from '../../app/routing'; +import { ipfsCatPromise } from '../../app/ipfs'; +import { resolveContent } from '../../app/ens'; + +export default function(System: any) { + // libraries that should be cached + let cachableDBCPs = [ ]; + + /** + * Wrap data handling to be able to switch between dev and production mode => + * default load ens, development load from external + * + * @param {string} ensAddress ens address to load the definition for + * @return {any} The definition from ens. + */ + const getDefinitionFromEns = async function(ensAddress: string, domain: string) { + // remove domain from the end of the ensAddress to get the dapp name + let split = ensAddress + .replace(`angular-core`, `angularcore`) + .replace(`angular-libs`, `angularlibs`) + .replace(`smart-contracts`, `smartcontracts`) + .split('.'); + const dappName = split.slice(0, split.length - 1).join('.'); + + // get correct ens address and check if a cached ens is availabled + const validEnsAddress = ensAddress; + let dbcp; + + try { + if (utils.isDevAvailable(dappName) && ensAddress.indexOf('0x') !== 0) { + // load json and resolve it as stringified + dbcp = await System.import('dapps/' + dappName + '/dbcp.json!json'); + } else if (validEnsAddress.indexOf('Qm') === 0) { + dbcp = await ipfsCatPromise(validEnsAddress); + } else { + dbcp = await resolveContent(validEnsAddress); + } + } catch (ex) { + console.dir(ex); + } + + return JSON.stringify(dbcp && dbcp.public ? dbcp.public : dbcp); + }; + + /** + * Handle data handling for requested files params. + * + * @param {any} params SystemJS parameters + * @param {Function} originalFetch SystemJS original fetch function + * @return {Promise} resolved when everything is loaded + */ + function fetch(params: any) { + // parse ens address from requested url source + const ensAddress = params.address.split('/').pop(); + const rootDomain = ensAddress.split('.').pop(); + const queryParams = getQueryParameters(); + // check if dev domain is enabled, check for localStorage params or check for quer params + const devDomain = window.localStorage['evan-dev-dapps-domain'] || + queryParams['dev-domain']; + // enable devMode automatically, when queryparams for dev domain is enabled + const devMode = !!queryParams['dev-domain'] || + window.localStorage['evan-developer-mode'] === 'true'; + + // if the dapps dev domain is enabled, try to load the dapp from this url + if (devMode && devDomain && ensAddress.indexOf('Qm') !== 0) { + // replace the root domain at the end of the ens address with the dev domain + const ensDevAddress = ensAddress.slice( + 0, + ensAddress.lastIndexOf('.' + rootDomain) + ) + '.' + devDomain + + // try to load from dev domain, if is + return Promise.resolve() + .then(() => getDefinitionFromEns(ensDevAddress, devDomain)) + .catch(() => getDefinitionFromEns(ensAddress, rootDomain)); + } else { + return getDefinitionFromEns(ensAddress, rootDomain); + } + }; + + /** + * use translate to handle json results => format result as common js and + prepend an module.exports, so the json will be returned + + @param {} load original load function + @return {string} module.exports + source, call SystemJS to return JSON + */ + function translate(load: any) { + load.metadata.format = 'cjs'; + + return 'module.exports = ' + load.source; + }; + + return { fetch, translate }; +} diff --git a/src/systemjs/plugins/index.ts b/src/systemjs/plugins/index.ts new file mode 100644 index 0000000..528bffa --- /dev/null +++ b/src/systemjs/plugins/index.ts @@ -0,0 +1,34 @@ +/* + Copyright (C) 2018-present evan GmbH. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ +*/ + +import registerDAppContent from './dapp-content'; +import registerEns from './ens'; +import registerIpfs from './ipfs'; +import registerJson from './json'; +import registerText from './text'; + +function registerPlugins(System: any) { + System.amdDefine('dapp-content', registerDAppContent(System)); + System.amdDefine('ens', registerEns(System)); + System.amdDefine('ipfs', registerIpfs(System)); + System.amdDefine('json', registerJson(System)); + System.amdDefine('text', registerText(System)); +} + +export { registerPlugins }; \ No newline at end of file diff --git a/src/systemjs/plugins/ipfs.ts b/src/systemjs/plugins/ipfs.ts new file mode 100644 index 0000000..112742b --- /dev/null +++ b/src/systemjs/plugins/ipfs.ts @@ -0,0 +1,68 @@ +/* + Copyright (C) 2018-present evan GmbH. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ +*/ + +import * as utils from '../../app/utils'; +import { ipfsCatPromise } from '../../app/ipfs'; + +export default function(System: any) { + const devLoad = function(externalFilePath: string, params: any, originalFetch: Function) { + params.address = 'dapps/' + externalFilePath; + params.metadata = { }; + + return originalFetch(params); + }; + + const devCoreLibs = [ + 'bcc/bcc.js', + 'smartcontracts/compiled.js' + ]; + + /** + * Handle data handling for requested files params. + * + * @param {any} params SystemJS parameters + * @param {Function} originalFetch SystemJS original fetch function + * @return {Promise} resolved when everything is loaded + */ + function fetchIpfs(params: any, originalFetch: Function) { + // get current window location without any postfix + // => http://localhost:8080/ipfs/.../.../index.html?asd=blu#125=hash8162 + // => http://localhost:8080/ipfs/../.. + const relativeWindowLocation = (window.location.origin + window.location.pathname) + .replace(/\/dev.html|\/index.html/g, ''); + + // get the correct ipfs route without the window location + let ipfsRoute = params.address + .replace(relativeWindowLocation, '') + .replace(/\//g, ''); + + // check for dev load + if (utils.devMode) { + for (let i = 0; i < devCoreLibs.length; i++) { + if (ipfsRoute.indexOf(devCoreLibs[i]) !== -1 && utils.isDevAvailable(devCoreLibs[i].split('/')[0])) { + return devLoad(devCoreLibs[i], params, originalFetch); + } + } + } + + return ipfsCatPromise(ipfsRoute); + }; + + return { fetch: fetchIpfs }; +} diff --git a/src/systemjs/plugins/json.ts b/src/systemjs/plugins/json.ts new file mode 100644 index 0000000..e462cd4 --- /dev/null +++ b/src/systemjs/plugins/json.ts @@ -0,0 +1,34 @@ +/* + Copyright (C) 2018-present evan GmbH. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ +*/ + +export default function(System: any) { + /** + * use translate to handle json results => format result as common js and + * prepend an module.exports, so the json will be returned + * + * @param {any} load original load object + * @return {string} module.exports + source, call SystemJS to return JSON + */ + function translate(load: any) { + load.metadata.format = 'cjs'; + return 'module.exports = ' + load.source; + }; + + return { translate }; +} diff --git a/src/systemjs/plugins/text.ts b/src/systemjs/plugins/text.ts new file mode 100644 index 0000000..f6a4211 --- /dev/null +++ b/src/systemjs/plugins/text.ts @@ -0,0 +1,38 @@ +/* + Copyright (C) 2018-present evan GmbH. + + This program is free software: you can redistribute it and/or modify it + under the terms of the GNU Affero General Public License, version 3, + as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see http://www.gnu.org/licenses/ or + write to the Free Software Foundation, Inc., 51 Franklin Street, + Fifth Floor, Boston, MA, 02110-1301 USA, or download the license from + the following URL: https://evan.network/license/ +*/ + +export default function(System: any) { + /** + * Load basic text (used for css) + * + * @param {string} load SystemJS payload properties + * @return {string} location adjusted to return only text + */ + function translate(load: any) { + if (this.builder && this.transpiler) { + load.metadata.format = 'esm'; + return 'exp' + 'ort var __useDefault = ' + JSON.stringify(load.source) + '; exp' + 'ort default __useDefault;'; + } + + load.metadata.format = 'amd'; + return 'def' + 'ine(function() {\nreturn ' + JSON.stringify(load.source) + ';\n});'; + } + + return { translate }; +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json index eba2dd5..780df75 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,6 @@ "jsx": "react", "module": "es6", "noImplicitAny": true, - "outDir": "./runtime/", "sourceMap": true, "target": "es5" } diff --git a/webpack.config.js b/webpack.config.js index 2b2268b..96053a5 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -1,17 +1,21 @@ -const path = require('path'); const CopyWebpackPlugin = require('copy-webpack-plugin'); +const nodeExternals = require('webpack-node-externals'); +const path = require('path'); +const TerserPlugin = require('terser-webpack-plugin'); +const webpack = require('webpack'); +const argv = require('minimist')(process.argv.slice(2)); const outFolder = path.resolve(__dirname, 'dist'); -module.exports = { +const config = { entry: './src/index.ts', - devtool: 'inline-source-map', + mode: argv.mode || 'production', module: { rules: [ { test: /\.tsx?$/, use: 'ts-loader', - exclude: /node_modules/, + exclude: /node_modules|dist/, }, { test: /\.s[ac]ss$/i, @@ -27,12 +31,14 @@ module.exports = { ], }, plugins: [ - new CopyWebpackPlugin([ - { - flatten: true, - from: 'src/static/*', - } - ]) + new CopyWebpackPlugin([{ + flatten: true, + from: 'src/static/*', + }]), + new webpack.SourceMapDevToolPlugin({ + filename: 'dapp-browser.js.map', + exclude: ['libs'] + }), ], resolve: { extensions: [ '.tsx', '.ts', '.js' ], @@ -42,3 +48,26 @@ module.exports = { path: outFolder, }, }; + +if (argv.mode === 'production') { + config.devtool = '#source-map'; + // http://vue-loader.vuejs.org/en/workflow/production.html + config.plugins = config.plugins.concat([ + new webpack.DefinePlugin({ + 'process.env': { + NODE_ENV: '"production"', + }, + }), + new TerserPlugin({ + parallel: true, + terserOptions: { + ecma: 6, + output: { + comments: false, + }, + }, + }), + ]); +} + +module.exports = config; \ No newline at end of file