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
/dev
/dist
/dox
/packages/*/yarn.lock
/profile.*.json
/yarn.lock

View File

@ -5,6 +5,7 @@
'@avocado/color': {}
'@avocado/entity': {}
'@avocado/entity/persea': {}
'@avocado/filters': {}
'@avocado/graphics': {}
'@avocado/graphics/persea': {}
'@avocado/input': {}
@ -37,28 +38,19 @@
'@humus/core/persea': {}
'@flecks/core':
id: 'persea'
# '@flecks/core/server':
# profile:
# - http
# - server
'@flecks/db': {}
'@flecks/db/server':
port: 32362
'@flecks/docker': {}
'@flecks/dox': {}
'@flecks/electron/server':
browserWindowOptions:
backgroundColor: '#212121'
show: false
quitOnClosed: false
window:
- '...'
- '@persea/core'
'@flecks/governor': {}
'@flecks/react':
providers:
- '@flecks/redux'
- '@flecks/react/router'
- '...'
'@flecks/passport-local-react': {}
'@flecks/react': {}
'@flecks/react/router': {}
'@flecks/redis': {}
'@flecks/redis/server':
@ -69,45 +61,16 @@
'@flecks/server':
nodeArgs:
- '--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/server':
authenticate:
- '@flecks/user/session/server'
- '@flecks/user/server'
connect:
- '@flecks/socket/server'
'@flecks/user': {}
'@flecks/user/local': {}
'@flecks/user/session': {}
'@flecks/socket/server': {}
'@flecks/web': {}
'@flecks/web/client':
up:
- '@flecks/socket'
- '@flecks/react'
- '...'
'@flecks/web/client': {}
'@flecks/web/server':
devDisableHostCheck: true
dll:
- '@babel/core'
- '@babel/parser'
- '@babel/types'
- '@hot-loader/react-dom'
- '@pixi/constants'
- '@pixi/core'
- '@pixi/display'
@ -127,22 +90,16 @@
- 'matter-js'
- 'pako'
- 'react'
- 'react-dom'
- 'react-refresh/runtime'
- 'react-hex-editor'
- 'react-json-editor-ajrm'
- 'react-window'
port: 32360
public: 'persea.localhost'
request.route:
- '@flecks/user/session'
- '@flecks/user'
- '@persea/core/electron'
- '...'
request.socket:
- '@persea/core'
- '...'
stream.html:
- '@flecks/react'
- '...'
'@persea/bootstrap': {}
'@persea/core': {}
'@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",
"private": true,
"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",
"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",
"postinstall": "patch-package",
"refresh": "rm -rf yarn.lock node_modules dist && yarn link-all",
"repl": "npx flecks repl --rlwrap",
"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)"
},
"dependencies": {
@ -25,6 +25,7 @@
"@avocado/color": "^3.0.0",
"@avocado/core": "^3.0.0",
"@avocado/entity": "^3.0.0",
"@avocado/filters": "^3.0.0",
"@avocado/graphics": "^3.0.0",
"@avocado/input": "^3.0.0",
"@avocado/math": "^3.0.0",
@ -36,29 +37,30 @@
"@avocado/timing": "^3.0.0",
"@avocado/topdown": "^3.0.0",
"@avocado/traits": "^3.0.0",
"@flecks/core": "^1.4.1",
"@flecks/create-app": "^1.4.1",
"@flecks/db": "^1.4.1",
"@flecks/electron": "^1.4.1",
"@flecks/governor": "^1.4.1",
"@flecks/react": "^1.4.1",
"@flecks/redis": "^1.4.1",
"@flecks/redux": "^1.4.1",
"@flecks/repl": "^1.4.1",
"@flecks/server": "^1.4.1",
"@flecks/socket": "^1.4.1",
"@flecks/user": "^1.4.1",
"@flecks/web": "^1.4.1",
"@humus/combat": "^2.0.0",
"@humus/core": "^2.0.0",
"@flecks/core": "^2.0.3",
"@flecks/create-app": "^2.0.3",
"@flecks/db": "^2.0.3",
"@flecks/dox": "^2.0.3",
"@flecks/electron": "^2.0.3",
"@flecks/governor": "^2.0.3",
"@flecks/passport-local-react": "^2.0.3",
"@flecks/react": "^2.0.3",
"@flecks/redis": "^2.0.3",
"@flecks/redux": "^2.0.3",
"@flecks/repl": "^2.0.3",
"@flecks/server": "^2.0.3",
"@flecks/socket": "^2.0.3",
"@flecks/web": "^2.0.3",
"@humus/combat": "^2.1.0",
"@humus/core": "^2.1.0",
"@persea/bootstrap": "^4.0.0",
"@persea/core": "^4.0.0",
"pg": "^8.7.3",
"pg-hstore": "^2.3.4"
},
"devDependencies": {
"@flecks/create-fleck": "^1.4.1",
"@flecks/docker": "^1.4.1",
"@flecks/create-fleck": "^2.0.3",
"@flecks/docker": "^2.0.3",
"lerna": "^3.22.1",
"patch-package": "^6.4.7",
"postinstall-postinstall": "^2.1.0"

View File

@ -14,18 +14,12 @@
"test": "flecks test"
},
"files": [
"build",
"server.js",
"server.js.map",
"src",
"test",
"test.js",
"test.js.map"
"server.js"
],
"dependencies": {
"@flecks/core": "^1.4.1"
"@flecks/core": "^2.0.3"
},
"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 {
// NODE_ENV,
// } = process.env;
export default {
[Hooks]: {
'@flecks/server.up': async (flecks) => {
export const hooks = {
'@flecks/server.up': Flecks.priority(
async (flecks) => {
// if ('production' === NODE_ENV) {
// return;
// }
const {Project, User} = flecks.get('$flecks/db.models');
const {Project, User} = flecks.db.Models;
if (!await User.findOne({where: {email: 'persea@cha0s.io'}})) {
const user = await User.create({
email: 'persea@cha0s.io',
@ -25,5 +21,6 @@ export default {
await user.save();
}
},
},
{after: '@flecks/passport/server'},
),
};

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,7 +4,6 @@ import {
replaceResource,
undo,
} from '@avocado/resource/persea';
import {Hooks} from '@flecks/core';
import Persea from './components/persea';
import organization from './sidebar/organization';
@ -17,37 +16,35 @@ import {
export * from './state';
export default {
[Hooks]: {
'@flecks/react.roots': () => Persea,
'@flecks/redux.effects': (flecks) => {
const withSocket = (fn) => (...args) => fn(...args.concat(flecks.get('$flecks/socket.socket')));
return Object.fromEntries(
[
patchJsonResource,
redo,
replaceResource,
undo,
]
.map((action) => [
action,
withSocket((store, action, socket) => {
if (action.meta?.isRemote) {
return;
}
socket.send(['Action', action]);
}),
]),
);
},
'@flecks/redux.slices': () => ({
project,
projects,
resource,
}),
'@persea/core.sidebar': () => ({
projects: projectsSidebar,
organization,
}),
export const hooks = {
'@flecks/react.roots': () => Persea,
'@flecks/redux.effects': (flecks) => {
const withSocket = (fn) => (...args) => fn(...args.concat(flecks.socket.client));
return Object.fromEntries(
[
patchJsonResource,
redo,
replaceResource,
undo,
]
.map((action) => [
action,
withSocket((store, action, socket) => {
if (action.meta?.isRemote) {
return;
}
socket.send(['Action', action]);
}),
]),
);
},
'@flecks/redux.slices': () => ({
project,
projects,
resource,
}),
'@persea/core.sidebar': () => ({
projects: projectsSidebar,
organization,
}),
};

View File

@ -1,39 +1,51 @@
import {join} from 'path';
import {Flecks, Hooks} from '@flecks/core';
import {Flecks} from '@flecks/core';
import express from 'express';
import startFlush from './start-flush';
const resources = express.static(join(process.cwd(), 'projects'));
export default {
[Hooks]: {
'@flecks/core.starting': (flecks) => {
flecks.set('$persea/core.patches', []);
flecks.set('$persea/core.replacements', []);
startFlush(flecks);
},
'@flecks/core.webpack': (target, config) => {
if ('web' === target) {
// eslint-disable-next-line no-param-reassign
config.devServer.writeToDisk = true;
export const 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/db/server.models': Flecks.provide(require.context('./models', false, /\.js$/)),
'@flecks/db/server.models.decorate': (
Flecks.decorate(require.context('./models/decorators', false, /\.js$/))
),
'@flecks/web/server.request.socket': () => (req, res, next) => {
if (req.url.startsWith('/projects')) {
req.url = req.url.slice(9);
resources(req, res, next);
return;
}
next();
},
'@flecks/socket.packets.decorate': (
Flecks.decorate(require.context('./packets/decorators', false, /\.js$/))
),
}
),
'@flecks/core.starting': (flecks) => {
startFlush(flecks);
},
'@flecks/core.webpack': (target, config) => {
if ('web' === target) {
config.devServer.writeToDisk = true;
}
},
'@flecks/db/server.models': Flecks.provide(require.context('./models', false, /\.js$/)),
'@flecks/db/server.models.decorate': (
Flecks.decorate(require.context('./models/decorators', false, /\.js$/))
),
'@flecks/web/server.request.socket': () => (req, res, next) => {
if (req.url.startsWith('/projects')) {
req.url = req.url.slice(9);
resources(req, res, next);
return;
}
next();
},
'@flecks/socket.packets.decorate': (
Flecks.decorate(require.context('./packets/decorators', false, /\.js$/))
),
};

View File

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

View File

@ -15,42 +15,48 @@ export default (Action, flecks) => class ProjectAction extends Action {
const {data: {type, payload}} = packet;
switch (type) {
case patchJsonResource.toString(): {
flecks.get('$persea/core.patches').push(payload);
flecks.persea.core.patches.push(payload);
break;
}
case redo.toString(): {
const {project, uri} = payload;
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));
const buffer = await readFile(path);
const json = fromBuffer(buffer, flecks);
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)]);
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();
await writeFile(path, toBuffer(json, flecks));
}
break;
}
case replaceResource.toString(): {
flecks.get('$persea/core.replacements').push(payload);
flecks.persea.core.replacements.push(payload);
break;
}
case undo.toString(): {
const {project, uri} = payload;
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));
const buffer = await readFile(path);
const json = fromBuffer(buffer, flecks);
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)]);
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();
await writeFile(path, toBuffer(json, flecks));
}

View File

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

View File

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

View File

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

View File

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

View File

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