Compare commits

...

29 Commits

Author SHA1 Message Date
cha0s
0b708db7db refactor: user and session 2024-01-13 14:29:01 -06:00
cha0s
196d128e83 refactor: tabs 2024-01-13 14:28:38 -06:00
cha0s
a1cb769119 refactor: electron 2024-01-13 14:25:58 -06:00
cha0s
bf2d1630ed chore: tidy 2024-01-13 07:46:50 -06:00
cha0s
0d7255e2eb chore: bump glob 2024-01-13 01:59:25 -06:00
cha0s
0af48b6493 refactor: obsolete 2024-01-12 05:00:53 -06:00
cha0s
5cd735c11f refactor: style loading 2024-01-11 05:06:32 -06:00
cha0s
25cc07b7cd refactor: auto root 2024-01-10 05:26:55 -06:00
cha0s
97274d5402 refactor: react fast refresh 2024-01-10 04:50:23 -06:00
cha0s
c87cca3813 refactor: priority 2024-01-09 23:02:33 -06:00
cha0s
0879069d54 chore: template 2024-01-09 22:57:50 -06:00
cha0s
a60ac484fc refactor: mixin 2024-01-05 20:07:42 -06:00
cha0s
3553d6ca8d refactor: mixin 2024-01-05 19:26:41 -06:00
cha0s
9b8e39bc3c chore: build 2024-01-04 16:10:11 -06:00
cha0s
b7731fb8ab chore: tidy 2023-12-02 06:43:11 -06:00
cha0s
b852b564e8 chore: electron patch 2023-11-30 20:41:20 -06:00
cha0s
e5269df083 fix: exports 2023-11-30 20:41:13 -06:00
cha0s
77c3e21208 chore: webpack 5 2023-11-30 20:41:07 -06:00
cha0s
dd6422e8da fix: icon path 2023-11-30 20:40:57 -06:00
cha0s
34a472ad0e fix: version 2023-11-30 20:40:45 -06:00
cha0s
4b232926ba chore: bumps 2023-11-30 18:55:00 -06:00
cha0s
9d16aa2cd1 feat: dox 2022-08-11 07:02:40 -05:00
cha0s
7db6f37e2e fix: unlink-all 2022-08-11 06:38:44 -05:00
cha0s
43f9c7c3dd refactor: hooks 2022-08-10 14:33:03 -05:00
cha0s
ba33810599 feat: filters 2022-04-19 05:18:12 -05:00
cha0s
3b8658144e fix: no group 2022-04-15 12:35:21 -05:00
cha0s
e698a92b17 chore: color 2022-04-15 12:35:11 -05:00
cha0s
443fe7f2b3 feat: undo groups 2022-04-11 20:14:54 -05:00
cha0s
a6a676a2f1 chore: reset input 2022-04-11 14:42:49 -05:00
27 changed files with 237 additions and 304 deletions

1
.gitignore vendored
View File

@ -118,6 +118,7 @@ dist
# local # local
/dev /dev
/dist /dist
/dox
/packages/*/yarn.lock /packages/*/yarn.lock
/profile.*.json /profile.*.json
/yarn.lock /yarn.lock

View File

