Compare commits

...
Author SHA1 Message Date
telackey 5a09cdd79a Add CI webapp deployment (#57)
Publish npm package to gitea / npm_publish (18.x) (release) Successful in 2m55s
Publish ApplicationRecord to Registry / cns_publish (release) Successful in 1m29s
Reviewed-on: #57
Co-authored-by: Thomas E Lackey <telackey@bozemanpass.com>
Co-committed-by: Thomas E Lackey <telackey@bozemanpass.com>
2024-08-14 23:48:59 +00:00
zramsay fc83856e11 Merge pull request 'Update package version' (#56) from zramsay-patch-2 into main
Publish npm package to gitea / npm_publish (18.x) (release) Successful in 2m52s
Reviewed-on: #56
2024-08-09 19:10:42 +00:00
zramsay c1e368b3b0 Update package version 2024-08-09 19:09:54 +00:00
zramsay db449e9fe2 Merge pull request 'style/laconic-colors' (#55) from style/laconic-colors into main
Publish npm package to gitea / npm_publish (18.x) (release) Has been cancelled
Reviewed-on: #55
2024-08-09 17:49:56 +00:00
Monkey b1f95b488c add favicon, hard code site title 2024-08-09 10:16:13 -04:00
Monkey fc76478b8a background for sidebar, tabs and footer darker, inner container lighter 2024-08-09 00:02:37 -04:00
cfbender 4afadb9502 style: json tree view 2024-08-08 23:44:55 -04:00
Monkey bff6749a91 lighten background color, footer background color and border 2024-08-08 23:44:49 -04:00
cfbender a4c15a4d3f chore: undo json comment 2024-08-08 23:16:25 -04:00
cfbender 3ead0ee0d0 style: appbar logo 2024-08-08 23:00:38 -04:00
cfbender aa794637d1 style: font 2024-08-08 22:45:58 -04:00
Monkey 956c84c17e sidebar icon selected color matches font color 2024-08-08 22:36:39 -04:00
cfbender ccb31956a8 style: some more colors 2024-08-08 22:24:20 -04:00
cfbender 01122eb7a8 style: set primary to laconic blue 2024-08-08 22:12:38 -04:00
prathamesh 740143ce7d Update package version (#54)
Publish npm package to gitea / npm_publish (18.x) (release) Successful in 2m50s
Part of [Rename laconic2d to laconicd](https://www.notion.so/Rename-laconic2d-to-laconicd-9028d0c020d24d1288e92ebcb773d7a7)

Reviewed-on: #54
Co-authored-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
Co-committed-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
2024-07-25 07:04:11 +00:00
nabarun 4150076469 Rename laconic2d to laconicd repo in readme (#53)
Part of [Rename laconic2d to laconicd](https://www.notion.so/Rename-laconic2d-to-laconicd-9028d0c020d24d1288e92ebcb773d7a7)

Reviewed-on: #53
Co-authored-by: Nabarun <nabarun@deepstacksoft.com>
Co-committed-by: Nabarun <nabarun@deepstacksoft.com>
2024-07-23 04:54:40 +00:00
nabarun 7330d03c3c Upgrade registry-sdk package version (#51)
Part of [laconicd testnet validator enrollment](https://www.notion.so/laconicd-testnet-validator-enrollment-6fc1d3cafcc64fef8c5ed3affa27c675)

Reviewed-on: #51
Co-authored-by: Nabarun <nabarun@deepstacksoft.com>
Co-committed-by: Nabarun <nabarun@deepstacksoft.com>
2024-07-22 06:22:21 +00:00
prathameshandneeraj 06726b019d Upgrade registry-sdk version with changes for renaming laconic2d to laconicd (#50)
Part of https://www.notion.so/Rename-laconic2d-to-laconicd-9028d0c020d24d1288e92ebcb773d7a7

Co-authored-by: neeraj <neeraj.rtly@gmail.com>
Reviewed-on: #50
Co-authored-by: Prathamesh Musale <prathamesh@noreply.git.vdb.to>
Co-committed-by: Prathamesh Musale <prathamesh@noreply.git.vdb.to>
2024-04-02 13:57:45 +00:00
nabarun 61f445abe5 Update steps for running with laconic2d (#48)
Publish npm package to gitea / npm_publish (18.x) (release) Successful in 2m58s
Part of https://www.notion.so/Create-laconic-registry-SDK-d3a636d4aba44f7cbba3bd99b7146811?pvs=23

Reviewed-on: #48
Co-authored-by: Nabarun <nabarun@deepstacksoft.com>
Co-committed-by: Nabarun <nabarun@deepstacksoft.com>
2024-03-22 06:32:06 +00:00
prathameshandneeraj ef73da7ec5 Use registry-sdk and update minor version (#47)
Part of https://www.notion.so/Create-laconic-registry-SDK-d3a636d4aba44f7cbba3bd99b7146811?pvs=23

- Rename `crn` to `lrn`

Co-authored-by: neeraj <neeraj.rtly@gmail.com>
Reviewed-on: #47
Co-authored-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
Co-committed-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
2024-03-18 13:23:29 +00:00
prathamesh b9fd355a0e Upgrade SDK version (#46)
Part of cerc-io/laconicd#144

Reviewed-on: #46
Co-authored-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
Co-committed-by: Prathamesh Musale <prathamesh.musale0@gmail.com>
2024-02-08 06:17:56 +00:00
telackey 39ec9a2e31 Fix GQL QueryLink (#45)
Reviewed-on: #45
Co-authored-by: Thomas E Lackey <telackey@bozemanpass.com>
Co-committed-by: Thomas E Lackey <telackey@bozemanpass.com>
2024-01-16 23:40:42 +00:00
telackey 6f77228f73 v1.3.6 2024-01-15 15:46:05 -06:00
telackey 475f53cdcf v1.3.5 2024-01-15 15:29:37 -06:00
telackey 9dcbc6e657 Update version (#44)
Reviewed-on: #44
Co-authored-by: Thomas E Lackey <telackey@bozemanpass.com>
Co-committed-by: Thomas E Lackey <telackey@bozemanpass.com>
2024-01-15 21:12:31 +00:00
telackey 3458f454a6 Update SDK 2024-01-15 12:34:56 -06:00
dboreham 83fca9efe9 Update yarn.lock 2023-04-17 12:56:41 -06:00
dboreham b05706986b Merge pull request #39 from cerc-io/dboreham/update-react-ux
Update to latest version of @lirewine/react-ux
2023-04-11 14:07:21 -06:00
dboreham 3fe735cb9f Update to latest version of @lirewine/react-ux 2023-04-11 14:06:44 -06:00
dboreham 4d3f7d0598 Merge pull request #38 from cerc-io/dboreham/make-hostable
Add config to drive self-hosting webapp scheme in stack orchestrator
2023-04-01 13:39:32 -06:00
dboreham 59ec22ea34 Make default config file the same as before 2023-04-01 13:38:01 -06:00
dboreham e1b05a4c34 Use lowercase 2023-03-31 14:55:09 -06:00
dboreham 41d2278463 Use hosting config in build 2023-03-31 06:21:34 -06:00
dboreham 97a100d52f Add hosting template config file 2023-03-30 22:07:21 -06:00
dboreham a1bd672182 Merge pull request #36 from cerc-io/dboreham/publish-aware
Make console publishable as an npm package
2023-03-23 10:10:34 -06:00
dboreham 402599662b Make console publishable as an npm package 2023-03-23 10:09:34 -06:00
dboreham c662128f7a Fix legacy text 2023-03-22 13:32:08 -06:00
Zach 0266e7614e Merge pull request #27 from cerc-io/dboreham/remove-lerna
Remove lerna and update dependencies to modern versions
2023-03-22 08:27:59 -04:00
Zach 052bf92486 Merge pull request #35 from cerc-io/zach/readme
update readme & remove old image
2023-03-22 08:27:04 -04:00
zramsay 8d7b41abcb update readme & rm old image 2023-03-22 08:24:17 -04:00
dboreham f8c8ac1ba6 Finally working 2023-03-21 14:22:29 -06:00
dboreham 1f597fb21a Remove old package.json 2023-03-21 09:42:03 -06:00
dboreham b82e553001 Fix webpack config for non-workspace repo 2023-03-21 09:41:03 -06:00
dboreham 5df8740c55 Remove unnecessary plugin 2023-03-21 09:17:30 -06:00
dboreham 9dd46987e9 Another swipe with the scythe 2023-03-21 09:15:43 -06:00
dboreham 62ac7d66e2 Update more depedencies 2023-03-21 01:22:47 -06:00
David Boreham b8ab4368af Update package name and webpack-cli 2023-03-20 19:04:08 -06:00
David Boreham 9282e9ea26 New yarn.lock 2023-03-20 02:30:25 -06:00
David Boreham f1009e6daa First cut at de-lernaizing 2023-03-20 02:23:46 -06:00
dboreham 64768e1dc5 Merge pull request #24 from cerc-io/dboreham/update-dependencies
Fix incompatibility with latest Node.js
2023-03-20 02:12:26 -06:00
David Boreham 072bb718e3 Update webpack-cli at top level 2023-03-20 02:09:40 -06:00
David Boreham 4c8f2a1a26 Webpack v5 working 2023-03-19 20:28:14 -06:00
David Boreham ce7209453f Fix webpack migration issues 2023-03-19 20:19:28 -06:00
David Boreham 1aca4e062f Work around error to do with new Node.js or new webpack 2023-03-19 19:24:55 -06:00
David Boreham 2e4f0827d1 Update config to suit current webpack 2023-03-19 19:11:48 -06:00
David Boreham a7aaf88d88 Fix merge conflicts 2023-03-19 18:46:43 -06:00
dboreham 3b9af1f222 Merge pull request #25 from cerc-io/dboreham/cleanup-old-files
Dboreham/cleanup old files
2023-03-19 18:41:05 -06:00
David Boreham 30d9841e5e Remove git hook package 2023-03-19 18:32:41 -06:00
David Boreham 20033ef102 Remove IDEA config files 2023-03-19 18:18:18 -06:00
David Boreham 1fd9351a56 Begin to try to fix incompatibility with latest Node.js 2023-03-19 18:12:09 -06:00
Zach 8ea5a49d50 Merge pull request #23 from cerc-io/zramsay-patch-2
Bump laconic-sdk to 0.1.6
2023-03-15 21:37:18 -04:00
Zach 8322154f77 Update package.json 2023-03-10 09:19:33 -05:00
nabarun e2407c5b5b Note warning/error in dep install (#19) 2023-01-11 13:57:07 +05:30
nabarun 041e58d71e Fix gem-core dependency in yarn lock (#18) 2023-01-11 13:29:56 +05:30
nabarun 7d9047581b Use published debug and gem-core packages (#17)
* Remove dxos packages

* Use published debug and gem-core packages

* Update readme after laconicd chain ID change
2023-01-11 13:08:12 +05:30
nabarun 780cd29807 Use published packages and remove console-server (#8)
* Use published packages in lirewine

* Remove console-server package

* Use dxos packages until lirewine packages are published

* Use published cerc-io/laconic-sdk package

* Add readme to run console app with laconicd
2023-01-04 16:49:44 +05:30
Ian Norden 78be111ee4 Update README.md 2023-01-03 08:24:15 -06:00
137 changed files with 6521 additions and 16290 deletions
+36
View File
@@ -0,0 +1,36 @@
name: Publish ApplicationRecord to Registry
on:
release:
types: [published]
env:
CERC_REGISTRY_USER_KEY: ${{ secrets.CICD_VAASL_LACONIC_USER_KEY }}
CERC_REGISTRY_BOND_ID: ${{ secrets.CICD_VAASL_LACONIC_BOND_ID }}
CERC_REGISTRY_DEPLOYMENT_HOSTNAME: ${{ vars.CERC_REGISTRY_DEPLOYMENT_HOSTNAME }}
LACONIC_HOSTED_CONFIG_services_wns_server: ${{ vars.LACONIC_HOSTED_CONFIG_SERVICES_WNS_SERVER }}
LACONIC_HOSTED_CONFIG_services_wns_webui: ${{ vars.LACONIC_HOSTED_CONFIG_SERVICES_WNS_WEBUI }}
LACONIC_HOSTED_CONFIG_services_signal_api: ${{ vars.LACONIC_HOSTED_CONFIg_SERVICES_SIGNAL_API }}
LACONIC_HOSTED_CONFIG_app_api_url: ${{ vars.LACONIC_HOSTED_CONFIg_APP_API_URL }}
jobs:
cns_publish:
runs-on: ubuntu-latest
steps:
- name: "Clone project repository"
uses: actions/checkout@v3
- name: Use Node.js
uses: actions/setup-node@v3
with:
node-version: 18
- name: "Enable Yarn"
run: corepack enable
- name: "Install registry CLI"
run: |
npm config set @cerc-io:registry https://git.vdb.to/api/packages/cerc-io/npm/
npm install -g @cerc-io/laconic-registry-cli
- name: "Install jq"
run: apt -y update && apt -y install jq
- name: "Publish Application Record"
run: scripts/publish-app-record.sh
- name: "Request Deployment"
run: scripts/request-app-deployment.sh
+39
View File
@@ -0,0 +1,39 @@
name: Publish npm package to gitea
on:
release:
types: [published]
jobs:
npm_publish:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [ 18.x ]
steps:
- name: Checkout
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Download yarn
run: |
curl -fsSL -o /usr/local/bin/yarn https://github.com/yarnpkg/yarn/releases/download/v1.22.21/yarn-1.22.21.js
chmod +x /usr/local/bin/yarn
- name: Install jq
run: |
apt update && apt install -y jq
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- run: yarn
- name: Run yarn build
run: |
LACONIC_HOSTED_CONFIG_FILE=config-hosted.yml yarn dist
- name: Configure git.vdb.to npm registry
run: |
npm config set registry https://git.vdb.to/api/packages/cerc-io/npm/
- name: Authenticate to git.vdb.to registry
run: |
npm config set -- '//git.vdb.to/api/packages/cerc-io/npm/:_authToken' "${{ secrets.CICD_PUBLISH_TOKEN }}"
- name: npm publish
run: |
npm publish
-5
View File
@@ -1,5 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="PREFERRED_PROJECT_CODE_STYLE" value="Default" />
</state>
</component>
-12
View File
@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
-11
View File
@@ -1,11 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="Eslint" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="SpellCheckingInspection" enabled="false" level="TYPO" enabled_by_default="false">
<option name="processCode" value="true" />
<option name="processLiterals" value="true" />
<option name="processComments" value="true" />
</inspection_tool>
</profile>
</component>
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<includedPredefinedLibrary name="Node.js Core" />
</component>
</project>
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptSettings">
<option name="languageLevel" value="JSX" />
</component>
</project>
-8
View File
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/console.iml" filepath="$PROJECT_DIR$/.idea/console.iml" />
</modules>
</component>
</project>
-12
View File
@@ -1,12 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="client" type="js.build_tools.npm">
<package-json value="$PROJECT_DIR$/packages/console-app/package.json" />
<command value="run" />
<scripts>
<script value="start" />
</scripts>
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
</component>
-12
View File
@@ -1,12 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="server" type="js.build_tools.npm">
<package-json value="$PROJECT_DIR$/packages/console-server/package.json" />
<command value="run" />
<scripts>
<script value="start" />
</scripts>
<node-interpreter value="project" />
<envs />
<method v="2" />
</configuration>
</component>
Generated
-6
View File
@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
+82 -2
View File
@@ -1,5 +1,85 @@
# Console
Laconic Kubenet GraphQL server and console application.
Laconic console application.
![Console](./docs/images/console.png)
User interface for submitting and reading records registered on Laconic.
## Development
* Clone the required repos:
* [laconicd](https://git.vdb.to/cerc-io/laconicd)
```bash
git clone git@git.vdb.to:cerc-io/laconicd.git
```
* Run the `laconicd` chain:
* In [laconicd](https://git.vdb.to/cerc-io/laconicd) repo, start the chain
```bash
./scripts/init.sh clean
```
* Run the laconic-console app
* From the root of this repo, run:
```bash
yarn
```
*NOTE*: There is a warning containing error while installing dependencies
```bash
warning Error running install script for optional dependency: ".../laconic-console/node_modules/sodium-native: Command failed.
Exit code: 1
...
Error: ./configure exited with 127
```
This can be ignored as it is an error for installing optional dependency
* Start the app:
```bash
CONFIG_FILE=config-local.yml yarn start
```
* Open console at <http://localhost:8080>
* To view records in the console, the test suite in registry-sdk can be run
* Clone the [registry-sdk](https://git.vdb.to/cerc-io/registry-sdk) repo:
```bash
git clone git@git.vdb.to:cerc-io/registry-sdk.git
```
* In [registry-sdk](https://git.vdb.to/cerc-io/registry-sdk) repo, copy [.env.example](https://git.vdb.to/cerc-io/registry-sdk/blob/main/.env.example) file and create a `.env` file
```bash
cp .env.example .env
```
* Export the private key using:
```bash
laconicd keys export alice --keyring-backend test --unarmored-hex --unsafe
```
* Copy the private key exported above and assign it to variable `PRIVATE_KEY` in the `.env` file.
* Install dependencies
```bash
yarn
```
* Run the tests in registry-sdk repo:
```bash
yarn test
```
*NOTE*: One test from [util.test.ts](https://git.vdb.to/cerc-io/registry-sdk/blob/main/src/util.test.ts) fails as mentioned in the [PR](https://git.vdb.to/cerc-io/registry-sdk/pull/5#issuecomment-1299572012)
* Open console at <http://localhost:8080> to view the records.
@@ -12,7 +12,6 @@ module.exports = {
'import-graphql',
'inline-json-import',
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-export-default-from'
'@babel/plugin-proposal-class-properties'
]
};
+7
View File
@@ -0,0 +1,7 @@
#!/bin/sh
yarn
LACONIC_HOSTED_CONFIG_FILE=config-hosted.yml yarn build
rm -rf dist/es
mv dist/production "$1"
+42
View File
@@ -0,0 +1,42 @@
#
# NODE_ENV=development
# NOTE: Set CONFIG_FILE to swap out this config file.
#
# TODO: write a tool to automated insertion of the template strings in files like this.
app:
title: 'Console'
org': 'Laconic'
theme: 'dark'
website: 'LACONIC_HOSTED_CONFIG_app_website' # e.g. https://laconic.com
publicUrl: '/console'
api:
server: 'LACONIC_HOSTED_CONFIG_api_server' # e.g. http://127.0.0.1:9004
path: '/api'
intervalLog: 5000
pollInterval: 10000
system:
debug: 'laconic:console:*'
services:
app:
prefix: '/app'
server: 'LACONIC_HOSTED_CONFIG_services_app_server' # e.g. http://127.0.0.1:5999
wns:
server: 'LACONIC_HOSTED_CONFIG_services_wns_server' # e.g. http://127.0.0.1:9473/api
webui: 'LACONIC_HOSTED_CONFIG_services_wns_webui' # e.g. http://127.0.0.1:9473/console
signal:
server: 'LACONIC_HOSTED_CONFIG_services_signal_server' # e.g. ws://127.0.0.1:4000
api: 'LACONIC_HOSTED_CONFIG_services_signal_api' # e.g. http://127.0.0.1:4000/api
ipfs:
server: 'LACONIC_HOSTED_CONFIG_services_ipfs_server' # e.g. http://127.0.0.1:5001
gateway: 'LACONIC_HOSTED_CONFIG_services_ipfs_gateway' # e.g. http://127.0.0.1:8888/ipfs/
wellknown:
endpoint: 'LACONIC_HOSTED_CONFIG_services_wellknown_endpoint' # e.g. http://127.0.0.1:9000/.well-known/laconic
@@ -5,7 +5,7 @@
app:
title: 'Console'
org': 'Laconic'
org: 'Laconic'
theme: 'dark'
website: 'https://laconic.com'
publicUrl: '/console'
Binary file not shown.

Before

Width:  |  Height:  |  Size: 820 KiB

-5
View File
@@ -1,5 +0,0 @@
{
"version": "1.2.9",
"useWorkspaces": true,
"npmClient": "yarn"
}
+74 -52
View File
@@ -1,69 +1,91 @@
{
"name": "laconic-console",
"version": "1.2.9-alpha.0",
"name": "@cerc-io/console-app",
"version": "0.2.3",
"description": "Laconic Console",
"main": "index.js",
"private": true,
"repository": "https://github.com/cerc-io/laconic-console",
"main": "dist/es/index.js",
"files": [
"dist/*", "src/*"
],
"scripts": {
"build": "lerna run build",
"clean": "lerna run clean",
"lint": "lerna run lint",
"lint:fix": "lerna run lint -- --fix",
"lint:staged": "lint-staged",
"sort-package-json": "lerna exec npx sort-package-json",
"test": "lerna run test"
"analyzer": "webpack --config webpack-analyzer.config.js",
"build": "yarn dist",
"build:babel": "babel ./src --out-dir ./dist/es --ignore \"**/*.test.js\" --source-maps inline",
"clean": "rm -rf dist",
"updatever": "scripts/update_version.sh > src/version.json",
"dist": "yarn clean && yarn updatever && yarn build:babel && CONFIG_FILE=${LACONIC_HOSTED_CONFIG_FILE:-config-production.yml} webpack",
"lint": "semistandard 'src/**/*.js'",
"start": "CONFIG_FILE=${CONFIG_FILE:-config-testnet.yml} VERBOSE=true webpack-dev-server --mode development",
"test": "jest --rootDir ./src --passWithNoTests --no-cache"
},
"author": "",
"license": "AGPLv3",
"workspaces": {
"packages": [
"packages/*"
]
},
"license": "GPL-3.0",
"browserslist": [
"> 5%"
"> 2%"
],
"jest": {
"testEnvironment": "node"
},
"dependencies": {
"lerna": "^3.19.0"
"@apollo/client": "^3.7.10",
"@apollo/react-components": "^4.0.0",
"@apollo/react-hooks": "^4.0.0",
"@babel/runtime": "^7.21.0",
"@cerc-io/registry-sdk": "^0.2.2",
"@lirewine/debug": "1.0.0-beta.78",
"@lirewine/gem-core": "1.0.0-beta.28",
"@lirewine/react-ux": "1.1.0-beta.1",
"@material-ui/core": "^4.12.4",
"@material-ui/icons": "^4.11.3",
"@material-ui/lab": "^4.0.0-alpha.61",
"@rehooks/component-size": "^1.0.3",
"@visx/network": "^1.0.0",
"@visx/tooltip": "^1.0.0",
"@visx/zoom": "^1.0.0",
"build-url": "^2.0.0",
"clsx": "^1.1.0",
"compare-versions": "^3.6.0",
"d3-force": "^2.1.1",
"debug": "^4.1.1",
"graphql-tag": "^2.10.3",
"lodash.defaultsdeep": "^4.6.1",
"lodash.get": "^4.4.2",
"moment": "^2.26.0",
"node-polyfill-webpack-plugin": "^2.0.1",
"react": "^16.12.0",
"react-dom": "^16.12.0",
"react-router": "^5.3.4",
"react-router-dom": "^5.3.4",
"source-map-support": "^0.5.12"
},
"devDependencies": {
"babel-eslint": "^10.0.3",
"eslint": "^6.7.2",
"eslint-config-semistandard": "^15.0.0",
"eslint-config-standard": "^14.1.1",
"eslint-loader": "^3.0.3",
"eslint-plugin-babel": "^5.3.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-jest": "^23.13.1",
"eslint-plugin-jsdoc": "^21.0.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-standard": "^4.0.1",
"lint-staged": "^9.5.0",
"pre-commit": "^1.2.2",
"webpack-cli": "^3.3.11"
"@babel/cli": "7.21.0",
"@babel/core": "^7.21.0",
"@babel/preset-env": "^7.20.2",
"@babel/preset-react": "^7.18.6",
"@webpack-cli/info": "^2.0.1",
"babel-jest": "^29.5.0",
"babel-loader": "^9.1.2",
"babel-plugin-import-graphql": "^2.7.0",
"babel-plugin-inline-import": "^3.0.0",
"babel-plugin-inline-json-import": "^0.3.2",
"dotenv-webpack": "^8.0.1",
"graphql": "^15.0.0",
"html-webpack-plugin": "^5.5.0",
"jest": "^29.5.0",
"webpack": "^5.76.2",
"webpack-bundle-analyzer": "^4.8.0",
"webpack-cli": "^5.0.1",
"webpack-dev-server": "^4.13.1",
"webpack-merge": "^5.8.0",
"webpack-version-file-plugin": "^0.5.0",
"yaml-loader": "^0.8.0"
},
"eslintConfig": {
"parser": "babel-eslint",
"extends": [
"plugin:jest/recommended",
"semistandard"
],
"plugins": [
"babel"
],
"rules": {
"babel/semi": 1
}
"peerDependencies": {
"react": "16.12.0",
"react-dom": "^16.12.0"
},
"semistandard": {
"parser": "babel-eslint",
"env": [
"jest",
"node",
"browser"
]
"publishConfig": {
"access": "public"
}
}
-58
View File
@@ -1,58 +0,0 @@
# Console
Apollo GraphQL client.
## Usage
First start the server:
```bash
cd packages/console-server
yarn start
```
Then start the Webpack devserver.
```bash
cd packages/console-app
yarn start
```
Then load the app: http://localhost:8080.
## Using a KUBE
To use your KUBE for testing, rather than running all the services locally, specify a different
config file when starting: `config-kube.yml`, which connects to `kube.local` for all services.
For example:
```javascript
cd packages/console-app
CONFIG_FILE=config-kube.yml yarn start
```
## Deploy
```bash
yarn build
```
This creates the following folders:
```
/dist
/es # Module imports.
/production # Production build.
```
NOTE: GQL and Production files and exported and may be used by the server.
```javascript
import SYSTEM_STATUS from '@cerc-io/console-app/src/gql/system_status.graphql';
...
const file = path.join(__dirname + '../../../../node_modules/@cerc-io/console-app/dist/production', 'index.html');
res.sendFile(file);
```
-131
View File
@@ -1,131 +0,0 @@
{
"name": "@cerc-io/console-app",
"version": "1.2.9",
"description": "Kubenet Console Client",
"repository": "https://github.com/cerc-io/laconic-console",
"main": "dist/es/index.js",
"files": [
"src/gql"
],
"scripts": {
"analyzer": "webpack --config webpack-analyzer.config.js",
"build": "yarn dist",
"build:babel": "babel ./src --out-dir ./dist/es --ignore \"**/*.test.js\" --source-maps inline",
"clean": "rm -rf dist",
"dist": "yarn clean && yarn build:babel && CONFIG_FILE=config-production.yml webpack",
"lint": "semistandard 'src/**/*.js'",
"start": "CONFIG_FILE=${CONFIG_FILE:-config-testnet.yml} VERBOSE=true webpack-dev-server --mode development",
"test": "jest --rootDir ./src --passWithNoTests --no-cache"
},
"author": "",
"license": "GPL-3.0",
"browserslist": [
"> 2%"
],
"jest": {
"testEnvironment": "node"
},
"dependencies": {
"@apollo/react-components": "^3.1.5",
"@apollo/react-hooks": "^3.1.5",
"@babel/runtime": "^7.8.7",
"@dxos/debug": "^1.0.0-beta.78",
"@dxos/gem-core": "^1.0.0-beta.25",
"@dxos/react-ux": "https://github.com/dxos-deprecated/sdk.git#v1.1.0-beta.0",
"@material-ui/core": "^4.10.0",
"@material-ui/icons": "^4.9.1",
"@material-ui/lab": "^4.0.0-alpha.54",
"@rehooks/component-size": "^1.0.3",
"@visx/network": "^1.0.0",
"@visx/tooltip": "^1.0.0",
"@visx/zoom": "^1.0.0",
"apollo-cache-inmemory": "^1.6.6",
"apollo-client": "^2.6.10",
"apollo-link": "^1.2.14",
"apollo-link-http": "^1.5.17",
"build-url": "^2.0.0",
"clsx": "^1.1.0",
"compare-versions": "^3.6.0",
"d3-force": "^2.1.1",
"debug": "^4.1.1",
"graphql-tag": "^2.10.3",
"lodash.defaultsdeep": "^4.6.1",
"lodash.get": "^4.4.2",
"moment": "^2.26.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router": "^5.2.0",
"react-router-dom": "^5.2.0",
"source-map-support": "^0.5.12"
},
"devDependencies": {
"@babel/cli": "7.4.4",
"@babel/core": "^7.4.5",
"@babel/node": "^7.8.7",
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/plugin-proposal-export-default-from": "^7.8.3",
"@babel/preset-env": "^7.4.5",
"@babel/preset-react": "^7.0.0",
"@webpack-cli/info": "^0.2.0",
"@webpack-cli/init": "^0.3.0",
"babel-eslint": "^10.0.2",
"babel-jest": "^24.8.0",
"babel-loader": "^8.0.0",
"babel-plugin-add-module-exports": "^1.0.2",
"babel-plugin-import-graphql": "^2.7.0",
"babel-plugin-inline-import": "^3.0.0",
"babel-plugin-inline-json-import": "^0.3.2",
"dotenv-webpack": "^1.8.0",
"eslint": "^6.7.2",
"eslint-config-semistandard": "^15.0.0",
"eslint-config-standard": "^14.1.1",
"eslint-config-standard-jsx": "^8.1.0",
"eslint-loader": "^3.0.3",
"eslint-plugin-babel": "^5.3.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-jest": "^23.13.1",
"eslint-plugin-jsdoc": "^21.0.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-standard": "^4.0.1",
"html-webpack-plugin": "^4.3.0",
"jest": "^24.8.0",
"react-scripts": "^3.4.1",
"semistandard": "^14.2.0",
"webpack": "^4.41.2",
"webpack-bundle-analyzer": "^3.6.0",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.11.0",
"webpack-merge": "^4.2.2",
"webpack-version-file-plugin": "^0.4.0",
"yaml-loader": "^0.6.0"
},
"peerDependencies": {
"react": "16.12.0",
"react-dom": "^16.12.0"
},
"publishConfig": {
"access": "public"
},
"eslintConfig": {
"parser": "babel-eslint",
"extends": [
"plugin:jest/recommended",
"semistandard",
"standard-jsx"
],
"plugins": [
"babel"
],
"rules": {
"babel/semi": 1
}
},
"semistandard": {
"parser": "babel-eslint",
"env": [
"jest",
"node",
"browser"
]
}
}
-10
View File
@@ -1,10 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title><%= title %></title>
</head>
<body>
<div id="root"></div>
</body>
</html>
@@ -1,84 +0,0 @@
//
// Copyright 2020 DXOS.org
//
import React from 'react';
import { makeStyles } from '@material-ui/core';
import MuiAppBar from '@material-ui/core/AppBar';
import Link from '@material-ui/core/Link';
import Toolbar from '@material-ui/core/Toolbar';
import Typography from '@material-ui/core/Typography';
import blueGrey from '@material-ui/core/colors/blueGrey';
import GraphQLIcon from '@material-ui/icons/Adb';
// import LaconicIcon from '../icons/Laconic';
import { graphqlApi } from '../client';
const useStyles = makeStyles((theme) => ({
offset: theme.mixins.denseToolbar,
logo: {
marginRight: theme.spacing(2),
color: theme.palette.grey[800],
'& svg': {
width: 100,
height: 48
}
},
logoLink: {
lineHeight: 0
},
title: {
display: 'flex',
flex: 1,
marginTop: 2,
color: theme.palette.grey[800]
},
link: {
color: blueGrey[900]
}
}));
const AppBar = ({ config }) => {
const classes = useStyles();
return (
<>
<MuiAppBar position='fixed' elevation={0}>
<Toolbar>
<Link classes={{ root: classes.logoLink }} href='/'>
{/* <div className={classes.logo}>
<LaconicIcon />
</div> */}
<div className={classes.title}>
<Typography variant='h6'>Laconic</Typography>
</div>
</Link>
&nbsp;
<div className={classes.title}>
<Typography variant='h6'>{config.app.title}</Typography>
</div>
{/* <div>
<Link
className={classes.link}
href={graphqlApi(config)}
rel='noreferrer'
target='_blank'
title='Console GraphQL'
>
<GraphQLIcon />
</Link>
</div> */}
</Toolbar>
</MuiAppBar>
<div className={classes.offset} />
</>
);
};
export default AppBar;
@@ -1,26 +0,0 @@
//
// Copyright 2020 DXOS.org
//
import React from 'react';
import { makeStyles } from '@material-ui/core';
import { JsonTreeView } from '@dxos/react-ux';
import { omitDeep } from '../util/omit';
const useStyles = makeStyles(() => ({
root: {
flex: 1
}
}));
const Json = ({ data }) => {
const classes = useStyles();
return (
<JsonTreeView className={classes.root} data={omitDeep(data, '__typename')} />
);
};
export default Json;
@@ -1,100 +0,0 @@
//
// Copyright 2020 DXOS.org
//
import clsx from 'clsx';
import React from 'react';
import { useHistory, useParams } from 'react-router';
// import { useQuery } from '@apollo/react-hooks';
import { makeStyles } from '@material-ui/core';
import List from '@material-ui/core/List';
import ListItem from '@material-ui/core/ListItem';
import ListItemIcon from '@material-ui/core/ListItemIcon';
import LinkIcon from '@material-ui/icons/ExitToApp';
import ListItemText from '@material-ui/core/ListItemText';
// import EXTENSIONS from '../gql/extensions.graphql';
// import { useQueryStatusReducer } from '../hooks';
const useStyles = makeStyles(theme => ({
root: {
display: 'flex',
flex: 1,
flexDirection: 'column',
justifyContent: 'space-between'
},
list: {
padding: 0
},
icon: {
minWidth: 40,
color: theme.palette.grey[500]
},
selected: {
color: theme.palette.primary.main
},
expand: {
flex: 1
}
}));
const Sidebar = ({ modules: { services, settings } }) => {
const classes = useStyles();
const history = useHistory();
const { module } = useParams();
// const { data: extensionsData } = useQueryStatusReducer(useQuery(EXTENSIONS));
// const extensions = extensionsData ? JSON.parse(extensionsData.extensions.json) : [];
const extensions = [];
const isSelected = path => path === `/${module}`;
const Modules = ({ modules }) => (
<List aria-label='items' className={classes.list}>
{modules.map(({ path, title, icon: Icon }) => (
<ListItem button selected={isSelected(path)} key={path} onClick={() => history.push(path)}>
<ListItemIcon classes={{ root: classes.icon }}>
<Icon className={clsx(classes.icon, isSelected(path) && classes.selected)} />
</ListItemIcon>
<ListItemText primary={title} />
</ListItem>
))}
</List>
);
const Extensions = ({ extensions }) => (
<List aria-label='items' className={classes.list}>
{extensions.map(({ url, title }) => {
url = url
.replace('%HOST%', window.location.host)
.replace('%PORT%', window.location.port)
.replace('%PROTOCOL%', window.location.protocol);
return (
<ListItem button key={url} onClick={() => { window.location = url; return true; }}>
<ListItemIcon classes={{ root: classes.icon }}>
<LinkIcon className={clsx(classes.icon)} />
</ListItemIcon>
<ListItemText primary={title} />
</ListItem>
);
}
)}
</List>
);
return (
<div className={classes.root}>
<Modules modules={services} />
<Extensions extensions={extensions} />
<div className={classes.expand} />
<Modules modules={settings} />
</div>
);
};
export default Sidebar;
@@ -1,32 +0,0 @@
//
// Copyright 2020 DXOS.org
//
import React from 'react';
import { makeStyles } from '@material-ui/core';
import MuiToolbar from '@material-ui/core/Toolbar';
const useStyles = makeStyles(theme => ({
toolbar: {
display: 'flex',
justifyContent: 'space-between',
whiteSpace: 'nowrap',
'& > button': {
margin: theme.spacing(0.5)
}
}
}));
// TODO(burdon): Tabs.
const Toolbar = ({ children }) => {
const classes = useStyles();
return (
<MuiToolbar disableGutters className={classes.toolbar}>
{children}
</MuiToolbar>
);
};
export default Toolbar;
-37
View File
@@ -1,37 +0,0 @@
//
// Copyright 2020 DXOS.org
//
import React from 'react';
import SvgIcon from '@material-ui/core/SvgIcon';
// TODO(burdon): Fixed color?
const Icon = (props) => (
<SvgIcon {...props} viewBox='0 0 256 256'>
<g transform='matrix(1,0,0,1,-160,-124)'>
<path
d='M282.254,147.134L195.254,194.589C191.399,196.692 189,200.732 189,205.124L189,298.876C189,303.268 191.399,307.308 195.254,309.411L282.254,356.866C285.836,358.819 290.164,358.819 293.746,356.866L380.746,309.411C384.601,307.308 387,303.268 387,298.876L387,205.124C387,200.732 384.601,196.692 380.746,194.589L293.746,147.134C290.164,145.181 285.836,145.181 282.254,147.134Z'
style={{ fill: 'none', fillRule: 'nonzero', stroke: 'rgb(0,68,121)', strokeWidth: '12px' }}
/>
<path
d='M288,252L216,216'
style={{ fill: 'none', fillRule: 'nonzero', stroke: 'rgb(0,68,121)', strokeWidth: '8px', strokeLinejoin: 'round' }}
/>
<path
d='M216,288L288,252'
style={{ fill: 'none', fillRule: 'nonzero', stroke: 'rgb(0,68,121)', strokeWidth: '8px', strokeLinejoin: 'round' }}
/>
<path
d='M360,288L288,252'
style={{ fill: 'none', fillRule: 'nonzero', stroke: 'rgb(0,68,121)', strokeWidth: '8px', strokeLinejoin: 'round' }}
/>
<path
d='M360,216L288,252'
style={{ fill: 'none', fillRule: 'nonzero', stroke: 'rgb(0,68,121)', strokeWidth: '8px', strokeLinejoin: 'round' }}
/>
</g>
</SvgIcon>
);
export default Icon;
-79
View File
@@ -1,79 +0,0 @@
//
// Copyright 2019 DXOS.org
//
import { createMuiTheme } from '@material-ui/core/styles';
import teal from '@material-ui/core/colors/teal';
import orange from '@material-ui/core/colors/orange';
export const createTheme = (theme) => createMuiTheme({
// https://material-ui.com/system/shadows
shadows: ['none'],
// https://stackoverflow.com/questions/60567673/reactjs-material-ui-theme-mixins-toolbar-offset-is-not-adapting-when-toolbar
mixins: {
denseToolbar: {
height: 48
}
},
// https://material-ui.com/customization/globals/#default-props
props: {
MuiButtonBase: {
disableRipple: true
},
MuiButton: {
size: 'small'
},
MuiFilledInput: {
margin: 'dense'
},
MuiFormControl: {
margin: 'dense'
},
MuiFormHelperText: {
margin: 'dense'
},
MuiIconButton: {
size: 'small'
},
MuiInputBase: {
margin: 'dense'
},
MuiInputLabel: {
margin: 'dense'
},
MuiTable: {
size: 'small'
},
MuiTextField: {
margin: 'dense'
},
MuiToolbar: {
variant: 'dense'
}
},
// https://material-ui.com/customization/palette/
palette: theme === 'dark' ? {
type: 'dark',
primary: orange
} : {
primary: teal
},
// https://material-ui.com/customization/theming/#theme-configuration-variables
// https://material-ui.com/customization/globals/
overrides: {
MuiCssBaseline: {
'@global': {
body: {
margin: 0,
overflow: 'hidden'
}
}
}
}
});
-7
View File
@@ -1,7 +0,0 @@
{
"build": {
"name": "@cerc-io/console-app",
"buildDate": "2020-12-19T03:06:08.492Z",
"version": "1.2.9-alpha.1"
}
}
-7
View File
@@ -1,7 +0,0 @@
{
"build": {
"name": "<%= package.name %>",
"buildDate": "<%= currentTime.toISOString() %>",
"version": "<%= package.version %>"
}
}
-44
View File
@@ -1,44 +0,0 @@
# Console
Apollo GraphQL client.
## Usage
Use the following command to run the server at: http://localhost:9004
```bash
yarn start
```
To test the Console app, the `@cerc-io/console-app` must be built first:
```bash
cd ../console-app
yarn build
```
Use the following command to run the client in development mode (via the `webpack-dev-server`) at http://localhost:8080
```bash
yarn dev
```
To build the client and serve it directly from the server:
```bash
yarn build
yarn start
```
Then open the app at: http://localhost:9004/console
## Production
When running the Console server, either set the `CONFIG_FILE` environment variable or set the `--config` option.
```bash
./bin/console.js --config ./config.yml
```
NOTE: The server passes its configuration directly to the Console app when it is loaded.
-27
View File
@@ -1,27 +0,0 @@
//
// Copyright 2020 DXOS.org
//
module.exports = {
presets: [
'@babel/preset-env',
'@babel/preset-react'
],
plugins: [
[
'babel-plugin-inline-import', {
extensions: [
'.mustache',
'.graphql'
]
}
],
// Allows export of components importing GQL files (without webpack).
'import-graphql',
'inline-json-import',
'@babel/plugin-proposal-class-properties',
'@babel/plugin-proposal-export-default-from'
]
};
-3
View File
@@ -1,3 +0,0 @@
#!/usr/bin/env node
module.exports = require('../dist/es/server/main.js');
-40
View File
@@ -1,40 +0,0 @@
#
# NODE_ENV=development
# NOTE: Set CONFIG_FILE to swap out this config file.
#
app:
title: 'Console'
org': 'Laconic'
theme: 'dark'
website: 'https://laconic.com'
publicUrl: '/console'
api:
path: '/api'
port: 9004
intervalLog: 5000
pollInterval: 10000
system:
debug: 'laconic:console:*'
services:
app:
prefix: '/app'
server: 'https://kube.local'
wns:
server: 'https://kube.local/laconic/wns/api'
webui: 'https://kube.local/laconic/wns/console'
signal:
server: 'wss://kube.local/laconic/signal/api'
api: 'https://kube.local/laconic/signal'
ipfs:
server: 'https://kube.local/laconic/ipfs/api'
gateway: 'https://kube.local/laconic/ipfs/gateway'
wellknown:
endpoint: 'https://kube.local/.well-known/laconic'
@@ -1,40 +0,0 @@
#
# NODE_ENV=development
# NOTE: Set CONFIG_FILE to swap out this config file.
#
app:
title: 'Console'
org': 'Laconic'
theme: 'dark'
website: 'https://laconic.com'
publicUrl: '/console'
api:
path: '/api'
port: 9004
intervalLog: 5000
pollInterval: 10000
system:
debug: 'laconic:console:*'
services:
app:
prefix: '/app'
server: 'https://apollo1.kube.moon.laconic.network'
wns:
server: 'https://apollo1.kube.moon.laconic.network/laconic/wns/api'
webui: 'https://apollo1.kube.moon.laconic.network/laconic/wns/console'
signal:
server: 'wss://apollo1.kube.moon.laconic.network/laconic/signal'
api: 'https://apollo1.kube.moon.laconic.network/laconic/signal/api'
ipfs:
server: 'https://apollo1.kube.moon.laconic.network/laconic/ipfs/api'
gateway: 'https://apollo1.kube.moon.laconic.network/laconic/ipfs/gateway'
wellknown:
endpoint: 'https://apollo1.kube.moon.laconic.network/.well-known/laconic'
-40
View File
@@ -1,40 +0,0 @@
#
# NODE_ENV=production
# NOTE: Set CONFIG_FILE to swap out this config file.
#
app:
title: 'Console'
org': 'Laconic'
theme: 'dark'
website: 'https://laconic.com'
publicUrl: '/console'
api:
path: '/api'
port: 9004
intervalLog: 5000
pollInterval: 10000
system:
debug: 'laconic:console:*'
services:
app:
prefix: '/app'
server: 'http://127.0.0.1:5999'
wns:
server: 'http://127.0.0.1:9473/api'
webui: 'http://127.0.0.1:9473/console'
signal:
server: 'ws://127.0.0.1:4000'
api: 'http://127.0.0.1:4000/api'
ipfs:
server: 'http://127.0.0.1:5001'
gateway: 'http://127.0.0.1:8888/ipfs/'
wellknown:
endpoint: 'http://127.0.0.1:9000/.well-known/laconic'
-114
View File
@@ -1,114 +0,0 @@
{
"name": "@cerc-io/console-server",
"version": "1.2.9",
"description": "Kubenet Console Server",
"main": "dist/es/index.js",
"bin": {
"laconic-console": "bin/console.js"
},
"files": [
"bin/",
"dist/es"
],
"scripts": {
"build": "npm run clean && npm run build:client && npm run build:server",
"build:client": "PUBLIC_URL=/console webpack --mode development",
"build:server": "babel ./src --out-dir ./dist/es --ignore \"**/*.test.js\" --copy-files",
"clean": "rm -rf ./dist",
"dev": "VERBOSE=true webpack-dev-server --mode development --watch",
"lint": "semistandard 'src/**/*.js'",
"test": "jest --rootDir ./src --passWithNoTests --no-cache",
"start": "CONFIG_FILE=${CONFIG_FILE=./config.yml} BABEL_DISABLE_CACHE=1 nodemon --exec babel-node src/server/main.js -- --verbose"
},
"author": "",
"license": "GPL-3.0",
"browserslist": [
"> 5%"
],
"jest": {
"testEnvironment": "node"
},
"dependencies": {
"@babel/polyfill": "^7.8.7",
"@babel/runtime": "^7.8.7",
"@cerc-io/console-app": "^1.2.9",
"apollo-boost": "^0.4.9",
"apollo-server-express": "^2.13.1",
"body-parser": "^1.19.0",
"compression": "^1.7.4",
"debug": "^4.1.1",
"express": "^4.17.1",
"express-graphql": "^0.9.0",
"graphql": "^15.0.0",
"graphql-tag": "^2.10.3",
"graphql-tools": "^6.0.3",
"ipfs-http-client": "^44.1.0",
"js-yaml": "^3.14.0",
"lodash.defaultsdeep": "^4.6.1",
"lodash.pick": "^4.4.0",
"mustache-express": "^1.3.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"source-map-support": "^0.5.12",
"systeminformation": "^4.26.5",
"tree-kill": "^1.2.2",
"yargs": "^15.3.1"
},
"devDependencies": {
"@babel/cli": "7.4.4",
"@babel/core": "^7.4.5",
"@babel/node": "^7.8.7",
"@babel/plugin-proposal-class-properties": "^7.5.5",
"@babel/plugin-proposal-export-default-from": "^7.5.2",
"@babel/preset-env": "^7.4.5",
"babel-eslint": "^10.0.3",
"babel-jest": "^24.8.0",
"babel-loader": "^8.1.0",
"babel-plugin-add-module-exports": "^1.0.2",
"babel-plugin-import-graphql": "^2.7.0",
"babel-plugin-inline-import": "^3.0.0",
"babel-plugin-inline-json-import": "^0.3.2",
"dotenv-webpack": "^1.8.0",
"eslint": "^6.7.2",
"eslint-config-semistandard": "^15.0.0",
"eslint-config-standard": "^14.1.1",
"eslint-loader": "^3.0.3",
"eslint-plugin-babel": "^5.3.0",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-jest": "^23.13.1",
"eslint-plugin-jsdoc": "^21.0.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-standard": "^4.0.1",
"jest": "^24.8.0",
"nodemon": "^2.0.4",
"semistandard": "^14.2.0",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.11.0",
"webpack-merge": "^4.2.2"
},
"publishConfig": {
"access": "public"
},
"eslintConfig": {
"parser": "babel-eslint",
"extends": [
"plugin:jest/recommended",
"semistandard"
],
"plugins": [
"babel"
],
"rules": {
"babel/semi": 1
}
},
"semistandard": {
"parser": "babel-eslint",
"env": [
"jest",
"node",
"browser"
]
}
}
-10
View File
@@ -1,10 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title><%= title %></title>
</head>
<body>
<div id="root"></div>
</body>
</html>
@@ -1,16 +0,0 @@
//
// Copyright 2020 DXOS.org
//
import debug from 'debug';
import React from 'react';
import { render } from 'react-dom';
import { Main } from '@cerc-io/console-app';
// Load from global printed into HTML page via template.
const { config } = window.__Laconic__;
debug.enable(config.system.debug);
render(<Main config={config} />, document.getElementById('root'));
@@ -1,35 +0,0 @@
#
# Copyright 2020 DXOS.org
#
# TODO(burdon): Replace generic results with schema.
type JSONResult {
timestamp: String!
json: String!
}
#
# Schema
#
type Query {
logs(service: String!, incremental: Boolean): JSONResult!
app_status: JSONResult!
ipfs_status: JSONResult!
ipfs_swarm_status: JSONResult!
service_status: JSONResult!
signal_status: JSONResult!
system_status: JSONResult!
wns_status: JSONResult!
bot_list: JSONResult!
extensions: JSONResult!
}
type Mutation {
bot_kill(botId: String!): JSONResult!
}
schema {
query: Query
mutation: Mutation
}
@@ -1,105 +0,0 @@
//
// Copyright 2020 DXOS.org
//
import { spawn } from 'child_process';
import debug from 'debug';
import fs from 'fs';
import yaml from 'js-yaml';
import path from 'path';
import os from 'os';
import kill from 'tree-kill';
const DEFAULT_BOT_FACTORY_CWD = '.wire/bots';
const SERVICE_CONFIG_FILENAME = 'service.yml';
const log = debug('laconic:console:server:resolvers');
let topic;
const getBotFactoryTopic = (botFactoryCwd) => {
if (!topic) {
// TODO(egorgripasov): Get topic from config or registry.
const serviceFilePath = path.join(os.homedir(), botFactoryCwd || DEFAULT_BOT_FACTORY_CWD, SERVICE_CONFIG_FILENAME);
if (fs.existsSync(serviceFilePath)) {
const botFactoryInfo = yaml.safeLoad(fs.readFileSync(serviceFilePath));
topic = botFactoryInfo.topic;
}
}
return topic;
};
const executeCommand = async (command, args, timeout = 10000) => {
return new Promise((resolve) => {
const child = spawn(command, args, { encoding: 'utf8' });
const stdout = [];
const stderr = [];
const timer = setTimeout(() => {
try {
kill(child.pid, 'SIGKILL');
} catch (err) {
log(`Can not kill ${command} process: ${err}`);
}
stderr.push('Timeout.');
}, timeout);
child.stdout.on('data', (data) => stdout.push(data));
child.stderr.on('data', (data) => stderr.push(data));
child.on('exit', (code) => {
clearTimeout(timer);
resolve({
code: code === null ? 1 : code,
stdout: stdout.join('').trim(),
stderr: stderr.join('').trim()
});
});
});
};
const getRunningBots = async () => {
const command = 'wire';
const args = ['bot', 'factory', 'status', '--topic', getBotFactoryTopic()];
const { code, stdout, stderr } = await executeCommand(command, args);
return {
success: !code,
bots: code ? [] : JSON.parse(stdout).bots || [],
error: (stderr || code) ? stderr || stdout : undefined
};
};
const sendBotCommand = async (botId, botCommand) => {
const command = 'wire';
const args = ['bot', botCommand, '--topic', getBotFactoryTopic(), '--bot-id', botId];
const { code, stdout, stderr } = await executeCommand(command, args);
return {
success: !code,
botId: code ? undefined : botId,
error: (stderr || code) ? stderr || stdout : undefined
};
};
export const botsResolvers = {
Query: {
bot_list: async () => {
const result = await getRunningBots();
return {
timestamp: new Date().toUTCString(),
json: JSON.stringify(result)
};
}
},
Mutation: {
bot_kill: async (_, { botId }) => {
const result = await sendBotCommand(botId, 'kill');
return {
timestamp: new Date().toUTCString(),
json: JSON.stringify(result)
};
}
}
};
@@ -1,59 +0,0 @@
//
// Copyright 2020 DXOS.org
//
import childProcess from 'child_process';
// TODO(telackey): Make pluggable.
const ifBigDipper = () => {
try {
const result = childProcess.execSync('docker ps -f "ancestor=big-dipper_app" -q');
if (result && result.toString()) {
return {
title: 'Block Explorer',
url: 'http://%HOST%:3080/'
};
} else {
return {
title: 'Block Explorer',
url: 'http://blockexplorer.moon.laconic.network:3080/'
};
}
} catch (e) {}
};
const ifRadicle = () => {
try {
const result = childProcess.execSync('docker ps -f "ancestor=laconic/radicle-seed-node" -q');
if (result && result.toString()) {
return {
title: 'Radicle',
url: '/radicle/'
};
}
} catch (e) {}
};
// TODO(telackey): Use the local Sentry.
const ifSentry = () => {
return {
title: 'Sentry',
url: 'http://sentry.kube.laconic.network:9000/'
};
};
export const extensionResolvers = {
Query: {
extensions: async (_, __, { config }) => {
return {
timestamp: new Date().toUTCString(),
json: JSON.stringify([
ifBigDipper(),
ifRadicle(),
ifSentry()
].filter(x => x))
};
}
}
};
@@ -1,26 +0,0 @@
//
// Copyright 2020 DXOS.org
//
import debug from 'debug';
import defaultsDeep from 'lodash.defaultsdeep';
import { extensionResolvers } from './extensions';
import { ipfsResolvers } from './ipfs';
import { systemResolvers } from './system';
import { logResolvers } from './log';
import { botsResolvers } from './bots';
// eslint-disable-next-line
const log = debug('laconic:console:server:resolvers');
/**
* Resolvers
* https://www.apollographql.com/docs/graphql-tools/resolvers
*/
export const resolvers = defaultsDeep({
// TODO(burdon): Auth.
// https://www.apollographql.com/docs/apollo-server/data/errors/#codes
}, ipfsResolvers, systemResolvers, logResolvers, botsResolvers, extensionResolvers);
@@ -1,58 +0,0 @@
//
// Copyright 2020 DXOS.org
//
import debug from 'debug';
import IpfsHttpClient from 'ipfs-http-client';
const log = debug('laconic:console:server:resolvers');
export const ipfsResolvers = {
Query: {
//
// IPFS
// TODO(burdon): Call from client?
// https://github.com/ipfs/js-ipfs
// https://github.com/ipfs/js-ipfs/tree/master/packages/ipfs-http-client#api
//
ipfs_status: async (_, __, { config }) => {
log('Calling IPFS...');
// NOTE: Hangs if server not running.
const ipfs = new IpfsHttpClient(config.services.ipfs.server);
const id = await ipfs.id();
const version = await ipfs.version();
const peers = await ipfs.swarm.peers();
const stats = await ipfs.stats.repo();
// Do not expose the repo path.
delete stats.repoPath;
const refs = [];
for await (const ref of ipfs.refs.local()) {
if (ref.err) {
log(ref.err);
} else {
refs.push(ref.ref);
}
}
return {
timestamp: new Date().toUTCString(),
json: JSON.stringify({
id,
version,
repo: {
stats
},
refs: {
local: refs
},
swarm: {
peers
}
})
};
}
}
};
@@ -1,64 +0,0 @@
//
// Copyright 2020 DXOS.org
//
import { spawnSync } from 'child_process';
class LogCache {
constructor (maxLines = 500) {
// Sets in JS iterate in insertion order.
this.buffer = new Set();
this.maxLines = maxLines;
}
append (lines) {
const added = [];
for (const line of lines) {
if (!this.buffer.has(line)) {
this.buffer.add(line);
added.push(line);
}
}
if (this.buffer.size > this.maxLines) {
this.buffer = new Set(Array.from(this.buffer).slice(parseInt(this.maxLines / 2)));
}
return added;
}
}
const _caches = new Map();
const getLogCache = (name) => {
let cache = _caches.get(name);
if (!cache) {
cache = new LogCache();
_caches.set(name, cache);
}
return cache;
};
const getLogs = async (name, incremental = false, lines = 100) => {
const command = 'wire';
const args = ['service', 'logs', '--lines', lines, name];
const child = spawnSync(command, args, { encoding: 'utf8' });
const logLines = child.stdout.split(/\n/);
const cache = getLogCache(name);
const added = cache.append(logLines);
return incremental ? added : Array.from(cache.buffer);
};
export const logResolvers = {
Query: {
logs: async (_, { service, incremental }) => {
const lines = await getLogs(service, incremental);
return {
timestamp: new Date().toUTCString(),
json: JSON.stringify({ incremental, lines })
};
}
}
};
@@ -1,139 +0,0 @@
//
// Copyright 2020 DXOS.org
//
import fs from 'fs';
import moment from 'moment';
import pick from 'lodash.pick';
import os from 'os';
import si from 'systeminformation';
import { spawnSync } from 'child_process';
const num = new Intl.NumberFormat('en', { maximumSignificantDigits: 3 });
const size = (n, unit) => {
const units = {
K: 3,
M: 6,
G: 9,
T: 12
};
const power = units[unit] || 0;
return num.format(Math.round(n / (10 ** power))) + (unit ? ` ${unit}` : '');
};
const getVersionInfo = () => {
// TODO(telackey): Get from config (or figure out a better way to do this).
const versionFile = '/opt/kube/VERSION';
if (fs.existsSync(versionFile)) {
return fs.readFileSync(versionFile, { encoding: 'UTF8' }).replace(/^\s+|\s+$/g, '');
}
return undefined;
};
const getCliVersionInfo = () => {
const command = 'wire';
const args = ['version'];
const child = spawnSync(command, args, { encoding: 'utf8' });
return child.stdout;
};
/**
* Get system inforamtion.
* https://www.npmjs.com/package/systeminformation
*/
const getSystemInfo = async () => {
const ifaces = os.networkInterfaces();
const addresses = Object.entries(ifaces).reduce((result, [, values]) => {
values.forEach(({ family, address }) => {
address = address.toLowerCase();
// TODO(telackey): Include link-local IPv6?
if (!address.startsWith('127.') && !address.startsWith('fe80::') && !address.startsWith('::1')) {
result.push(address);
}
});
return result;
}, []);
const cpu = await si.cpu();
const memory = await si.mem();
const device = await si.system();
return {
cpu: pick(cpu, 'brand', 'cores', 'manufacturer', 'vendor', 'speed'),
memory: {
total: size(memory.total, 'M'),
free: size(memory.free, 'M'),
used: size(memory.used, 'M'),
swaptotal: size(memory.swaptotal, 'M')
},
device: pick(device, 'model', 'serial', 'version'),
network: {
addresses
},
// https://nodejs.org/api/os.html
os: {
arch: os.arch(),
platform: os.platform(),
version: os.version ? os.version() : undefined // Node > 13
},
time: {
now: moment(),
up: moment().subtract(os.uptime(), 'seconds')
},
nodejs: {
version: process.version
},
laconic: {
kube: {
version: getVersionInfo()
},
wire: {
version: getCliVersionInfo()
}
}
};
};
/**
* Get system inforamtion.
* https://www.npmjs.com/package/systeminformation
*/
const getServiceInfo = async () => {
const command = 'wire';
const args = ['service', '--json'];
const child = spawnSync(command, args, { encoding: 'utf8' });
return JSON.parse(child.stdout);
};
export const systemResolvers = {
Query: {
system_status: async () => {
const system = await getSystemInfo();
return {
timestamp: new Date().toUTCString(),
json: JSON.stringify(system)
};
},
service_status: async () => {
const serviceInfo = await getServiceInfo();
return {
timestamp: new Date().toUTCString(),
json: JSON.stringify(serviceInfo)
};
}
}
};
-155
View File
@@ -1,155 +0,0 @@
//
// Copyright 2020 DXOS.org
//
import compression from 'compression';
import bodyParser from 'body-parser';
import cors from 'cors';
import debug from 'debug';
import express from 'express';
import mustache from 'mustache-express';
import fs from 'fs';
import yaml from 'js-yaml';
import { ApolloServer, gql } from 'apollo-server-express';
import { print } from 'graphql/language';
import yargs from 'yargs';
// TODO(burdon): Use once published by @ashwinp.
// import { extensions as WNS_EXTENSIONS, schema as WNS_SCHEMA } from '@wirelineio/wns-schema';
import SYSTEM_STATUS from '@cerc-io/console-app/src/gql/system_status.graphql';
import { resolvers } from '../resolvers';
import API_SCHEMA from '../gql/api.graphql';
const argv = yargs
.option('config', {
alias: 'c',
description: 'Config file',
type: 'string'
})
.option('verbose', {
alias: 'v',
description: 'Verbse info',
type: 'boolean'
})
.help()
.alias('help', 'h')
.argv;
const configFile = argv.config || process.env.CONFIG_FILE;
if (!configFile) {
yargs.showHelp();
process.exit(1);
}
const config = yaml.safeLoad(fs.readFileSync(configFile));
const log = debug('laconic:console:server');
debug.enable(config.system.debug);
if (argv.verbose) {
log(JSON.stringify(config, undefined, 2));
}
//
// Express server.
//
const { app: { publicUrl } } = config;
const app = express();
app.set('views', `${__dirname}/views`);
app.set('view engine', 'mustache');
app.engine('mustache', mustache());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(compression());
app.get('/', (req, res) => {
res.redirect(publicUrl);
});
//
// CORS
//
// import cors from 'cors'
// https://expressjs.com/en/resources/middleware/cors.html
// https://www.prisma.io/blog/enabling-cors-for-express-graphql-apollo-server-1ef999bfb38d
app.use(cors({
origin: true,
credentials: true
}));
//
// React app
// TODO(burdon): Can we load this via WNS?
//
const bundles = [
'runtime', 'vendor', 'material-ui', 'cerc-io', 'main'
];
app.use(`${publicUrl}/lib`, express.static('./dist/client'));
app.get(publicUrl, (req, res) => {
res.render('console', {
title: 'Console',
container: 'root',
config: JSON.stringify(config),
scripts: bundles.map(bundle => ({ src: `${publicUrl}/lib/${bundle}.bundle.js` }))
});
});
//
// Apollo Server and middleware
// https://www.apollographql.com/docs/apollo-server/api/apollo-server
// https://www.apollographql.com/docs/apollo-server/api/apollo-server/#apolloserverapplymiddleware
//
const server = new ApolloServer({
typeDefs: [
API_SCHEMA
],
// https://www.apollographql.com/docs/graphql-tools/resolvers
resolvers,
// https://www.apollographql.com/docs/apollo-server/data/resolvers/#the-context-argument
context: ({ req }) => ({
config,
// TODO(burdon): Auth.
authToken: req.headers.authorization
}),
// https://www.apollographql.com/docs/apollo-server/testing/graphql-playground
// https://github.com/prisma-labs/graphql-playground#usage
// introspection: true,
playground: {
settings: {
'editor.theme': config.app.theme
},
tabs: [
{
name: 'Status',
endpoint: config.api.path,
query: print(gql(SYSTEM_STATUS))
}
]
}
});
server.applyMiddleware({ app, path: config.api.path });
//
// Start server
//
const { api: { port } } = config;
app.listen({ port }, () => {
log(`Running: http://localhost:${port}`);
});
@@ -1,20 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>{{ title }}</title>
</head>
<body>
<div id="{{ container }}"></div>
<!-- Config loaded by client. -->
<script charset="utf-8" type="application/javascript">
window.__Lacnonic__ = { config: {{{ config }}} };
</script>
<!-- React bundles. -->
{{#scripts}}
<script charset="utf-8" type="application/javascript" src="{{src}}"></script>
{{/scripts}}
</body>
</html>
-110
View File
@@ -1,110 +0,0 @@
//
// Copyright 2019 DXOS.org
//
const path = require('path');
const Dotenv = require('dotenv-webpack');
const webpack = require('webpack');
const HtmlWebPackPlugin = require('html-webpack-plugin');
const PUBLIC_URL = process.env.PUBLIC_URL || '';
module.exports = {
devtool: 'eval-source-map',
devServer: {
contentBase: path.join(__dirname, 'dist'),
compress: true,
disableHostCheck: true,
port: 8080,
watchOptions: {
ignored: /node_modules/,
aggregateTimeout: 600
}
},
node: {
fs: 'empty'
},
entry: './src/client/main.js',
output: {
path: `${__dirname}/dist/client`,
filename: '[name].bundle.js',
publicPath: PUBLIC_URL
},
optimization: {
runtimeChunk: 'single',
splitChunks: {
chunks: 'all',
maxInitialRequests: Infinity,
minSize: 0,
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name (module) {
const packageName = module.context.match(/[\\/]node_modules[\\/](.*?)([\\/]|$)/)[1];
if (packageName.startsWith('@cerc-io')) {
return 'cerc-io';
}
if (packageName.startsWith('@material-ui')) {
return 'material-ui';
}
return 'vendor';
}
}
}
}
},
plugins: [
// https://github.com/jantimon/html-webpack-plugin#options
new HtmlWebPackPlugin({
template: './public/index.html',
templateParameters: {
title: 'Console'
}
}),
// https://www.npmjs.com/package/dotenv-webpack#properties
new Dotenv({
path: process.env.DOT_ENV || '.env'
}),
// NOTE: Must be defined below Dotenv (otherwise will override).
// https://webpack.js.org/plugins/environment-plugin
new webpack.EnvironmentPlugin({})
],
module: {
rules: [
{
test: /\.js$/,
exclude: /(node_modules)/,
use: {
loader: 'babel-loader'
}
},
// https://github.com/eemeli/yaml-loader
{
test: /\.ya?ml$/,
type: 'json',
use: 'yaml-loader'
}
]
},
resolve: {
alias: {
'@material-ui/styles': path.resolve(__dirname, '..', '..', 'node_modules/@material-ui/styles'),
'react': path.resolve(__dirname, '..', '..', 'node_modules/react'),
'react-dom': path.resolve(__dirname, '..', '..', 'node_modules/react-dom')
}
}
};
Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

+18
View File
@@ -0,0 +1,18 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Laconic | Console</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=DM+Mono:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&display=swap"
rel="stylesheet" />
</head>
<body>
<div id="root"></div>
</body>
</html>
-32
View File
@@ -1,32 +0,0 @@
#!/bin/bash
set -euo pipefail
for appdir in `find ./packages -name '*-app' -type d | grep -v node_modules`; do
pushd $appdir
WNS_ORG="${WNS_ORG:-dxos}"
PKG_CHANNEL="${PKG_CHANNEL:-}"
PKG_NAME=`cat package.json | jq -r '.name' | cut -d'/' -f2- | sed 's/-app$//'`
WNS_NAME="$WNS_ORG/$PKG_NAME"
cat <<EOF > app.yml
name: $PKG_NAME
build: yarn dist
EOF
cat app.yml
echo "wrn://${WNS_ORG}/application/${PKG_NAME}${PKG_CHANNEL}"
yarn clean
yarn -s wire app build
if [ -d "dist/production" ]; then
yarn -s wire app publish --path './dist/production'
else
yarn -s wire app publish
fi
yarn -s wire app register --name "wrn://${WNS_ORG}/application/${PKG_NAME}${PKG_CHANNEL}"
popd
done
+69
View File
@@ -0,0 +1,69 @@
#!/bin/bash
set -e
RECORD_FILE=tmp.rf.$$
CONFIG_FILE=`mktemp`
CERC_APP_TYPE=${CERC_APP_TYPE:-"webapp"}
CERC_REPO_REF=${CERC_REPO_REF:-${GITHUB_SHA:-`git log -1 --format="%H"`}}
CERC_IS_LATEST_RELEASE=${CERC_IS_LATEST_RELEASE:-"true"}
rcd_name=$(jq -r '.name' package.json | sed 's/null//')
rcd_desc=$(jq -r '.description' package.json | sed 's/null//')
rcd_repository=$(jq -r '.repository' package.json | sed 's/null//')
rcd_homepage=$(jq -r '.homepage' package.json | sed 's/null//')
rcd_license=$(jq -r '.license' package.json | sed 's/null//')
rcd_author=$(jq -r '.author' package.json | sed 's/null//')
rcd_app_version=$(jq -r '.version' package.json | sed 's/null//')
cat <<EOF > "$CONFIG_FILE"
services:
registry:
rpcEndpoint: '${CERC_REGISTRY_RPC_ENDPOINT:-http://testnet-a-1.dev.vaasl.io:26657}'
gqlEndpoint: '${CERC_REGISTRY_GQL_ENDPOINT:-http://testnet-a-1.dev.vaasl.io:9473/api}'
chainId: ${CERC_REGISTRY_CHAIN_ID:-laconic-08062024}
gas: 900000
fees: 900000alnt
EOF
next_ver=$(laconic -c $CONFIG_FILE registry record list --type ApplicationRecord --all --name "$rcd_name" 2>/dev/null | jq -r -s ".[] | sort_by(.createTime) | reverse | [ .[] | select(.bondId == \"$CERC_REGISTRY_BOND_ID\") ] | .[0].attributes.version" | awk -F. -v OFS=. '{$NF += 1 ; print}')
if [ -z "$next_ver" ] || [ "1" == "$next_ver" ]; then
next_ver=0.0.1
fi
cat <<EOF | sed '/.*: ""$/d' > "$RECORD_FILE"
record:
type: ApplicationRecord
version: ${next_ver}
name: "$rcd_name"
description: "$rcd_desc"
homepage: "$rcd_homepage"
license: "$rcd_license"
author: "$rcd_author"
repository:
- "$rcd_repository"
repository_ref: "$CERC_REPO_REF"
app_version: "$rcd_app_version"
app_type: "$CERC_APP_TYPE"
EOF
cat $RECORD_FILE
RECORD_ID=$(laconic -c $CONFIG_FILE registry record publish --filename $RECORD_FILE --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} | jq -r '.id')
echo $RECORD_ID
if [ -z "$CERC_REGISTRY_APP_LRN" ]; then
authority=$(echo "$rcd_name" | cut -d'/' -f1 | sed 's/@//')
app=$(echo "$rcd_name" | cut -d'/' -f2-)
CERC_REGISTRY_APP_LRN="lrn://$authority/applications/$app"
fi
laconic -c $CONFIG_FILE registry name set --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} "$CERC_REGISTRY_APP_LRN@${rcd_app_version}" "$RECORD_ID"
laconic -c $CONFIG_FILE registry name set --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} "$CERC_REGISTRY_APP_LRN@${CERC_REPO_REF}" "$RECORD_ID"
if [ "true" == "$CERC_IS_LATEST_RELEASE" ]; then
laconic -c $CONFIG_FILE registry name set --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} "$CERC_REGISTRY_APP_LRN" "$RECORD_ID"
fi
rm -f $RECORD_FILE $CONFIG_FILE
+58
View File
@@ -0,0 +1,58 @@
#!/bin/bash
set -e
RECORD_FILE=tmp.rf.$$
CONFIG_FILE=`mktemp`
rcd_name=$(jq -r '.name' package.json | sed 's/null//' | sed 's/^@//')
rcd_app_version=$(jq -r '.version' package.json | sed 's/null//')
cat <<EOF > "$CONFIG_FILE"
services:
registry:
rpcEndpoint: '${CERC_REGISTRY_RPC_ENDPOINT:-http://testnet-a-1.dev.vaasl.io:26657}'
gqlEndpoint: '${CERC_REGISTRY_GQL_ENDPOINT:-http://testnet-a-1.dev.vaasl.io:9473/api}'
chainId: ${CERC_REGISTRY_CHAIN_ID:-laconic-08062024}
gas: 900000
fees: 900000alnt
EOF
if [ -z "$CERC_REGISTRY_APP_LRN" ]; then
authority=$(echo "$rcd_name" | cut -d'/' -f1 | sed 's/@//')
app=$(echo "$rcd_name" | cut -d'/' -f2-)
CERC_REGISTRY_APP_LRN="lrn://$authority/applications/$app"
fi
APP_RECORD=$(laconic -c $CONFIG_FILE registry name resolve "$CERC_REGISTRY_APP_LRN" | jq '.[0]')
if [ -z "$APP_RECORD" ] || [ "null" == "$APP_RECORD" ]; then
echo "No record found for $CERC_REGISTRY_APP_LRN."
exit 1
fi
cat <<EOF | sed '/.*: ""$/d' > "$RECORD_FILE"
record:
type: ApplicationDeploymentRequest
version: 1.0.0
name: "$rcd_name@$rcd_app_version"
application: "$CERC_REGISTRY_APP_LRN@$rcd_app_version"
dns: "$CERC_REGISTRY_DEPLOYMENT_HOSTNAME"
deployment: "$CERC_REGISTRY_DEPLOYMENT_LRN"
config:
env:
CERC_WEBAPP_DEBUG: "$rcd_app_version"
LACONIC_HOSTED_CONFIG_services_wns_server: "$LACONIC_HOSTED_CONFIG_services_wns_server"
LACONIC_HOSTED_CONFIG_services_wns_webui: "$LACONIC_HOSTED_CONFIG_services_wns_webui"
LACONIC_HOSTED_CONFIG_services_signal_api: "$LACONIC_HOSTED_CONFIG_services_signal_api"
LACONIC_HOSTED_CONFIG_app_api_url: "$LACONIC_HOSTED_CONFIG_app_api_url"
meta:
note: "Added by CI @ `date`"
repository: "`git remote get-url origin`"
repository_ref: "${GITHUB_SHA:-`git log -1 --format="%H"`}"
EOF
cat $RECORD_FILE
RECORD_ID=$(laconic -c $CONFIG_FILE registry record publish --filename $RECORD_FILE --user-key "${CERC_REGISTRY_USER_KEY}" --bond-id ${CERC_REGISTRY_BOND_ID} | jq -r '.id')
echo $RECORD_ID
rm -f $RECORD_FILE $CONFIG_FILE
+8
View File
@@ -0,0 +1,8 @@
#/bin/bash
NAME=`cat package.json | jq '.name'`
VERSION=`cat package.json | jq '.version'`
DATE=`date --rfc-3339=seconds`
echo '{"build": {}}' | jq ".build.name = $NAME" | jq ".build.version = $VERSION" | jq ".build.buildDate = \"$DATE\""
@@ -2,10 +2,7 @@
// Copyright 2020 DXOS.org
//
import { ApolloClient } from 'apollo-client';
import { ApolloLink } from 'apollo-link';
import { createHttpLink } from 'apollo-link-http';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { ApolloClient, InMemoryCache, ApolloLink, HttpLink } from '@apollo/client';
import { createResolvers } from './resolvers';
import { getServiceUrl } from './util/config';
@@ -28,7 +25,7 @@ export const graphqlApi = config => {
*/
export const clientFactory = config => {
// https://www.apollographql.com/docs/link/
const defaultLink = createHttpLink({
const defaultLink = new HttpLink({
uri: graphqlApi(config),
// TODO(burdon): Authentication: send signed message to server (from client wallet).
@@ -39,7 +36,7 @@ export const clientFactory = config => {
});
const serviceLinks = {
signal: createHttpLink({
signal: new HttpLink({
uri: getServiceUrl(config, 'signal.api')
})
};
+94
View File
@@ -0,0 +1,94 @@
//
// Copyright 2020 DXOS.org
//
import React from "react";
import { makeStyles } from "@material-ui/core";
import MuiAppBar from "@material-ui/core/AppBar";
import Divider from "@material-ui/core/Divider";
import Link from "@material-ui/core/Link";
import Toolbar from "@material-ui/core/Toolbar";
import Typography from "@material-ui/core/Typography";
import blueGrey from "@material-ui/core/colors/blueGrey";
// import GraphQLIcon from '@material-ui/icons/Adb';
import LaconicIcon from "../icons/Logo";
// import { graphqlApi } from '../client';
const useStyles = makeStyles((theme) => ({
offset: theme.mixins.denseToolbar,
logo: {
marginRight: theme.spacing(2),
color: theme.palette.grey[800],
"& svg": {
width: 100,
height: 48,
},
},
logoLink: {
lineHeight: 0,
},
title: {
display: "flex",
flex: 1,
marginTop: 2,
color: "#FBFBFB",
},
link: {
color: blueGrey[900],
},
divider: {
backgroundColor: theme.palette.text.primary,
width: "1px",
height: "20px",
alignSelf: "center",
marginRight: 14,
},
}));
const AppBar = ({ config }) => {
const classes = useStyles();
return (
<>
<MuiAppBar position="fixed" elevation={0} color="primary">
<Toolbar>
<Link classes={{ root: classes.logoLink }} href="/">
<div className={classes.logo}>
<LaconicIcon />
</div>
</Link>
<Divider
orientation="vertical"
flexItem
className={classes.divider}
/>
<div className={classes.title}>
<Typography variant="h6">{config.app.title}</Typography>
</div>
{/* <div>
<Link
className={classes.link}
href={graphqlApi(config)}
rel='noreferrer'
target='_blank'
title='Console GraphQL'
>
<GraphQLIcon />
</Link>
</div> */}
</Toolbar>
</MuiAppBar>
<div className={classes.offset} />
</>
);
};
export default AppBar;
@@ -31,9 +31,9 @@ const getAppUrl = (config, { wrn }) => {
* @param {string} name
* @param {string} [text]
*/
const AppLink = ({ config, crn, text }) => {
const fullURL = getAppUrl(config, { crn });
return <Link href={fullURL} target={crn}>{text || crn}</Link>;
const AppLink = ({ config, lrn, text }) => {
const fullURL = getAppUrl(config, { lrn });
return <Link href={fullURL} target={lrn}>{text || lrn}</Link>;
};
export default AppLink;
+38
View File
@@ -0,0 +1,38 @@
//
// Copyright 2020 DXOS.org
//
import React from "react";
import { makeStyles } from "@material-ui/core";
import { JsonTreeView } from "@lirewine/react-ux";
import { omitDeep } from "../util/omit";
const useStyles = makeStyles(() => ({
root: {
flex: 1,
},
}));
const useTreeStyles = makeStyles(
(theme) => ({
colorPrimary: {
color: theme.palette.secondary.main,
},
}),
{ name: "MuiTypography" },
);
const Json = ({ data }) => {
const classes = useStyles();
useTreeStyles();
return (
<JsonTreeView
className={classes.root}
data={omitDeep(data, "__typename")}
/>
);
};
export default Json;
@@ -5,7 +5,7 @@
import React from 'react';
import { makeStyles } from '@material-ui/core';
const useStyles = makeStyles(() => ({
const useStyles = makeStyles(theme => ({
root: {
display: 'flex',
flexDirection: 'column',
@@ -17,7 +17,8 @@ const useStyles = makeStyles(() => ({
display: 'flex',
flexDirection: 'column',
flex: 1,
overflow: 'hidden'
overflow: 'hidden',
backgroundColor: theme.palette.background.paper,
}
}));
@@ -10,8 +10,41 @@ import LinkIcon from '@material-ui/icons/ExitToApp';
import { getServiceUrl } from '../util/config';
const QUERY = `
query {
getRecordsByIds(ids: [ "%ID%" ]) {
fragment ValueParts on Value {
... on BooleanValue {
bool: value
}
... on IntValue {
int: value
}
... on FloatValue {
float: value
}
... on StringValue {
string: value
}
... on BytesValue {
bytes: value
}
... on LinkValue {
link: value
}
}
fragment AttrParts on Attribute {
key
value {
...ValueParts
... on ArrayValue {
value {
...ValueParts
}
}
}
}
{
getRecordsByIds(ids: ["%ID%"]) {
id
names
bondId
@@ -19,12 +52,12 @@ const QUERY = `
expiryTime
owners
attributes {
key
...AttrParts
value {
string
json
reference {
id
... on MapValue {
map: value {
...AttrParts
}
}
}
}
+138
View File
@@ -0,0 +1,138 @@
//
// Copyright 2020 DXOS.org
//
import clsx from "clsx";
import React from "react";
import { useHistory, useParams } from "react-router";
// import { useQuery } from '@apollo/react-hooks';
import { makeStyles } from "@material-ui/core";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import LinkIcon from "@material-ui/icons/ExitToApp";
import ListItemText from "@material-ui/core/ListItemText";
// import EXTENSIONS from '../gql/extensions.graphql';
// import { useQueryStatusReducer } from '../hooks';
const useStyles = makeStyles((theme) => ({
root: {
display: "flex",
flex: 1,
flexDirection: "column",
justifyContent: "space-between",
},
list: {
padding: 0,
},
listItem: {
display: "flex",
alignItems: "center",
backgroundColor: theme.palette.background.default,
},
selected: {
backgroundColor: theme.palette.background.secondary,
},
itemText: {
fontFamily: '"DM Mono", monospace',
fontWeight: 400,
},
icon: {
minWidth: 40,
color: theme.palette.grey[500],
},
selected: {
color: theme.palette.text.primary,
},
expand: {
flex: 1,
},
}));
const Sidebar = ({ modules: { services, settings } }) => {
const classes = useStyles();
const history = useHistory();
const { module } = useParams();
// const { data: extensionsData } = useQueryStatusReducer(useQuery(EXTENSIONS));
// const extensions = extensionsData ? JSON.parse(extensionsData.extensions.json) : [];
const extensions = [];
const isSelected = (path) => path === `/${module}`;
const Modules = ({ modules }) => (
<List aria-label="items" className={classes.list}>
{modules.map(({ path, title, icon: Icon }) => (
<ListItem
button
selected={isSelected(path)}
key={path}
onClick={() => history.push(path)}
classes={{ root: classes.listItem, selected: classes.selected }}
>
<ListItemIcon classes={{ root: classes.icon }}>
<Icon
className={clsx(
classes.icon,
isSelected(path) && classes.selected,
)}
/>
</ListItemIcon>
<ListItemText
primary={title.toUpperCase()}
classes={{ primary: classes.itemText }}
/>
</ListItem>
))}
</List>
);
const Extensions = ({ extensions }) => (
<List aria-label="items" className={classes.list}>
{extensions.map(({ url, title }) => {
url = url
.replace("%HOST%", window.location.host)
.replace("%PORT%", window.location.port)
.replace("%PROTOCOL%", window.location.protocol);
return (
<ListItem
button
key={url}
onClick={() => {
window.location = url;
return true;
}}
>
<ListItemIcon classes={{ root: classes.icon }}>
<LinkIcon className={clsx(classes.icon)} />
</ListItemIcon>
<ListItemText
primary={title.toUpperCase()}
classes={{ primary: classes.itemText }}
/>
</ListItem>
);
})}
</List>
);
return (
<div className={classes.root}>
<Modules modules={services} />
<Extensions extensions={extensions} />
<div className={classes.expand} />
<Modules modules={settings} />
</div>
);
};
export default Sidebar;
+33
View File
@@ -0,0 +1,33 @@
//
// Copyright 2020 DXOS.org
//
import React from "react";
import { makeStyles } from "@material-ui/core";
import MuiToolbar from "@material-ui/core/Toolbar";
const useStyles = makeStyles((theme) => ({
toolbar: {
display: "flex",
justifyContent: "space-between",
whiteSpace: "nowrap",
"& > button": {
margin: theme.spacing(0.5),
},
color: "primary",
},
}));
// TODO(burdon): Tabs.
const Toolbar = ({ children }) => {
const classes = useStyles();
return (
<MuiToolbar disableGutters className={classes.toolbar}>
{children}
</MuiToolbar>
);
};
export default Toolbar;
@@ -5,7 +5,7 @@
import React, { useContext } from 'react';
import { makeStyles } from '@material-ui/core';
import { FullScreen } from '@dxos/gem-core';
import { FullScreen } from '@lirewine/gem-core';
import { ConsoleContext } from '../hooks';
@@ -8,7 +8,7 @@ import { ApolloProvider } from '@apollo/react-hooks';
import { ThemeProvider } from '@material-ui/core/styles';
import CssBaseline from '@material-ui/core/CssBaseline';
import { ErrorHandler } from '@dxos/debug';
import { ErrorHandler } from '@lirewine/debug';
import { build } from '../version.json';
@@ -28,7 +28,10 @@ const useStyles = makeStyles((theme) => ({
flexDirection: 'row',
flex: 1,
justifyContent: 'space-between',
backgroundColor: grey[900],
backgroundColor: theme.palette.background.default,
borderTop: 1,
borderTopColor: "rgba(255, 255, 255, 0.12)",
borderTopStyle: "solid",
color: grey[400]
},
left: {
@@ -2,43 +2,48 @@
// Copyright 2020 DXOS.org
//
import React, { useState } from 'react';
import { makeStyles } from '@material-ui/core';
import Paper from '@material-ui/core/Paper';
import Tab from '@material-ui/core/Tab';
import Tabs from '@material-ui/core/Tabs';
import TabContext from '@material-ui/lab/TabContext';
import React, { useState } from "react";
import { makeStyles } from "@material-ui/core";
import Paper from "@material-ui/core/Paper";
import Tab from "@material-ui/core/Tab";
import Tabs from "@material-ui/core/Tabs";
import TabContext from "@material-ui/lab/TabContext";
import Panel from '../../../components/Panel';
import Toolbar from '../../../components/Toolbar';
import Panel from "../../../components/Panel";
import Toolbar from "../../../components/Toolbar";
// import LogPoller from '../../../components/LogPoller';
import RegistryLookup, { LookupType } from './RegistryLookup';
import RegistryStatus from './RegistryStatus';
import RegistryRecords from './RegistryRecords';
import RegistryLookup, { LookupType } from "./RegistryLookup";
import RegistryStatus from "./RegistryStatus";
import RegistryRecords from "./RegistryRecords";
// import RegistryRecords, { RecordType } from './RegistryRecords';
const TAB_RECORDS = 'records';
const TAB_STATUS = 'status';
const TAB_LOOKUP = 'lookup';
const TAB_RECORDS = "records";
const TAB_STATUS = "status";
const TAB_LOOKUP = "lookup";
// const TAB_LOG = 'log';
const useStyles = makeStyles(() => ({
expand: {
flex: 1
flex: 1,
},
panel: {
display: 'flex',
overflowY: 'scroll',
flex: 1
display: "flex",
overflowY: "scroll",
flex: 1,
},
paper: {
display: 'flex',
overflow: 'hidden',
flex: 1
}
display: "flex",
overflow: "hidden",
flex: 1,
},
tabs: {
fontFamily: '"DM Mono", monospace',
fontWeight: 400,
},
}));
const Registry = () => {
@@ -51,10 +56,14 @@ const Registry = () => {
<Panel
toolbar={
<Toolbar>
<Tabs value={tab} onChange={(_, value) => setTab(value)}>
<Tab value={TAB_RECORDS} label='Records' />
<Tab value={TAB_LOOKUP} label='Lookup' />
<Tab value={TAB_STATUS} label='Status' />
<Tabs
value={tab}
onChange={(_, value) => setTab(value)}
indicatorColor="primary"
>
<Tab value={TAB_RECORDS} label="Records" className={classes.tabs} />
<Tab value={TAB_LOOKUP} label="Lookup" className={classes.tabs} />
<Tab value={TAB_STATUS} label="Status" className={classes.tabs} />
{/* <Tab value={TAB_LOG} label='Log' /> */}
</Tabs>
@@ -37,7 +37,7 @@ const useStyles = makeStyles(theme => ({
const types = [
{ key: 'authority', label: 'Authority' },
{ key: 'crn', label: 'CRN' }
{ key: 'lrn', label: 'LRN' }
];
export const LookupType = ({ scope = types[0].key, onChange }) => {
@@ -87,7 +87,7 @@ const RegistryLookup = ({ scope }) => {
const getNames = () => {
let ret;
switch (scope) {
case 'crn': {
case 'lrn': {
ret = [];
records.forEach(item => ret.push(...(item.names || [])));
break;
@@ -99,8 +99,8 @@ const RegistryLookup = ({ scope }) => {
const names = new Set();
for (const record of records) {
for (const name of (record.names || [])) {
// TODO(telackey): We need a general purpose CRN handling library.
names.add(name.replace('crn://', '').split('/')[0]);
// TODO(telackey): We need a general purpose LRN handling library.
names.add(name.replace('lrn://', '').split('/')[0]);
}
}
ret = Array.from(names.values());
@@ -120,7 +120,7 @@ const RegistryLookup = ({ scope }) => {
let result;
switch (scope) {
case 'crn':
case 'lrn':
result = await registry.lookupNames([newInputValue], true);
break;
@@ -31,13 +31,13 @@ const useStyles = makeStyles(theme => ({
const types = [
{ key: null, label: 'ALL' },
{ key: 'crn:kube', label: 'Kube' },
{ key: 'crn:service', label: 'Service' },
{ key: 'crn:app', label: 'App' },
{ key: 'crn:bot', label: 'Bot' },
{ key: 'crn:bot-factory', label: 'Bot Factory' },
{ key: 'crn:file', label: 'File' },
{ key: 'crn:type', label: 'Type' }
{ key: 'lrn:kube', label: 'Kube' },
{ key: 'lrn:service', label: 'Service' },
{ key: 'lrn:app', label: 'App' },
{ key: 'lrn:bot', label: 'Bot' },
{ key: 'lrn:bot-factory', label: 'Bot Factory' },
{ key: 'lrn:file', label: 'File' },
{ key: 'lrn:type', label: 'Type' }
];
export const RecordType = ({ type = types[0].key, onChange }) => {
@@ -104,12 +104,12 @@ const RegistryRecords = ({ type }) => {
pkgLink = (<PackageLink config={config} type={type} pkg={pkg} />);
}
if (type === 'crn:app') {
if (type === 'lrn:app') {
appLinks = (
<>
{(names || []).map(crn =>
<div key={crn}>
<AppLink config={config} crn={crn} />
{(names || []).map(lrn =>
<div key={lrn}>
<AppLink config={config} lrn={lrn} />
</div>
)}
</>

Some files were not shown because too many files have changed in this diff Show More