Fix dashboard (#12)

* TS replaced with js

* Livereload works for ELM part

* Fix layout issue with empty spaces

* Using pure css spinners

* Fixed services not being displayed in module page
This commit is contained in:
Pavel 2021-06-09 22:18:03 +03:00 committed by GitHub
parent ddc7cd7a57
commit d7a59b2ff0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 2872 additions and 5993 deletions

View File

@ -1,5 +1,6 @@
* *
**/* **/*
!bundle/ !bundle/
!dist/
!Caddyfile !Caddyfile
!nginx.conf !nginx.conf

View File

@ -16,14 +16,40 @@ module.exports = {
'plugin:prettier/recommended', 'plugin:prettier/recommended',
], ],
plugins: ['@typescript-eslint', 'prettier'], plugins: ['@typescript-eslint', 'prettier'],
rules: {}, rules: {
'func-names': ['error', 'as-needed'],
'prefer-destructuring': 'off',
'object-shorthand': ['error', 'consistent-as-needed'],
'no-restricted-syntax': ['error', 'ForInStatement', 'LabeledStatement', 'WithStatement'],
'import/prefer-default-export': 'off',
'import/extensions': [
'error',
'ignorePackages',
{
js: 'never',
mjs: 'never',
jsx: 'never',
ts: 'never',
tsx: 'never',
},
],
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': ['error', { varsIgnorePattern: '^_', argsIgnorePattern: '^_' }],
'@typescript-eslint/no-explicit-any': 'off',
// should be overriden for current project only
'no-param-reassign': ['error', { props: false }],
'no-console': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
},
settings: { settings: {
// 'import/resolver': { 'import/extensions': ['.js', '.ts', '.jsx', '.tsx'],
// browser: { 'import/resolver': {
// extensions: ['.js', '.js', '.ts', '.ts', '.css', '.elm'], typescript: {},
// paths: ['src'], node: {
// }, paths: ['src'],
// }, },
'import/extensions': ['.js', '.ts'], },
}, },
}; };

View File

@ -28,7 +28,7 @@ jobs:
node-version: 14 node-version: 14
- run: npm install - run: npm install
- run: npm run pack - run: npm run build
env: env:
CI: true CI: true

View File

@ -1,6 +1,6 @@
FROM caddy FROM caddy
WORKDIR / WORKDIR /
COPY ./bundle /bundle COPY ./dist /bundle
COPY Caddyfile /Caddyfile COPY Caddyfile /Caddyfile
#RUN printf '\n\ #RUN printf '\n\

View File