@ -5,6 +5,7 @@
'@avocado/color': {} '@avocado/color': {}
'@avocado/entity': {} '@avocado/entity': {}
'@avocado/entity/persea': {} '@avocado/entity/persea': {}
'@avocado/filters': {}
'@avocado/graphics': {} '@avocado/graphics': {}
'@avocado/graphics/persea': {} '@avocado/graphics/persea': {}
'@avocado/input': {} '@avocado/input': {}
@ -37,28 +38,19 @@
'@humus/core/persea': {} '@humus/core/persea': {}
'@flecks/core': '@flecks/core':
id: 'persea' id: 'persea'
# '@flecks/core/server':
# profile:
# - http
# - server
'@flecks/db': {} '@flecks/db': {}
'@flecks/db/server': '@flecks/db/server':
port: 32362 port: 32362
'@flecks/docker': {} '@flecks/docker': {}
'@flecks/dox': {}
'@flecks/electron/server': '@flecks/electron/server':
browserWindowOptions: browserWindowOptions:
backgroundColor: '#212121' backgroundColor: '#212121'
show: false show: false
quitOnClosed: false quitOnClosed: false
window:
- '...'
- '@persea/core'
'@flecks/governor': {} '@flecks/governor': {}
'@flecks/react': '@flecks/passport-local-react': {}
providers: '@flecks/react': {}
- '@flecks/redux'
- '@flecks/react/router'
- '...'
'@flecks/react/router': {} '@flecks/react/router': {}
'@flecks/redis': {} '@flecks/redis': {}
'@flecks/redis/server': '@flecks/redis/server':
@ -69,45 +61,16 @@
'@flecks/server': '@flecks/server':
nodeArgs: nodeArgs:
- '--inspect' - '--inspect'
# - '--log-deopt'
# - '--log-ic'
# - '--logfile=/home/cha0s/yuge/tmp/v8.log'
up:
- '@flecks/docker'
- '@flecks/db'
- '@flecks/redis'
- '@flecks/user/session'
- '@flecks/user'
- '@flecks/user/local'
- '@flecks/governor'
- '...'
- '@persea/bootstrap'
- '@flecks/web'
- '@flecks/electron'
- '@flecks/repl'
'@flecks/socket': {} '@flecks/socket': {}
'@flecks/socket/server': '@flecks/socket/server': {}
authenticate:
- '@flecks/user/session/server'
- '@flecks/user/server'
connect:
- '@flecks/socket/server'
'@flecks/user': {}
'@flecks/user/local': {}
'@flecks/user/session': {}
'@flecks/web': {} '@flecks/web': {}
'@flecks/web/client': '@flecks/web/client': {}
up:
- '@flecks/socket'
- '@flecks/react'
- '...'
'@flecks/web/server': '@flecks/web/server':
devDisableHostCheck: true devDisableHostCheck: true
dll: dll:
- '@babel/core' - '@babel/core'
- '@babel/parser' - '@babel/parser'
- '@babel/types' - '@babel/types'
- '@hot-loader/react-dom'
- '@pixi/constants' - '@pixi/constants'
- '@pixi/core' - '@pixi/core'
- '@pixi/display' - '@pixi/display'
@ -127,22 +90,16 @@
- 'matter-js' - 'matter-js'
- 'pako' - 'pako'
- 'react' - 'react'
- 'react-dom'
- 'react-refresh/runtime'
- 'react-hex-editor' - 'react-hex-editor'
- 'react-json-editor-ajrm' - 'react-json-editor-ajrm'
- 'react-window' - 'react-window'
port: 32360 port: 32360
public: 'persea.localhost' public: 'persea.localhost'
request.route:
- '@flecks/user/session'
- '@flecks/user'
- '@persea/core/electron'
- '...'
request.socket: request.socket:
- '@persea/core' - '@persea/core'
- '...' - '...'
stream.html:
- '@flecks/react'
- '...'
'@persea/bootstrap': {} '@persea/bootstrap': {}
'@persea/core': {} '@persea/core': {}
'@persea/core/electron': {} '@persea/core/electron': {}

View File

@ -1,26 +0,0 @@
<!DOCTYPE html>
<html lang="<%= htmlWebpackPlugin.options.lang %>">
<head>
<base href="/" />
<meta charset="utf-8">
<link rel="icon" type="image/png" href="/icon.png" />
<meta name="viewport" content="width=device-width, user-scalable=no" />
<title>Persea</title>
<style>
html {
background-color: #212121;
color: #ffffff;
}
</style>
<% if (styleFile) { %>
<style data-href="<%= styleFile.href %>">
<%= styleFile.content %>
</style>
<% } %>
</head>
<body>
<div id="<%= htmlWebpackPlugin.options.appMountId %>"></div>
<script src="/flecks.config.js"></script>
<%= htmlWebpackPlugin.tags.bodyTags %>
</body>
</html>

View File

@ -1,21 +0,0 @@
/* eslint-disable import/no-extraneous-dependencies */
const copy = require('@neutrinojs/copy');
module.exports = async (flecks) => {
// eslint-disable-next-line global-require
const config = await require('@flecks/web/server/build/web.neutrinorc')(flecks);
config.use.push(
copy({
copyUnmodified: true,
patterns: [
{
from: 'icon.png',
to: 'web/assets/icon.png',
},
],
}),
);
return config;
};

View File

@ -0,0 +1,17 @@
const {copy} = require('@flecks/core/server');
const configFn = require('@flecks/web/server/build/web.webpack.config');
module.exports = async (env, argv, flecks) => {
const config = await configFn(env, argv, flecks);
config.plugins.push(
copy({
patterns: [
{
from: 'icon.png',
to: 'assets/icon.png',
},
],
}),
);
return config;
};

View File

@ -8,16 +8,16 @@
"version": "4.0.0", "version": "4.0.0",
"private": true, "private": true,
"scripts": { "scripts": {
"build": "FLECKS_ENV_FLECKS_SERVER_start=0 npm run build:only", "build": "FLECKS_ENV__flecks_server__start=0 npm run build:only",
"build:only": "flecks build", "build:only": "flecks build",
"debug": "DEBUG=*,-babel* npm run dev", "debug": "DEBUG=*,-babel* npm run dev",
"dev": "npm run -- build:only -h", "dev": "npm run -- build:only -dh",
"link-all": "yarn && for i in avocado humus persea; do yarn link $(for j in $(ls node_modules/@$i/); do echo \" @$i/$j\"; done); done", "link-all": "yarn && for i in avocado humus persea; do yarn link $(for j in $(ls node_modules/@$i/); do echo \" @$i/$j\"; done); done",
"postinstall": "patch-package", "postinstall": "patch-package",
"refresh": "rm -rf yarn.lock node_modules dist && yarn link-all", "refresh": "rm -rf yarn.lock node_modules dist && yarn link-all",
"repl": "npx flecks repl --rlwrap", "repl": "npx flecks repl --rlwrap",
"start": "DEBUG=@avocado*,@flecks*,@persea*,persea*,-*:silly npm run dev", "start": "DEBUG=@avocado*,@flecks*,@persea*,persea*,-*:silly npm run dev",
"unlink-all": "yarn unlink $(for i in $(ls node_modules/@flecks); do echo -n \"@flecks/$i \"; done) && yarn install --force", "unlink-all": "for i in avocado humus persea; do yarn unlink $(for j in $(ls node_modules/@$i/); do echo \" @$i/$j\"; done); done && yarn install --force",
"up": "yarn add $(for i in $(ls node_modules/@flecks); do echo -n \"@flecks/$i \"; done) $(for i in $(ls node_modules/@avocado); do echo -n \"@avocado/$i \"; done) $(for i in $(ls node_modules/@humus); do echo -n \"@humus/$i \"; done)" "up": "yarn add $(for i in $(ls node_modules/@flecks); do echo -n \"@flecks/$i \"; done) $(for i in $(ls node_modules/@avocado); do echo -n \"@avocado/$i \"; done) $(for i in $(ls node_modules/@humus); do echo -n \"@humus/$i \"; done)"
}, },
"dependencies": { "dependencies": {
@ -25,6 +25,7 @@
"@avocado/color": "^3.0.0", "@avocado/color": "^3.0.0",
"@avocado/core": "^3.0.0", "@avocado/core": "^3.0.0",
"@avocado/entity": "^3.0.0", "@avocado/entity": "^3.0.0",
"@avocado/filters": "^3.0.0",
"@avocado/graphics": "^3.0.0", "@avocado/graphics": "^3.0.0",
"@avocado/input": "^3.0.0", "@avocado/input": "^3.0.0",
"@avocado/math": "^3.0.0", "@avocado/math": "^3.0.0",
@ -36,29 +37,30 @@
"@avocado/timing": "^3.0.0", "@avocado/timing": "^3.0.0",
"@avocado/topdown": "^3.0.0", "@avocado/topdown": "^3.0.0",
"@avocado/traits": "^3.0.0", "@avocado/traits": "^3.0.0",
"@flecks/core": "^1.4.1", "@flecks/core": "^2.0.3",
"@flecks/create-app": "^1.4.1", "@flecks/create-app": "^2.0.3",
"@flecks/db": "^1.4.1", "@flecks/db": "^2.0.3",
"@flecks/electron": "^1.4.1", "@flecks/dox": "^2.0.3",
"@flecks/governor": "^1.4.1", "@flecks/electron": "^2.0.3",
"@flecks/react": "^1.4.1", "@flecks/governor": "^2.0.3",
"@flecks/redis": "^1.4.1", "@flecks/passport-local-react": "^2.0.3",
"@flecks/redux": "^1.4.1", "@flecks/react": "^2.0.3",
"@flecks/repl": "^1.4.1", "@flecks/redis": "^2.0.3",
"@flecks/server": "^1.4.1", "@flecks/redux": "^2.0.3",
"@flecks/socket": "^1.4.1", "@flecks/repl": "^2.0.3",
"@flecks/user": "^1.4.1", "@flecks/server": "^2.0.3",
"@flecks/web": "^1.4.1", "@flecks/socket": "^2.0.3",
"@humus/combat": "^2.0.0", "@flecks/web": "^2.0.3",
"@humus/core": "^2.0.0", "@humus/combat": "^2.1.0",
"@humus/core": "^2.1.0",
"@persea/bootstrap": "^4.0.0", "@persea/bootstrap": "^4.0.0",
"@persea/core": "^4.0.0", "@persea/core": "^4.0.0",
"pg": "^8.7.3", "pg": "^8.7.3",
"pg-hstore": "^2.3.4" "pg-hstore": "^2.3.4"
}, },
"devDependencies": { "devDependencies": {
"@flecks/create-fleck": "^1.4.1", "@flecks/create-fleck": "^2.0.3",
"@flecks/docker": "^1.4.1", "@flecks/docker": "^2.0.3",
"lerna": "^3.22.1", "lerna": "^3.22.1",
"patch-package": "^6.4.7", "patch-package": "^6.4.7",
"postinstall-postinstall": "^2.1.0" "postinstall-postinstall": "^2.1.0"

View File

@ -14,18 +14,12 @@
"test": "flecks test" "test": "flecks test"
}, },
"files": [ "files": [
"build", "server.js"
"server.js",
"server.js.map",
"src",
"test",
"test.js",
"test.js.map"
], ],
"dependencies": { "dependencies": {
"@flecks/core": "^1.4.1" "@flecks/core": "^2.0.3"
}, },
"devDependencies": { "devDependencies": {
"@flecks/fleck": "^1.4.1" "@flecks/fleck": "^2.0.3"
} }
} }