@ -1,15 +1,12 @@
{ {
"type": "application", "type": "application",
"source-directories": [ "source-directories": ["src"],
"src"
],
"elm-version": "0.19.1", "elm-version": "0.19.1",
"dependencies": { "dependencies": {
"direct": { "direct": {
"Chadtech/unique-list": "2.1.4", "Chadtech/unique-list": "2.1.4",
"avh4/elm-color": "1.0.0", "avh4/elm-color": "1.0.0",
"ccapndave/elm-flat-map": "1.2.0", "ccapndave/elm-flat-map": "1.2.0",
"damienklinnert/elm-spinner": "3.0.2",
"elm/browser": "1.0.2", "elm/browser": "1.0.2",
"elm/core": "1.0.5", "elm/core": "1.0.5",
"elm/html": "1.0.0", "elm/html": "1.0.0",

BIN
favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -16,7 +16,6 @@
<title>Fluence Network Dashboard</title> <title>Fluence Network Dashboard</title>
</head> </head>
<body> <body>
<script src="/bundle.js"></script>
<!-- Global site tag (gtag.js) - Google Analytics --> <!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-6ZTQKE1D4L"></script> <script async src="https://www.googletagmanager.com/gtag/js?id=G-6ZTQKE1D4L"></script>
<script> <script>

View File

@ -1,4 +0,0 @@
FROM nginx
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
COPY ./bundle /usr/share/nginx/html

View File

@ -1,9 +0,0 @@
server {
listen 80;
server_name frontend;
location / {
# This would be the directory where your React app's static files are stored at
root /usr/share/nginx/html;
try_files $uri /index.html;
}
}

8092
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,61 +1,62 @@
{ {
"name": "fluence-admin", "name": "fluence-admin",
"version": "0.0.1", "version": "0.0.1",
"description": "", "description": "",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"start": "npx webpack && docker build -f nginx.Dockerfile -t dashboard . && docker run --rm --name dashboard -p443:443 -p80:80 dashboard", "test": "elm-test",
"serve": "webpack serve", "start": "npm run dev",
"pack": "webpack --mode production", "dev": "webpack-dev-server --hot --colors --port 3000",
"prettier-format": "prettier --config .prettierrc 'src/**/*.ts' --write" "build": "webpack",
}, "prod": "webpack -p",
"repository": { "analyse": "elm-analyse -s -p 3001 -o"
"type": "git", },
"url": "git+https://github.com/fluencelabs/fluence-admin.git" "repository": {
}, "type": "git",
"author": "", "url": "git+https://github.com/fluencelabs/fluence-admin.git"
"license": "ISC", },
"bugs": { "author": "",
"url": "https://github.com/fluencelabs/fluence-admin/issues" "license": "ISC",
}, "bugs": {
"homepage": "https://github.com/fluencelabs/fluence-admin#readme", "url": "https://github.com/fluencelabs/fluence-admin/issues"
"dependencies": { },
"@fluencelabs/fluence": "0.9.42", "homepage": "https://github.com/fluencelabs/fluence-admin#readme",
"@fluencelabs/fluence-network-environment": "1.0.8", "dependencies": {
"tachyons": "^4.12.0", "@fluencelabs/fluence": "0.9.47",
"yup": "^0.32.9" "@fluencelabs/fluence-network-environment": "1.0.9",
}, "css-spinners": "^1.0.1",
"devDependencies": { "tachyons": "^4.12.0",
"@types/yup": "^0.29.11", "yup": "^0.32.9"
"@babel/core": "7.12.9", },
"@typescript-eslint/eslint-plugin": "^4.9.0", "devDependencies": {
"@typescript-eslint/parser": "^4.9.0", "@babel/core": "^7.11.6",
"clean-webpack-plugin": "3.0.0", "@babel/preset-env": "^7.11.5",
"copy-webpack-plugin": "6.3.2", "@types/yup": "^0.29.11",
"create-elm-app": "5.18.0", "babel-loader": "^8.1.0",
"css-loader": "5.0.1", "clean-webpack-plugin": "^3.0.0",
"elm-hot-webpack-loader": "1.1.7", "closure-webpack-plugin": "^2.3.0",
"elm-webpack-loader": "7.0.1", "copy-webpack-plugin": "^6.4.1",
"eslint": "^7.14.0", "css-loader": "^4.3.0",
"eslint-config-airbnb": "^18.2.1", "elm": "^0.19.1-3",
"eslint-config-airbnb-base": "^14.2.1", "elm-analyse": "^0.16.5",
"eslint-config-prettier": "^6.15.0", "elm-format": "^0.8.4",
"eslint-plugin-import": "^2.22.1", "elm-hot-webpack-loader": "^1.1.7",
"eslint-plugin-node": "^11.1.0", "elm-test": "^0.19.1-revision4",
"eslint-plugin-prettier": "^3.1.4", "elm-webpack-loader": "^6.0.1",
"eslint-plugin-promise": "^4.2.1", "file-loader": "^6.1.0",
"html-webpack-plugin": "4.5.0", "google-closure-compiler": "^20200920.0.0",
"http-server": "0.12.3", "html-webpack-plugin": "^4.5.0",
"prettier": "2.2.1", "mini-css-extract-plugin": "^0.11.2",
"replace-in-file": "6.1.0", "node-sass": "^4.14.1",
"source-map-loader": "1.1.2", "optimize-css-assets-webpack-plugin": "^5.0.4",
"style-loader": "2.0.0", "resolve-url-loader": "^3.1.1",
"ts-loader": "8.0.11", "source-map-loader": "^1.0.0",
"typescript": "4.1.2", "sass-loader": "^10.0.2",
"webpack": "5.7.0", "style-loader": "^1.2.1",
"webpack-cli": "4.2.0", "url-loader": "^4.1.0",
"webpack-nano": "^1.1.0", "webpack": "^4.44.2",
"webpack-plugin-serve": "^1.2.0", "webpack-cli": "^3.3.12",
"webpack-serve": "3.2.0" "webpack-dev-server": "^3.11.0",
} "webpack-merge": "^5.1.4"
}
} }

View File

@ -3,7 +3,7 @@ module BlueprintPage.View exposing (..)
import BlueprintPage.Model exposing (BlueprintViewInfo) import BlueprintPage.Model exposing (BlueprintViewInfo)
import Blueprints.Model exposing (Blueprint) import Blueprints.Model exposing (Blueprint)
import Dict exposing (Dict) import Dict exposing (Dict)
import Html exposing (Html, a, article, div, img, span, text) import Html exposing (Html, a, article, div, img, span, strong, text)
import Html.Attributes exposing (attribute) import Html.Attributes exposing (attribute)
import Html.Events exposing (onClick) import Html.Events exposing (onClick)
import Info exposing (getBlueprintDescription) import Info exposing (getBlueprintDescription)
@ -81,6 +81,19 @@ blueprintToInfo model id =
Nothing Nothing
-- TODO:: do this for all possible places which could be empty
textOrBsp : String -> String
textOrBsp text =
if text == "" then
String.fromChar (Char.fromCode 0xA0)
else
text
viewInfo : BlueprintViewInfo -> Html Msg viewInfo : BlueprintViewInfo -> Html Msg
viewInfo blueprintInfo = viewInfo blueprintInfo =
let let
@ -88,14 +101,19 @@ viewInfo blueprintInfo =
\id -> blueprintInfo.openedModule |> Maybe.map (\om -> om == id) |> Maybe.withDefault False \id -> blueprintInfo.openedModule |> Maybe.map (\om -> om == id) |> Maybe.withDefault False
in in
article [ classes "cf" ] article [ classes "cf" ]
[ div [ classes "fl w-100 w-20-ns gray-font mv3" ] [ text "AUTHOR" ] [ div [ classes "fl w-20-ns gray-font mv3" ] [ text "AUTHOR" ]
, div [ classes "fl w-100 w-80-ns mv3 lucida" ] , div [ classes "fl w-80-ns mv3 lucida" ]
[ span [ classes "fl w-100 black b" ] [ text blueprintInfo.author ] ] [ span [ classes "fl black b" ] [ text (textOrBsp blueprintInfo.author) ] ]
, div [ classes "fl w-100 w-20-ns gray-font mv3" ] [ text "DESCRIPTION" ] , div [ classes "fl w-20-ns gray-font mv3" ] [ text "DESCRIPTION" ]
, div [ classes "fl w-100 w-80-ns mv3" ] [ span [ classes "fl w-100 black lucida pv1" ] [ text blueprintInfo.description ] ] , div [ classes "fl w-80-ns mv3 cf" ]
, div [ classes "fl w-100 w-20-ns gray-font mv3" ] [ text "MODULES" ] [ span [ classes "fl black lucida pv1" ] [ text (textOrBsp blueprintInfo.description) ] ]
, div [ classes "fl w-100 w-80-ns mv3" ] , div [ classes "fl w-20-ns gray-font mv3" ] [ text "MODULES" ]
[ text (String.join ", " (blueprintInfo.modules |> List.map (\m -> m.name))) ] , div [ classes "fl w-80-ns mv3" ]
[ text
(textOrBsp
(String.join ", " (blueprintInfo.modules |> List.map (\m -> m.name)))
)
]
--(blueprintInfo.modules --(blueprintInfo.modules
-- |> List.map (\m -> viewToggledInterface (checkToggle m.name) m.name) -- |> List.map (\m -> viewToggledInterface (checkToggle m.name) m.name)

View File

@ -23,7 +23,6 @@ import Dict
import Model exposing (Model) import Model exposing (Model)
import Msg exposing (Msg(..)) import Msg exposing (Msg(..))
import Route import Route
import Spinner
import Subscriptions exposing (subscriptions) import Subscriptions exposing (subscriptions)
import Update exposing (update) import Update exposing (update)
import Url import Url
@ -60,7 +59,6 @@ init flags url key =
, toggledInterface = Nothing , toggledInterface = Nothing
, knownPeers = flags.knownPeers , knownPeers = flags.knownPeers
, isInitialized = False , isInitialized = False
, spinner = Spinner.init
} }
in in
( emptyModel, Route.routeCommand emptyModel r ) ( emptyModel, Route.routeCommand emptyModel r )

1
src/Main.elm.d.ts vendored
View File

@ -1 +0,0 @@
export const Elm: any

View File

@ -22,7 +22,6 @@ import Dict exposing (Dict)
import Modules.Model exposing (Module) import Modules.Model exposing (Module)
import Nodes.Model exposing (Identify, emptyIdentify) import Nodes.Model exposing (Identify, emptyIdentify)
import Service.Model exposing (Service) import Service.Model exposing (Service)
import Spinner
import Url import Url
@ -59,5 +58,4 @@ type alias Model =
, toggledInterface : Maybe String , toggledInterface : Maybe String
, knownPeers : List String , knownPeers : List String
, isInitialized : Bool , isInitialized : Bool
, spinner : Spinner.Model
} }

View File

@ -1,5 +1,6 @@
module ModulePage.View exposing (..) module ModulePage.View exposing (..)
import Debug exposing (toString)
import Dict exposing (Dict) import Dict exposing (Dict)
import Html exposing (Html, a, article, div, span, text) import Html exposing (Html, a, article, div, span, text)
import Html.Attributes exposing (attribute, property) import Html.Attributes exposing (attribute, property)
@ -12,6 +13,7 @@ import ModulePage.Model exposing (ModuleViewInfo)
import Modules.Model exposing (Module) import Modules.Model exposing (Module)
import Palette exposing (classes, redFont) import Palette exposing (classes, redFont)
import SpinnerView exposing (spinner) import SpinnerView exposing (spinner)
import Utils.Utils exposing (hashValueFromString)
view : Model -> String -> Html msg view : Model -> String -> Html msg
@ -23,8 +25,11 @@ view model id =
case moduleInfo of case moduleInfo of
Just mi -> Just mi ->
let let
hash =
mi.moduleInfo.hash
check = check =
Maybe.map (\bp -> bp.dependencies |> List.member id) Maybe.map (\bp -> bp.dependencies |> List.map hashValueFromString |> List.member hash)
filter = filter =
\s -> model.blueprints |> Dict.get s.blueprint_id |> check |> Maybe.withDefault False \s -> model.blueprints |> Dict.get s.blueprint_id |> check |> Maybe.withDefault False

View File

@ -76,9 +76,7 @@ filterByModuleName bps moduleName =
names = names =
\bp -> \bp ->
bp.dependencies bp.dependencies
|> List.map (\d -> String.split ":" d) |> List.map Utils.Utils.hashValueFromString
|> List.map (\p -> Maybe.withDefault [] (List.tail p))
|> List.map (\p -> Maybe.withDefault "" (List.head p))
check = check =
Maybe.map (\bp -> names bp |> List.member moduleName) Maybe.map (\bp -> names bp |> List.member moduleName)
@ -95,9 +93,7 @@ filterByModuleHash bps moduleHash =
hashes = hashes =
\bp -> \bp ->
bp.dependencies bp.dependencies
|> List.map (\d -> String.split ":" d) |> List.map Utils.Utils.hashValueFromString
|> List.map (\p -> Maybe.withDefault [] (List.tail p))
|> List.map (\p -> Maybe.withDefault "" (List.head p))
check = check =
Maybe.map (\bp -> hashes bp |> List.member moduleHash) Maybe.map (\bp -> hashes bp |> List.member moduleHash)

View File

@ -2,7 +2,6 @@ module Msg exposing (..)
import Browser exposing (UrlRequest) import Browser exposing (UrlRequest)
import Port import Port
import Spinner
import Url import Url
@ -13,5 +12,4 @@ type Msg
| AquamarineEvent Port.ReceiveEvent | AquamarineEvent Port.ReceiveEvent
| RelayChanged String | RelayChanged String
| ToggleInterface String | ToggleInterface String
| SpinnerMsg Spinner.Msg
| Reload | Reload

View File

@ -1,33 +1,13 @@
module SpinnerView exposing (..) module SpinnerView exposing (..)
import Color
import Html exposing (Html) import Html exposing (Html)
import Html.Attributes exposing (height, width)
import Model exposing (Model) import Model exposing (Model)
import Palette exposing (classes) import Palette exposing (classes)
import Spinner
spinner : Model -> List (Html msg) spinner : Model -> List (Html msg)
spinner model = spinner model =
[ Html.div [ classes "p3 relative" ] [ Html.div [ classes "p3 relative" ]
[ Spinner.view [ Html.div [ classes "spin" ] [] ]
{ lines = 11
, length = 20
, width = 9
, radius = 21
, scale = 0.5
, corners = 1
, opacity = 0.25
, rotate = 0
, direction = Spinner.Clockwise
, speed = 1
, trail = 60
, translateX = 50
, translateY = 50
, shadow = True
, hwaccel = False
, color = always <| Color.rgba 255 255 255 1
}
model.spinner
]
] ]

View File

@ -19,12 +19,10 @@ limitations under the License.
import Model exposing (Model) import Model exposing (Model)
import Msg exposing (Msg(..)) import Msg exposing (Msg(..))
import Port exposing (eventReceiver) import Port exposing (eventReceiver)
import Spinner
subscriptions : Model -> Sub Msg subscriptions : Model -> Sub Msg
subscriptions model = subscriptions model =
Sub.batch Sub.batch
[ eventReceiver AquamarineEvent [ eventReceiver AquamarineEvent
, Sub.map SpinnerMsg Spinner.subscription
] ]

View File

@ -29,7 +29,6 @@ import Nodes.Model exposing (Identify)
import Port exposing (sendAir) import Port exposing (sendAir)
import Route exposing (getAllCmd) import Route exposing (getAllCmd)
import Service.Model exposing (Service) import Service.Model exposing (Service)
import Spinner
import Url import Url
@ -108,15 +107,6 @@ update msg model =
Reload -> Reload ->
( model, sendAir (GetAll.air model.peerId model.relayId model.knownPeers) ) ( model, sendAir (GetAll.air model.peerId model.relayId model.knownPeers) )
SpinnerMsg spinnerMsg ->
let
spinnerModel =
Spinner.update spinnerMsg model.spinner
in
( { model | spinner = spinnerModel }
, Cmd.none
)
updateModel : Model -> String -> Identify -> List Service -> List Module -> List Blueprint -> Model updateModel : Model -> String -> Identify -> List Service -> List Module -> List Blueprint -> Model
updateModel model peer identify services modules blueprints = updateModel model peer identify services modules blueprints =

View File

@ -3,6 +3,11 @@ module Utils.Utils exposing (..)
import Html exposing (Html) import Html exposing (Html)
hashValueFromString : String -> String
hashValueFromString x =
x |> String.split ":" |> List.tail |> Maybe.andThen List.head |> Maybe.withDefault ""
instancesText : Int -> Html msg instancesText : Int -> Html msg
instancesText num = instancesText num =
let let

View File

@ -15,21 +15,29 @@
*/ */
import 'tachyons/css/tachyons.min.css'; import 'tachyons/css/tachyons.min.css';
import 'css-spinners/dist/all.min.css';
import './main.css'; import './main.css';
// eslint-disable-next-line import/no-extraneous-dependencies // eslint-disable-next-line import/no-extraneous-dependencies
import log from 'loglevel'; import log from 'loglevel';
import { Node, dev, testNet } from '@fluencelabs/fluence-network-environment'; import { dev, testNet } from '@fluencelabs/fluence-network-environment';
import { createClient, generatePeerId, Particle, sendParticle, subscribeToEvent } from '@fluencelabs/fluence'; import {
createClient,
generatePeerId,
Particle,
sendParticle,
subscribeToEvent,
setLogLevel,
} from '@fluencelabs/fluence';
import { Elm } from './Main.elm'; import { Elm } from './Main.elm';
import * as serviceWorker from './serviceWorker'; import * as serviceWorker from './serviceWorker';
import {EventType, eventType} from "./types"; import { eventType } from './types';
const relayIdx = 3; const relayIdx = 3;
const relays: Node[] = testNet; const relays = testNet;
// const relays: Node[] = dev; // const relays = dev;
function genFlags(peerId: string): any { function genFlags(peerId) {
return { return {
peerId, peerId,
relayId: relays[relayIdx].peerId, relayId: relays[relayIdx].peerId,
@ -38,15 +46,7 @@ function genFlags(peerId: string): any {
} }
/* eslint-disable */ /* eslint-disable */
function event( function event(name, peer, peers, identify, services, modules, blueprints) {
name: string,
peer: string,
peers?: string[],
identify?: any,
services?: any[],
modules?: any[],
blueprints?: any[],
) {
if (!peers) { if (!peers) {
peers = null; peers = null;
} }
@ -68,7 +68,8 @@ function event(
/* eslint-enable */ /* eslint-enable */
(async () => { (async () => {
log.setLevel('silent'); setLogLevel('SILENT');
const pid = await generatePeerId(); const pid = await generatePeerId();
const flags = genFlags(pid.toB58String()); const flags = genFlags(pid.toB58String());
console.log(`connect with client: ${pid.toB58String()}`); console.log(`connect with client: ${pid.toB58String()}`);
@ -78,7 +79,7 @@ function event(
const app = Elm.Main.init({ const app = Elm.Main.init({
node: document.getElementById('root'), node: document.getElementById('root'),
flags, flags: flags,
}); });
subscribeToEvent(client, 'event', 'peers_discovered', (args, _tetraplets) => { subscribeToEvent(client, 'event', 'peers_discovered', (args, _tetraplets) => {
@ -91,29 +92,38 @@ function event(
subscribeToEvent(client, 'event', 'all_info', (args, _tetraplets) => { subscribeToEvent(client, 'event', 'all_info', (args, _tetraplets) => {
try { try {
let peerId = args[0]; const peerId = args[0];
let identify = args[1]; const identify = args[1];
let services = args[2]; const services = args[2];
let blueprints = args[3]; const blueprints = args[3];
let modules = args[4]; const modules = args[4];
let eventRaw = { const eventRaw = {
peerId: peerId, peerId,
identify: identify, identify,
services: services, services,
blueprints: blueprints, blueprints,
modules: modules, modules,
} };
const inputEventRaw: any = eventType.cast(eventRaw); const inputEvent = eventType.cast(eventRaw);
const inputEvent = inputEventRaw as EventType;
app.ports.eventReceiver.send(event('all_info', inputEvent.peerId, undefined, inputEvent.identify, inputEvent.services, inputEvent.modules, inputEvent.blueprints)); app.ports.eventReceiver.send(
event(
'all_info',
inputEvent.peerId,
undefined,
inputEvent.identify,
inputEvent.services,
inputEvent.modules,
inputEvent.blueprints,
),
);
} catch (err) { } catch (err) {
log.error('Elm eventreceiver failed: ', err); log.error('Elm eventreceiver failed: ', err);
} }
}); });
app.ports.sendParticle.subscribe(async (part: { script: string; data: any }) => { app.ports.sendParticle.subscribe(async (part) => {
const particle = new Particle(part.script, part.data, 45000); const particle = new Particle(part.script, part.data, 45000);
await sendParticle(client, particle); await sendParticle(client, particle);
}); });
@ -123,16 +133,3 @@ function event(
// unregister() to register() below. Note this comes with some pitfalls. // unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA // Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister(); serviceWorker.unregister();
function setLogLevel(level: any) {
log.setLevel(level);
}
declare global {
interface Window {
test: any;
setLogLevel: any;
}
}
window.setLogLevel = setLogLevel;

46
src/types.js Normal file
View File

@ -0,0 +1,46 @@
import { object, number, string, array, boolean } from 'yup';
export const service = object({
id: string().required(),
owner_id: string().required(),
blueprint_id: string().required(),
});
export const blueprint = object({
dependencies: array(string()).required(),
id: string().required(),
name: string().required(),
facade: string().nullable().notRequired(),
});
export const identify = object({
external_addresses: array(string()).required(),
});
export const wasi = object({
envs: object().notRequired().nullable(),
mapped_dirs: object().notRequired().nullable(),
preopened_files: array(string()).notRequired().nullable(),
});
export const config = object({
logger_enabled: boolean().notRequired().nullable(),
logging_mask: object().notRequired().nullable(),
mem_pages_count: number().notRequired().nullable(),
mounted_binaries: object().notRequired().nullable(),
wasi: wasi.notRequired().nullable(),
});
export const module = object({
config: config.required(),
hash: string().required(),
name: string().required(),
});
export const eventType = object({
peerId: string().required(),
identify: identify.required(),
services: array(service).required(),
blueprints: array(blueprint).required(),
modules: array(module).required(),
});

View File

@ -1,91 +0,0 @@
import { object, number, string, array, SchemaOf, boolean } from "yup";
export const service: SchemaOf<Service> = object({
id: string().required(),
owner_id: string().required(),
blueprint_id: string().required(),
});
export const blueprint: SchemaOf<Blueprint> = object({
dependencies: array(string()).required(),
id: string().required(),
name: string().required(),
facade: string().nullable().notRequired(),
});
export const identify: SchemaOf<Identify> = object({
external_addresses: array(string()).required(),
});
export const wasi: SchemaOf<Wasi> = object({
envs: object().notRequired().nullable(),
mapped_dirs: object().notRequired().nullable(),
preopened_files: array(string()).notRequired().nullable(),
})
export const config: SchemaOf<Config> = object({
logger_enabled: boolean().notRequired().nullable(),
logging_mask: object().notRequired().nullable(),
mem_pages_count: number().notRequired().nullable(),
mounted_binaries: object().notRequired().nullable(),
wasi: wasi.notRequired().nullable(),
})
export const module: SchemaOf<Module> = object({
config: config.required(),
hash: string().required(),
name: string().required(),
})
export const eventType: SchemaOf<EventType> = object({
peerId: string().required(),
identify: identify.required(),
services: array(service).required(),
blueprints: array(blueprint).required(),
modules: array(module).required(),
})
export interface Service {
blueprint_id: string;
id: string;
owner_id: string;
}
export interface Blueprint {
dependencies: string[];
facade?: any;
id: string;
name: string;
}
export interface Wasi {
envs?: any;
mapped_dirs?: any;
preopened_files: any[];
}
export interface Config {
logger_enabled?: boolean;
logging_mask?: any;
mem_pages_count?: number;
mounted_binaries?: any;
wasi?: Wasi;
}
export interface Module {
config: Config;
hash: string;
name: string;
}
export interface Identify {
external_addresses: string[]
}
export interface EventType {
peerId: string,
identify: Identify,
services: Service[],
blueprints: Blueprint[],
modules: Module[],
}

View File

@ -1,28 +0,0 @@
{
"compilerOptions": {
"outDir": "./dist/",
"sourceMap": true,
"inlineSources": true,
"noImplicitAny": true,
"strictFunctionTypes": true,
"allowSyntheticDefaultImports": true,
"resolveJsonModule": true,
"pretty": true,
"target": "es2018",
"module": "commonjs",
"moduleResolution": "node",
"declaration": true,
"strict": true,
"strictNullChecks": false,
"esModuleInterop": true,
"declarationMap": true,
"baseUrl": ".",
"allowJs": true
},
"exclude": [
"node_modules",
"dist",
"bundle"
],
"include": ["src/**/*"]
}

View File

@ -1,82 +1,203 @@
const path = require('path'); const path = require('path');
const { merge } = require('webpack-merge');
const ClosurePlugin = require('closure-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin'); const CopyWebpackPlugin = require('copy-webpack-plugin');
const webpack = require('webpack'); const HTMLWebpackPlugin = require('html-webpack-plugin');
const { WebpackPluginServe: Serve } = require('webpack-plugin-serve'); const { CleanWebpackPlugin } = require('clean-webpack-plugin');
const TerserPlugin = require('terser-webpack-plugin');
module.exports = (env, argv) => { // Production CSS assets - separate, minimised file
const isDebug = argv.mode === 'development'; const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const isProduction = argv.mode === 'production'; const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
return { var MODE = process.env.npm_lifecycle_event === 'prod' ? 'production' : 'development';
entry: { var withDebug = !process.env['npm_config_nodebug'] && MODE === 'development';
app: ['./src/index.ts'], // this may help for Yarn users
// var withDebug = !npmParams.includes("--nodebug");
console.log('\x1b[36m%s\x1b[0m', `** elm-webpack-starter: mode "${MODE}", withDebug: ${withDebug}\n`);
var common = {
mode: MODE,
entry: './src/index.js',
output: {
path: path.join(__dirname, 'dist'),
publicPath: '/',
// FIXME webpack -p automatically adds hash when building for production
filename: MODE === 'production' ? '[name]-[hash].js' : 'index.js',
},
plugins: [
new HTMLWebpackPlugin({
// Use this template to get basic responsive meta tags
template: 'index.html',
// inject details of output file at end of body
inject: 'body',
}),
],
resolve: {
modules: [path.join(__dirname, 'src'), 'node_modules'],
extensions: ['.js', '.elm', '.scss', '.png'],
},
module: {
rules: [
{
test: /\.js$/,
enforce: 'pre',
use: ['source-map-loader'],
},
{
test: /\.js$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
},
},
{
test: /\.scss$/,
exclude: [/elm-stuff/],
// see https://github.com/webpack-contrib/css-loader#url
use: ['style-loader', 'css-loader?url=false', 'sass-loader'],
},
{
test: /\.css$/,
exclude: [/elm-stuff/],
use: ['style-loader', 'css-loader?url=false'],
},
{
test: /\.woff(2)?(\?v=[0-9]\.[0-9]\.[0-9])?$/,
exclude: [/elm-stuff/, /node_modules/],
use: {
loader: 'url-loader',
options: {
limit: 10000,
mimetype: 'application/font-woff',
},
},
},
{
test: /\.(ttf|eot|svg)(\?v=[0-9]\.[0-9]\.[0-9])?$/,
exclude: [/elm-stuff/, /node_modules/],
loader: 'file-loader',
},
{
test: /\.(jpe?g|png|gif|svg)$/i,
exclude: [/elm-stuff/, /node_modules/],
loader: 'file-loader',
},
],
},
};
if (MODE === 'development') {
module.exports = merge(common, {
optimization: {
// Prevents compilation errors causing the hot loader to lose state
noEmitOnErrors: true,
}, },
resolve: {
extensions: ['.js', '.ts', '.elm'],
},
devServer: {
contentBase: './bundle',
hot: false,
inline: false,
},
devtool: 'eval-source-map',
module: { module: {
rules: [ rules: [
{ {
test: /\.html$/, test: /\.elm$/,
use: [{ loader: 'file-loader?name=[name].[ext]' }],
},
{
test: [/\.elm$/],
exclude: [/elm-stuff/, /node_modules/], exclude: [/elm-stuff/, /node_modules/],
use: [ use: [
{ loader: 'elm-hot-webpack-loader' }, { loader: 'elm-hot-webpack-loader' },
{ {
loader: 'elm-webpack-loader', loader: 'elm-webpack-loader',
options: { options: {
debug: isDebug, // add Elm's debug overlay to output
optimize: isProduction, debug: withDebug,
forceWatch: false, //
forceWatch: true,
}, },
}, },
], ],
}, },
{ test: /\.ts$/, loader: 'ts-loader' },
{
test: /\.(png)$/,
loader: 'file-loader',
},
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
], ],
}, },
mode: 'development', devServer: {
watch: isDebug, inline: true,
output: { stats: 'errors-only',
filename: 'bundle.js', contentBase: path.join(__dirname, 'src/assets'),
path: path.resolve(__dirname, 'bundle'), historyApiFallback: true,
publicPath: '/', // feel free to delete this section if you don't need anything like this
}, before(app) {
optimization: { // on port 3000
minimize: isProduction, app.get('/test', function (req, res) {
minimizer: [new TerserPlugin()], res.json({ result: 'OK' });
});
},
}, },
plugins: [ plugins: [
new CopyWebpackPlugin({ new CopyWebpackPlugin({
patterns: [{ from: './*.html' }, { from: './images/*.svg' }], patterns: [{ from: './images/*.*' }],
}),
new webpack.ProvidePlugin({
process: 'process/browser.js',
Buffer: ['buffer', 'Buffer'],
}),
new Serve({
historyFallback: true,
port: 55553,
host: 'localhost',
}), }),
], ],
}; });
}; }
if (MODE === 'production') {
module.exports = merge(common, {
optimization: {
minimizer: [
new ClosurePlugin(
{ mode: 'STANDARD' },
{
// compiler flags here
//
// for debugging help, try these:
//
// formatting: 'PRETTY_PRINT',
// debug: true
// renaming: false
},
),
new OptimizeCSSAssetsPlugin({}),
],
},
plugins: [
// Delete everything from output-path (/dist) and report to user
new CleanWebpackPlugin({
root: __dirname,
exclude: [],
verbose: true,
dry: false,
}),
// Copy static assets
new CopyWebpackPlugin({
patterns: [
{
from: 'src/assets',
},
],
}),
new MiniCssExtractPlugin({
// Options similar to the same options in webpackOptions.output
// both options are optional
filename: '[name]-[hash].css',
}),
],
module: {
rules: [
{
test: /\.elm$/,
exclude: [/elm-stuff/, /node_modules/],
use: {
loader: 'elm-webpack-loader',
options: {
optimize: true,
},
},
},
{
test: /\.css$/,
exclude: [/elm-stuff/, /node_modules/],
use: [MiniCssExtractPlugin.loader, 'css-loader?url=false'],
},
{
test: /\.scss$/,
exclude: [/elm-stuff/, /node_modules/],
use: [MiniCssExtractPlugin.loader, 'css-loader?url=false', 'sass-loader'],
},
],
},
});
}