View File

@ -1,16 +1,12 @@
import {Hooks} from '@flecks/core'; import {Flecks} from '@flecks/core';
// const { export const hooks = {
// NODE_ENV, '@flecks/server.up': Flecks.priority(
// } = process.env; async (flecks) => {
export default {
[Hooks]: {
'@flecks/server.up': async (flecks) => {
// if ('production' === NODE_ENV) { // if ('production' === NODE_ENV) {
// return; // return;
// } // }
const {Project, User} = flecks.get('$flecks/db.models'); const {Project, User} = flecks.db.Models;
if (!await User.findOne({where: {email: 'persea@cha0s.io'}})) { if (!await User.findOne({where: {email: 'persea@cha0s.io'}})) {
const user = await User.create({ const user = await User.create({
email: 'persea@cha0s.io', email: 'persea@cha0s.io',
@ -25,5 +21,6 @@ export default {
await user.save(); await user.save();
} }
}, },
}, {after: '@flecks/passport/server'},
),
}; };

View File

@ -15,34 +15,23 @@
"test": "flecks test" "test": "flecks test"
}, },
"files": [ "files": [
"assets",
"build",
"electron/server.js", "electron/server.js",
"electron/server.js.map",
"index.css",
"index.css.map",
"index.js", "index.js",
"index.js.map", "server.js"
"server.js",
"server.js.map",
"src",
"test",
"test.js",
"test.js.map"
], ],
"dependencies": { "dependencies": {
"@avocado/graphics": "^3.0.0", "@avocado/graphics": "^3.0.0",
"@avocado/math": "^3.0.0", "@avocado/math": "^3.0.0",
"@avocado/react": "^3.0.0", "@avocado/react": "^3.0.0",
"@avocado/resource": "^3.0.0", "@avocado/resource": "^3.0.0",
"@flecks/core": "^1.4.1", "@flecks/core": "^2.0.3",
"@flecks/db": "^1.4.1", "@flecks/db": "^2.0.3",
"@flecks/react": "^1.4.1", "@flecks/passport": "^2.0.3",
"@flecks/redux": "^1.4.1", "@flecks/passport-react": "^2.0.3",
"@flecks/user": "^1.4.1", "@flecks/react": "^2.0.3",
"@flecks/redux": "^2.0.3",
"express": "^4.17.1", "express": "^4.17.1",
"fast-json-patch": "^3.0.0-1", "fast-json-patch": "^3.0.0-1",
"glob": "^7.1.6",
"is-electron": "^2.2.1", "is-electron": "^2.2.1",
"natsort": "^2.0.2", "natsort": "^2.0.2",
"react-hex-editor": "^0.3.0", "react-hex-editor": "^0.3.0",
@ -50,6 +39,6 @@
"react-ui-tree": "^4.0.0" "react-ui-tree": "^4.0.0"
}, },
"devDependencies": { "devDependencies": {
"@flecks/fleck": "^1.4.1" "@flecks/fleck": "^2.0.3"
} }
} }

View File

@ -9,6 +9,7 @@ html {
color: #FFFFFF; color: #FFFFFF;
--background-color-active: rgba(0, 120, 255, 0.5); --background-color-active: rgba(0, 120, 255, 0.5);
--color-active: rgb(0, 99, 112); --color-active: rgb(0, 99, 112);
--color-active-light: rgb(0, 168, 191);
--message-font-family: verdana, arial, helvetica, sans-serif; --message-font-family: verdana, arial, helvetica, sans-serif;
--system-font-family: system-ui, Ubuntu, Droid Sans, sans-serif; --system-font-family: system-ui, Ubuntu, Droid Sans, sans-serif;
--title-font-family: LatoLight, Ubuntu, "Droid Sans", sans-serif; --title-font-family: LatoLight, Ubuntu, "Droid Sans", sans-serif;
@ -115,6 +116,12 @@ label, .label {
user-select: none; user-select: none;
} }
button[disabled],
input[disabled]
{
opacity: 0.4;
}
// .muted { // .muted {
// color: $color-muted; // color: $color-muted;
// } // }

View File

@ -1,6 +1,5 @@
import { import {
React, React,
hot,
} from '@flecks/react'; } from '@flecks/react';
import useLocalStorage from '../../hooks/use-local-storage'; import useLocalStorage from '../../hooks/use-local-storage';
@ -23,4 +22,4 @@ Persea.displayName = 'Persea';
Persea.propTypes = {}; Persea.propTypes = {};
export default hot(module)(Persea); export default Persea;

View File

@ -1,15 +1,15 @@
import {basename} from 'path'; import {basename} from 'path';
import {Context, Resource as ResourceComponent} from '@avocado/resource/persea';
import {classnames, PropTypes, React} from '@flecks/react';
import { import {
Tab, Tab,
Tabs, Tabs,
TabList, TabList,
TabPanel, TabPanel,
} from '@avocado/react'; } from '@flecks/react/tabs';
import {Context, Resource as ResourceComponent} from '@avocado/resource/persea';
import {classnames, PropTypes, React} from '@flecks/react';
import {useDispatch, useSelector} from '@flecks/redux'; import {useDispatch, useSelector} from '@flecks/redux';
import {userIdSelector} from '@flecks/user'; import {userIdSelector} from '@flecks/passport';
import { import {
closeResource, closeResource,
currentResourceSelector, currentResourceSelector,

View File

@ -1,12 +1,12 @@
import {Login as PassportLogin} from '@flecks/passport-react';
import {React} from '@flecks/react'; import {React} from '@flecks/react';
import {UserLocalLogin} from '@flecks/user/local';
import styles from './index.module.scss'; import styles from './index.module.scss';
function Login() { function Login() {
return ( return (
<div className={styles.login}> <div className={styles.login}>
<UserLocalLogin /> <PassportLogin />
</div> </div>
); );
} }

View File

@ -5,7 +5,7 @@ del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var, small, strike, strong, sub, sup, tt, var,
b, u, i, center, b, u, i, center,
dl, dt, dd, ol, ul, li, dl, dt, dd, ol, ul, li,
fieldset, form, label, legend, fieldset, form, input, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td, table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed, article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup, figure, figcaption, footer, header, hgroup,

View File

@ -1,8 +1,8 @@
.react-tabs { .react-tabs[class] {
flex-shrink: 0; flex-shrink: 0;
} }
.react-tabs__tab { .react-tabs__tab[class] {
background-color: #222; background-color: #222;
color: white; color: white;
border: none; border: none;
@ -36,22 +36,22 @@
visibility: visible; visibility: visible;
} }
} }
.react-tabs__tab--selected { .react-tabs__tab--selected[class] {
background-color: #171717; background-color: #171717;
border: none; border: none;
border-left: 1px solid rgba(255, 255, 255, 0.1); border-left: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 0; border-radius: 0;
color: #FFFFFF; color: #FFFFFF;
} }
.react-tabs__tab-list { .react-tabs__tab-list[class] {
border: none; border: none;
margin: 0; margin: 0;
position: relative; position: relative;
white-space: nowrap; white-space: nowrap;
} }
.react-tabs__tab-panel { .react-tabs__tab-panel[class] {
background-color: rgba(0, 0, 0, 0.2); background-color: rgba(0, 0, 0, 0.2);
} }
.react-tabs__tab-panel--selected { .react-tabs__tab-panel--selected[class] {
display: block; display: block;
} }

View File

@ -1,6 +1,6 @@
import {Flecks} from '@flecks/core';
import {join} from 'path'; import {join} from 'path';
import {Hooks} from '@flecks/core';
import isElectron from 'is-electron'; import isElectron from 'is-electron';
const { const {
@ -8,13 +8,12 @@ const {
NODE_ENV, NODE_ENV,
} = process.env; } = process.env;
export default { export const hooks = {
[Hooks]: { '@flecks/electron/server.browserWindowOptions.alter': (browserWindowOptions) => {
'@flecks/core.starting': (flecks) => {
const {browserWindowOptions} = flecks.get('@flecks/electron/server');
browserWindowOptions.icon = join(FLECKS_CORE_ROOT, 'icon.png'); browserWindowOptions.icon = join(FLECKS_CORE_ROOT, 'icon.png');
}, },
'@flecks/electron/server.window': async (win) => { '@flecks/electron/server.window': Flecks.priority(
async (win) => {
// win.removeMenu(); // win.removeMenu();
if ('production' !== NODE_ENV) { if ('production' !== NODE_ENV) {
win.openDevTools(); win.openDevTools();
@ -24,13 +23,17 @@ export default {
win.show(); win.show();
}); });
}, },
'@flecks/web/server.request.route': (flecks) => async (req, res, next) => { {after: '@flecks/electron/server'},
),
'@flecks/web/server.request.route': Flecks.priority(
(flecks) => async (req, res, next) => {
if (isElectron() && 0 === req.user.id) { if (isElectron() && 0 === req.user.id) {
const {User} = flecks.get('$flecks/db.models'); const {User} = flecks.db.Models;
req.logIn(await User.findByPk(1), next); req.logIn(await User.findByPk(1), next);
return; return;
} }
next(); next();
}, },
}, {after: '@flecks/passport/server'},
),
}; };

View File

@ -4,7 +4,6 @@ import {
replaceResource, replaceResource,
undo, undo,
} from '@avocado/resource/persea'; } from '@avocado/resource/persea';
import {Hooks} from '@flecks/core';
import Persea from './components/persea'; import Persea from './components/persea';
import organization from './sidebar/organization'; import organization from './sidebar/organization';
@ -17,11 +16,10 @@ import {
export * from './state'; export * from './state';
export default { export const hooks = {
[Hooks]: {
'@flecks/react.roots': () => Persea, '@flecks/react.roots': () => Persea,
'@flecks/redux.effects': (flecks) => { '@flecks/redux.effects': (flecks) => {
const withSocket = (fn) => (...args) => fn(...args.concat(flecks.get('$flecks/socket.socket'))); const withSocket = (fn) => (...args) => fn(...args.concat(flecks.socket.client));
return Object.fromEntries( return Object.fromEntries(
[ [
patchJsonResource, patchJsonResource,
@ -49,5 +47,4 @@ export default {
projects: projectsSidebar, projects: projectsSidebar,
organization, organization,
}), }),
},
}; };

View File

@ -1,22 +1,35 @@
import {join} from 'path'; import {join} from 'path';
import {Flecks, Hooks} from '@flecks/core'; import {Flecks} from '@flecks/core';
import express from 'express'; import express from 'express';
import startFlush from './start-flush'; import startFlush from './start-flush';
const resources = express.static(join(process.cwd(), 'projects')); const resources = express.static(join(process.cwd(), 'projects'));
export default { export const hooks = {
[Hooks]: { '@flecks/core.mixin': (Flecks) => (
class FlecksWithPerseaCore extends Flecks {
constructor(...args) {
super(...args);
if (!this.persea) {
this.persea = {};
}
if (!this.persea.core) {
this.persea.core = {};
}
this.persea.core.patches = [];
this.persea.core.replacements = [];
}
}
),
'@flecks/core.starting': (flecks) => { '@flecks/core.starting': (flecks) => {
flecks.set('$persea/core.patches', []);
flecks.set('$persea/core.replacements', []);
startFlush(flecks); startFlush(flecks);
}, },
'@flecks/core.webpack': (target, config) => { '@flecks/core.webpack': (target, config) => {
if ('web' === target) { if ('web' === target) {
// eslint-disable-next-line no-param-reassign
config.devServer.writeToDisk = true; config.devServer.writeToDisk = true;
} }
}, },
@ -35,5 +48,4 @@ export default {
'@flecks/socket.packets.decorate': ( '@flecks/socket.packets.decorate': (
Flecks.decorate(require.context('./packets/decorators', false, /\.js$/)) Flecks.decorate(require.context('./packets/decorators', false, /\.js$/))
), ),
},
}; };

View File

@ -2,11 +2,10 @@ import fs from 'fs';
import {join} from 'path'; import {join} from 'path';
import {promisify} from 'util'; import {promisify} from 'util';
import {glob} from '@flecks/core/server';
import {Model, Sequelize, Types} from '@flecks/db/server'; import {Model, Sequelize, Types} from '@flecks/db/server';
import natsort from 'natsort'; import natsort from 'natsort';
import G from 'glob';
const glob = promisify(G);
const stat = promisify(fs.stat); const stat = promisify(fs.stat);
const sorter = natsort({insensitive: true}); const sorter = natsort({insensitive: true});

View File

@ -15,42 +15,48 @@ export default (Action, flecks) => class ProjectAction extends Action {
const {data: {type, payload}} = packet; const {data: {type, payload}} = packet;
switch (type) { switch (type) {
case patchJsonResource.toString(): { case patchJsonResource.toString(): {
flecks.get('$persea/core.patches').push(payload); flecks.persea.core.patches.push(payload);
break; break;
} }
case redo.toString(): { case redo.toString(): {
const {project, uri} = payload; const {project, uri} = payload;
const path = join(process.cwd(), 'projects', project, uri); const path = join(process.cwd(), 'projects', project, uri);
const {toBuffer, fromBuffer} = flecks.get('$avocado/resource/persea.controllers') const {toBuffer, fromBuffer} = flecks.avocado.resource.persea.Controllers
.find(({matcher}) => uri.match(matcher)); .find(({matcher}) => uri.match(matcher));
const buffer = await readFile(path); const buffer = await readFile(path);
const json = fromBuffer(buffer, flecks); const json = fromBuffer(buffer, flecks);
if (json.history?.redo?.length) { if (json.history?.redo?.length) {
const patch = json.history.redo[json.history.redo.length - 1]; const {group, patch} = json.history.redo.at(-1);
socket.send(['Action', patchJsonResource({patch, project, uri}, true)]); socket.send(['Action', patchJsonResource({patch, project, uri}, true)]);
applyPatch(json, patch); applyPatch(json, patch);
json.history.undo.push(compare(json, fromBuffer(buffer, flecks))); json.history.undo.push({
...(group && {group}),
patch: compare(json, fromBuffer(buffer, flecks)),
});
json.history.redo.pop(); json.history.redo.pop();
await writeFile(path, toBuffer(json, flecks)); await writeFile(path, toBuffer(json, flecks));
} }
break; break;
} }
case replaceResource.toString(): { case replaceResource.toString(): {
flecks.get('$persea/core.replacements').push(payload); flecks.persea.core.replacements.push(payload);
break; break;
} }
case undo.toString(): { case undo.toString(): {
const {project, uri} = payload; const {project, uri} = payload;
const path = join(process.cwd(), 'projects', project, uri); const path = join(process.cwd(), 'projects', project, uri);
const {toBuffer, fromBuffer} = flecks.get('$avocado/resource/persea.controllers') const {toBuffer, fromBuffer} = flecks.avocado.resource.persea.Controllers
.find(({matcher}) => uri.match(matcher)); .find(({matcher}) => uri.match(matcher));
const buffer = await readFile(path); const buffer = await readFile(path);
const json = fromBuffer(buffer, flecks); const json = fromBuffer(buffer, flecks);
if (json.history?.undo?.length) { if (json.history?.undo?.length) {
const patch = json.history.undo[json.history.undo.length - 1]; const {group, patch} = json.history.undo.at(-1);
socket.send(['Action', patchJsonResource({patch, project, uri}, true)]); socket.send(['Action', patchJsonResource({patch, project, uri}, true)]);
applyPatch(json, patch); applyPatch(json, patch);
json.history.redo.push(compare(json, fromBuffer(buffer, flecks))); json.history.redo.push({
...(group && {group}),
patch: compare(json, fromBuffer(buffer, flecks)),
});
json.history.undo.pop(); json.history.undo.pop();
await writeFile(path, toBuffer(json, flecks)); await writeFile(path, toBuffer(json, flecks));
} }

View File

@ -5,47 +5,46 @@ import {applyPatch, compare} from 'fast-json-patch';
const startFlush = (flecks) => { const startFlush = (flecks) => {
const flushPatches = async () => { const flushPatches = async () => {
const patches = flecks.get('$persea/core.patches'); const {patches} = flecks.persea.core;
if (patches.length > 0) { if (patches.length > 0) {
const patching = {};
while (patches.length > 0) { while (patches.length > 0) {
const {patch, project, uri} = patches.shift(); const {
group,
patch,
project,
uri,
} = patches.shift();
const path = join(process.cwd(), 'projects', project, uri); const path = join(process.cwd(), 'projects', project, uri);
if (!patching[path]) { // Get controller.
const {toBuffer, fromBuffer} = flecks.get('$avocado/resource/persea.controllers') const {toBuffer, fromBuffer} = flecks.avocado.resource.persea.Controllers
.find(({matcher}) => uri.match(matcher)); .find(({matcher}) => uri.match(matcher));
patching[path] = new Promise((resolve) => { // Load.
readFile(path).then((buffer) => {
resolve({
fromBuffer,
toBuffer,
json: fromBuffer(buffer, flecks),
});
});
});
}
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
const {json} = await patching[path];
applyPatch(json, patch);
}
await Promise.all(
Object.entries(patching)
.map(async ([path, promise]) => {
const {fromBuffer, toBuffer, json} = await promise;
const buffer = await readFile(path); const buffer = await readFile(path);
const json = fromBuffer(buffer, flecks);
// Patch.
applyPatch(json, patch);
// Manage history.
const undo = compare(json, fromBuffer(buffer, flecks)); const undo = compare(json, fromBuffer(buffer, flecks));
json.history = json.history || {redo: [], undo: []}; json.history = json.history || {redo: [], undo: []};
json.history.redo = []; json.history.redo = [];
json.history.undo.push(undo); if (
return writeFile(path, toBuffer(json, flecks)); !group
}), || 0 === json.history.undo.length
); || group !== json.history.undo.at(-1).group
) {
json.history.undo.push({group, patch: undo});
}
// Flush.
// eslint-disable-next-line no-await-in-loop
await writeFile(path, toBuffer(json, flecks));
}
} }
setTimeout(flushPatches, 0); setTimeout(flushPatches, 0);
}; };
setTimeout(flushPatches, 0); setTimeout(flushPatches, 0);
const flushReplacements = async () => { const flushReplacements = async () => {
const replacements = flecks.get('$persea/core.replacements'); const {replacements} = flecks.persea.core;
if (replacements.length > 0) { if (replacements.length > 0) {
while (replacements.length > 0) { while (replacements.length > 0) {
const {value, project, uri} = replacements.shift(); const {value, project, uri} = replacements.shift();

View File

@ -25,11 +25,11 @@ const normalizeDisplayName = (displayName) => (
displayName.startsWith('HotExported') ? displayName.slice(11) : displayName displayName.startsWith('HotExported') ? displayName.slice(11) : displayName
); );
const Organization = ({ function Organization({
label, label,
resourcePaths, resourcePaths,
uuid, uuid,
}) => { }) {
const dispatch = useDispatch(); const dispatch = useDispatch();
const current = useSelector(currentResourceSelector); const current = useSelector(currentResourceSelector);
const flecks = useFlecks(); const flecks = useFlecks();
@ -69,14 +69,12 @@ const Organization = ({
} }
else { else {
const next = createNextState(expanded, (draft) => { const next = createNextState(expanded, (draft) => {
/* eslint-disable no-param-reassign */
if (value in draft) { if (value in draft) {
delete draft[value]; delete draft[value];
} }
else { else {
draft[value] = true; draft[value] = true;
} }
/* eslint-enable no-param-reassign */
}); });
setExpanded(next); setExpanded(next);
} }
@ -94,7 +92,7 @@ const Organization = ({
nodes={nodesFromResourcePaths(label, uuid, resourcePaths)} nodes={nodesFromResourcePaths(label, uuid, resourcePaths)}
renderLabel={({label, nodes, value}) => { renderLabel={({label, nodes, value}) => {
const {displayName = 'Binary'} = flecks const {displayName = 'Binary'} = flecks
.get('$avocado/resource/persea.controllers') .avocado.resource.persea.Controllers
.find(({matcher}) => value.match(matcher)) .find(({matcher}) => value.match(matcher))
.Component; .Component;
return ( return (

View File

@ -10,14 +10,12 @@ export const projectSelector = (state) => state.project;
const slice = createSlice({ const slice = createSlice({
name: 'persea/project', name: 'persea/project',
initialState: null, initialState: null,
/* eslint-disable no-param-reassign */
reducers: { reducers: {
setProject: (state, {payload}) => payload, setProject: (state, {payload}) => payload,
}, },
extraReducers: (builder) => { extraReducers: (builder) => {
builder.addCase(hydrateServer, (state, {payload}) => payload.req[HydrateServer]); builder.addCase(hydrateServer, (state, {payload}) => payload.req[HydrateServer]);
}, },
/* eslint-enable no-param-reassign */
}); });
slice.reducer.hydrateServer = async (req) => { slice.reducer.hydrateServer = async (req) => {

View File

@ -17,7 +17,7 @@ export const fetchProjectResource = createAsyncThunk(
async ({uri, uuid}, {extra: flecks}) => { async ({uri, uuid}, {extra: flecks}) => {
Resource.root = join('/projects', uuid); Resource.root = join('/projects', uuid);
const buffer = await Resource.read(uri); const buffer = await Resource.read(uri);
const {fromBuffer} = flecks.get('$avocado/resource/persea.controllers') const {fromBuffer} = flecks.avocado.resource.persea.Controllers
.find(({matcher}) => uri.match(matcher)); .find(({matcher}) => uri.match(matcher));
try { try {
return fromBuffer(Buffer.from(buffer), flecks); return fromBuffer(Buffer.from(buffer), flecks);
@ -51,7 +51,6 @@ const slice = createSlice({
pending: {}, pending: {},
resources: {}, resources: {},
}, },
/* eslint-disable no-param-reassign */
extraReducers: (builder) => { extraReducers: (builder) => {
builder.addCase(hydrateServer, (state, action) => { builder.addCase(hydrateServer, (state, action) => {
const {req} = action.payload; const {req} = action.payload;
@ -89,7 +88,6 @@ const slice = createSlice({
// delete resources[`${project}${from}`]; // delete resources[`${project}${from}`];
// }, // },
}, },
/* eslint-enable no-param-reassign */
}); });
slice.reducer.hydrateServer = async (req) => { slice.reducer.hydrateServer = async (req) => {

View File

@ -22,7 +22,6 @@ const slice = createSlice({
current: null, current: null,
open: [], open: [],
}, },
/* eslint-disable no-param-reassign */
reducers: { reducers: {
closeResource: (state, {payload}) => { closeResource: (state, {payload}) => {
const index = state.open.findIndex(({uri}) => uri === payload); const index = state.open.findIndex(({uri}) => uri === payload);
@ -48,7 +47,6 @@ const slice = createSlice({
state.open = openResourcesSelector(payload); state.open = openResourcesSelector(payload);
}); });
}, },
/* eslint-enable no-param-reassign */
}); });
export const { export const {

View File

@ -1,9 +0,0 @@
diff --git a/node_modules/electron/cli.js b/node_modules/electron/cli.js
index 09f4677..b64bb88 100755
--- a/node_modules/electron/cli.js
+++ b/node_modules/electron/cli.js
@@ -23,3 +23,4 @@ const handleTerminationSignal = function (signal) {
handleTerminationSignal('SIGINT');
handleTerminationSignal('SIGTERM');
+handleTerminationSignal('SIGUSR2');

View File

@ -0,0 +1,18 @@
diff --git a/node_modules/electron/cli.js b/node_modules/electron/cli.js
index 09f4677..5227264 100755
--- a/node_modules/electron/cli.js
+++ b/node_modules/electron/cli.js
@@ -15,11 +15,10 @@ child.on('close', function (code, signal) {
const handleTerminationSignal = function (signal) {
process.on(signal, function signalHandler () {
- if (!child.killed) {
- child.kill(signal);
- }
+ child.kill(signal);
});
};
handleTerminationSignal('SIGINT');
handleTerminationSignal('SIGTERM');
+handleTerminationSignal('SIGUSR2');