chore: 4.0.0

This commit is contained in:
cha0s 2022-03-16 00:41:32 -05:00
parent d792b50070
commit 85ebf2d33e
46 changed files with 4855 additions and 21152 deletions

5
.gitignore vendored
View File

@ -116,5 +116,6 @@ dist
.pnp.* .pnp.*
# local # local
/build /dev
/projects /dist
/packages/*/yarn.lock

View File

@ -1,6 +0,0 @@
module.exports = {
options: {
root: __dirname,
},
use: [],
};

5
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,5 @@
{
"files.exclude": {
"projects": true
}
}

98
build/flecks.yml Normal file
View File

@ -0,0 +1,98 @@
'@avocado/behavior': {}
'@avocado/behavior-persea': {}
'@avocado/color': {}
'@avocado/entity': {}
'@avocado/entity-persea': {}
'@avocado/graphics': {}
'@avocado/graphics-persea': {}
'@avocado/input': {}
'@avocado/math': {}
'@avocado/math-persea': {}
'@avocado/physics': {}
'@avocado/physics-persea': {}
'@avocado/react': {}
'@avocado/resource': {}
'@avocado/resource-persea':
controllers:
- '@avocado/behavior-persea'
- '@avocado/graphics-persea'
- '@avocado/entity-persea'
- '@avocado/sound-persea'
- '@avocado/timing-persea'
- '@avocado/topdown-persea'
'@avocado/s13n': {}
'@avocado/sound': {}
'@avocado/sound-persea': {}
'@avocado/timing': {}
'@avocado/timing-persea': {}
'@avocado/topdown': {}
'@avocado/topdown-persea': {}
'@avocado/traits': {}
'@avocado/traits-persea': {}
'@humus/combat': {}
'@humus/combat-persea': {}
'@humus/core': {}
'@humus/core-persea': {}
'@flecks/core':
id: 'persea'
'@flecks/db': {}
'@flecks/db/server':
port: 32362
'@flecks/docker': {}
'@flecks/governor': {}
'@flecks/http': {}
'@flecks/http/client':
up:
- '@flecks/socket'
- '@flecks/react'
- '...'
'@flecks/http/server':
devPublic: 'persea.local.cha0s.io'
port: 32360
request.route:
- '@flecks/user/session/server'
- '@flecks/user/server'
- '...'
request.socket:
- '@persea/core/server'
- '...'
stream.html:
- '@flecks/react'
- '...'
'@flecks/react':
providers:
- '@flecks/redux'
- '@flecks/react/router'
- '...'
'@flecks/react/router': {}
'@flecks/redis': {}
'@flecks/redis/server':
port: 32363
'@flecks/redis/session': {}
'@flecks/redux': {}
'@flecks/repl': {}
'@flecks/server':
up:
- '@flecks/docker'
- '@flecks/db'
- '@flecks/redis'
- '@flecks/user/session'
- '@flecks/user'
- '@flecks/user/local'
- '@flecks/governor'
- '...'
- '@persea/bootstrap'
- '@flecks/http'
- '@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': {}
'@persea/bootstrap': {}
'@persea/core': {}

View File

@ -1,6 +0,0 @@
**/*.js
**/*.map
/assets
!/.*
!src/**/*.js
!/test/**/*.js

View File

@ -1,21 +0,0 @@
{
"version": "3.0.0",
"main": "index.js",
"scripts": {
"build": "latus-build",
"clean": "latus-build clean",
"fp": "latus-build forcepublish",
"lint": "latus-build lint",
"test": "latus-build test"
},
"files": [
"index.js",
"index.js.map",
"test.js",
"test.js.map"
],
"dependencies": {},
"devDependencies": {
"@latus/build": "1.x"
}
}

View File

@ -1,5 +0,0 @@
import {expect} from 'chai';
it('exists', () => {
expect(true).to.be.true;
});

View File

@ -1,17 +0,0 @@
version: '2'
services:
redis:
image: redis:6
ports:
- 6380:6379
mysql:
image: mysql:8
command:
- '--default-authentication-plugin=mysql_native_password'
environment:
- MYSQL_DATABASE=db
- MYSQL_ROOT_PASSWORD=UNSAFE_DEV_PASSWORD
ports:
- 32342:3306

109
latus.yml
View File

@ -1,109 +0,0 @@
'@avocado/behavior': {}
'@avocado/behavior-persea': {}
'@avocado/color': {}
'@avocado/entity': {}
'@avocado/entity-persea': {}
'@avocado/graphics': {}
'@avocado/graphics-persea': {}
'@avocado/input': {}
'@avocado/math': {}
'@avocado/math-persea': {}
'@avocado/physics': {}
'@avocado/physics-persea': {}
'@avocado/react': {}
'@avocado/resource': {}
'@avocado/resource-persea': {
'controllers': [
'@avocado/behavior-persea',
'@avocado/graphics-persea',
'@avocado/entity-persea',
'@avocado/sound-persea',
'@avocado/timing-persea',
'@avocado/topdown-persea',
],
}
'@avocado/s13n': {}
'@avocado/sound': {}
'@avocado/sound-persea': {}
'@avocado/timing': {}
'@avocado/timing-persea': {}
'@avocado/topdown': {}
'@avocado/topdown-persea': {}
'@avocado/traits': {}
'@avocado/traits-persea': {}
'@humus/combat': {}
'@humus/combat-persea': {}
'@humus/core': {}
'@humus/core-persea': {}
'@latus/core': {
id: 'persea',
}
'@latus/core/server': {
up: [
'@latus/db/server',
'@latus/redis/server',
'@latus/user/session/server',
'@latus/user/server',
'@latus/user/local/server',
'@latus/http/server',
'@persea/bootstrap/server',
'@latus/repl/server',
],
}
'@latus/db': {}
'@latus/db/server': {
models.decorate: [
'@latus/user/local/server',
'@persea/core/server',
],
docker: 'cached',
}
'@latus/governor': {}
'@latus/http': {
title: 'Persea',
}
'@latus/http/client': {
up: [
'@latus/socket/client',
'@latus/react/client',
],
}
'@latus/http/server': {
devPublic: 'persea.localhost',
request.page: [
'@latus/user/session/server',
'@latus/user/server',
],
request.socket: [
'@persea/core/server',
]
}
'@latus/react': {}
'@latus/redis': {}
'@latus/redis/server': {
docker: 'cached',
}
'@latus/redux': {}
'@latus/redis/session': {}
'@latus/repl': {}
'@latus/socket': {
packets.decorate: [
'@latus/governor/server',
'@persea/core/server',
]
}
'@latus/socket/client': {}
'@latus/socket/server': {
authenticate: [
'@latus/user/session/server',
'@latus/user/server',
],
connect: [
'@latus/socket/server',
],
}
'@latus/user': {}
'@latus/user/local': {}
'@latus/user/session': {}
'@persea/bootstrap': {}
'@persea/core': {}

View File

@ -2,5 +2,5 @@
"packages": [ "packages": [
"packages/*" "packages/*"
], ],
"version": "1.0.0" "version": "4.0.0"
} }

View File

@ -1,37 +0,0 @@
const {execSync} = require('child_process');
const {join} = require('path');
const fs = require('fs-extra')
const cwd = process.cwd();
const [exe, script, package] = process.argv;
const path = join(cwd, 'packages', package);
try {
fs.accessSync(path);
console.error(`Package '${package}' already exists, aborting.`);
process.exit(1);
}
catch (error) {}
const [scope] = require('./package.json').name.split('/');
const name = [scope, package].join('/');
console.log(`Copying new project '${name}' to ${path}...`);
fs.copySync(
join(cwd, 'config/package'),
path,
);
const json = {
name,
...require(join(path, 'package.json')),
};
fs.writeFileSync(
join(path, 'package.json'),
JSON.stringify(json, null, 2),
);
const exec = (cmd) => execSync(cmd, {cwd: path, stdio: 'inherit'});
console.log(`Installing...`);
exec('yarn');
console.log(`Testing...`);
exec('yarn run test');

View File

@ -1,66 +1,73 @@
{ {
"name": "@persea/monorepo", "name": "@persea/monorepo",
"repository": {
"type": "git",
"url": "https://git.hq.cha0s.io/cha0s/persea.git"
},
"version": "4.0.0",
"private": true, "private": true,
"scripts": { "scripts": {
"build": "lerna run build", "build": "FLECKS_ENV_FLECKS_SERVER_start=0 npm run build:only",
"build:docker": "docker build -t docker.hq.cha0s.io/cha0s6983/$(echo $(jq -r .name package.json):$(jq -r .version package.json)) .", "build:only": "flecks build",
"build:lat": "latus-build", "debug": "DEBUG=*,-babel* npm run dev",
"clean": "lerna run clean", "dev": "npm run -- build:only -h",
"docker": "yarn build:lat && docker-compose up --build", "link-all": "yarn link $(for i in $(ls node_modules/@flecks); do echo -n \"@flecks/$i \"; done)",
"electron": "NODE_ENV=production NODE_PATH=./node_modules electron build/electron.js", "postinstall": "patch-package",
"fp": "lerna run fp", "repl": "npx flecks repl --rlwrap",
"http": "LATUS_ONLY_BUILD=http latus-build -d --hot --watch", "start": "DEBUG=@avocado*,@flecks*,@persea*,persea*,-@flecks/core/flecks* npm run dev",
"lint": "lerna run lint", "unlink-all": "yarn unlink $(for i in $(ls node_modules/@flecks); do echo -n \"@flecks/$i \"; done) && yarn install --force",
"package": "node ./package.js", "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)"
"refresh": "yarn run clean && npx lerna exec link-all && yarn run build && yarn run test",
"repl": "rlwrap -C qmp socat STDIO UNIX:$(ls /tmp/latus-*.sock | tail -n 1)",
"server": "LATUS_ONLY_BUILD=server latus-build -d --start-server --inspect --watch",
"start": "NODE_ENV=production NODE_PATH=./node_modules node build/index.js",
"test": "lerna run test --no-bail -- --silent"
}, },
"dependencies": { "dependencies": {
"@avocado/behavior": "^2.0.0", "@avocado/behavior": "^3.0.0",
"@avocado/behavior-persea": "^1.0.0", "@avocado/behavior-persea": "^3.0.0",
"@avocado/color": "^1.0.0", "@avocado/color": "^3.0.0",
"@avocado/core": "^2.0.0", "@avocado/core": "^3.0.0",
"@avocado/entity": "^2.0.0", "@avocado/entity": "^3.0.0",
"@avocado/entity-persea": "^1.0.0", "@avocado/entity-persea": "^3.0.0",
"@avocado/graphics": "^2.0.0", "@avocado/graphics": "^3.0.0",
"@avocado/graphics-persea": "^1.0.0", "@avocado/graphics-persea": "^3.0.0",
"@avocado/input": "^2.0.0", "@avocado/input": "^3.0.0",
"@avocado/math": "^2.0.0", "@avocado/math": "^3.0.0",
"@avocado/math-persea": "^1.0.0", "@avocado/math-persea": "^3.0.0",
"@avocado/physics": "^1.0.0", "@avocado/physics": "^3.0.0",
"@avocado/physics-persea": "^1.0.0", "@avocado/physics-persea": "^3.0.0",
"@avocado/react": "^1.0.0", "@avocado/react": "^3.0.0",
"@avocado/resource": "^2.0.0", "@avocado/resource": "^3.0.0",
"@avocado/resource-persea": "^1.0.0", "@avocado/resource-persea": "^3.0.0",
"@avocado/s13n": "^2.0.0", "@avocado/s13n": "^3.0.0",
"@avocado/sound": "^1.0.0", "@avocado/sound": "^3.0.0",
"@avocado/sound-persea": "^1.0.0", "@avocado/sound-persea": "^3.0.0",
"@avocado/timing": "^2.0.0", "@avocado/timing": "^3.0.0",
"@avocado/timing-persea": "^1.0.0", "@avocado/timing-persea": "^3.0.0",
"@avocado/topdown": "^2.0.0", "@avocado/topdown": "^3.0.0",
"@avocado/topdown-persea": "^1.0.0", "@avocado/topdown-persea": "^3.0.0",
"@avocado/traits": "^2.0.0", "@avocado/traits": "^3.0.0",
"@avocado/traits-persea": "^1.0.0", "@avocado/traits-persea": "^3.0.0",
"@humus/combat": "^1.0.0", "@flecks/core": "^1.3.0",
"@humus/core": "^1.0.0", "@flecks/create-app": "^1.3.0",
"@latus/core": "^2.0.0", "@flecks/db": "^1.3.0",
"@latus/db": "^2.0.0", "@flecks/governor": "^1.3.0",
"@latus/governor": "^2.0.0", "@flecks/http": "^1.3.0",
"@latus/http": "^2.0.0", "@flecks/react": "^1.3.0",
"@latus/react": "^2.0.0", "@flecks/redis": "^1.3.0",
"@latus/redis": "^2.0.0", "@flecks/redux": "^1.3.0",
"@latus/redux": "^2.0.0", "@flecks/repl": "^1.3.0",
"@latus/repl": "^2.0.0", "@flecks/server": "^1.3.0",
"@latus/socket": "^2.0.0", "@flecks/socket": "^1.3.0",
"@latus/user": "^2.0.0", "@flecks/user": "^1.3.0",
"@persea/bootstrap": "^3.0.0", "@humus/combat": "^2.0.0",
"@persea/core": "^3.0.0" "@humus/core": "^2.0.0",
"@persea/bootstrap": "^4.0.0",
"@persea/core": "^4.0.0",
"pg": "^8.7.3",
"pg-hstore": "^2.3.4"
}, },
"devDependencies": { "devDependencies": {
"@latus/build": "1.x", "@flecks/create-fleck": "^1.3.0",
"lerna": "^3.22.1" "@flecks/docker": "^1.3.0",
"lerna": "^3.22.1",
"patch-package": "^6.4.7",
"postinstall-postinstall": "^2.1.0"
} }
} }

View File

@ -1,6 +1,116 @@
**/*.js # Logs
**/*.map logs
/assets *.log
!/.* npm-debug.log*
!src/**/*.js yarn-debug.log*
!/test/**/*.js yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

View File

@ -1,24 +1,31 @@
{ {
"name": "@persea/bootstrap", "name": "@persea/bootstrap",
"version": "3.0.0", "version": "4.0.0",
"main": "index.js", "repository": {
"type": "git",
"url": "https://git.hq.cha0s.io/cha0s/persea.git",
"directory": "packages/bootstrap"
},
"scripts": { "scripts": {
"build": "latus-build", "build": "flecks build",
"clean": "latus-build clean", "clean": "flecks clean",
"fp": "latus-build forcepublish", "lint": "flecks lint",
"lint": "latus-build lint", "postversion": "cp package.json dist",
"test": "latus-build test" "test": "flecks test"
}, },
"files": [ "files": [
"index.js", "build",
"index.js.map",
"server.js", "server.js",
"server.js.map", "server.js.map",
"src",
"test",
"test.js", "test.js",
"test.js.map" "test.js.map"
], ],
"dependencies": {}, "dependencies": {
"@flecks/core": "^1.3.0"
},
"devDependencies": { "devDependencies": {
"@latus/build": "1.x" "@flecks/fleck": "^1.3.0"
} }
} }

View File

@ -1,11 +1,16 @@
import {Hooks} from '@flecks/core';
const {
NODE_ENV,
} = process.env;
export default { export default {
hooks: { [Hooks]: {
'@latus/core/server/up': async (latus) => { '@flecks/server.up': async (flecks) => {
// eslint-disable-next-line no-eval if ('production' === NODE_ENV) {
if ('production' === eval('process.env.NODE_ENV')) {
return; return;
} }
const {Project, User} = latus.get('%models'); const {Project, User} = flecks.get('$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',

View File

@ -1,5 +0,0 @@
import {expect} from 'chai';
it('exists', () => {
expect(true).to.be.true;
});

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,116 @@
**/*.js # Logs
**/*.map logs
/assets *.log
!/.* npm-debug.log*
!src/**/*.js yarn-debug.log*
!/test/**/*.js yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*

View File

@ -0,0 +1,6 @@
'@flecks/core': {}
'@flecks/fleck': {}
'@flecks/http': {}
'@flecks/http/server':
build: false
'@flecks/react': {}

View File

@ -1,51 +1,53 @@
{ {
"name": "@persea/core", "name": "@persea/core",
"version": "3.0.0", "version": "4.0.0",
"repository": {
"type": "git",
"url": "https://git.hq.cha0s.io/cha0s/persea.git",
"directory": "packages/core"
},
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"build": "latus-build", "build": "flecks build",
"clean": "latus-build clean", "clean": "flecks clean",
"fp": "latus-build forcepublish", "lint": "flecks lint",
"lint": "latus-build lint", "postversion": "cp package.json dist",
"test": "latus-build test" "test": "flecks test"
}, },
"files": [ "files": [
"build",
"client.js", "client.js",
"client.js.map", "client.js.map",
"index.js", "index.js",
"index.js.map", "index.js.map",
"server.js", "server.js",
"server.js.map", "server.js.map",
"src",
"test",
"test.js", "test.js",
"test.js.map" "test.js.map"
], ],
"dependencies": { "dependencies": {
"@avocado/graphics": "^2.0.0", "@avocado/graphics": "^3.0.0",
"@avocado/math": "^2.0.0", "@avocado/math": "^3.0.0",
"@avocado/react": "^1.0.0", "@avocado/react": "^3.0.0",
"@avocado/resource": "^2.0.0", "@avocado/resource": "^3.0.0",
"@avocado/resource-persea": "^1.0.0", "@avocado/resource-persea": "^3.0.0",
"@latus/core": "^2.0.0", "@flecks/core": "^1.3.0",
"@latus/db": "^2.0.0", "@flecks/db": "^1.3.0",
"@latus/react": "^2.0.0", "@flecks/react": "^1.3.0",
"@latus/redux": "^2.0.0", "@flecks/redux": "^1.3.0",
"@latus/user": "^2.0.0", "@flecks/user": "^1.3.0",
"connected-react-router": "^6.9.1",
"deepmerge": "^4.2.2",
"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", "glob": "^7.1.6",
"history": "^4.10.0",
"import": "^0.0.6",
"lodash.flatten": "^4.4.0",
"natsort": "^2.0.2", "natsort": "^2.0.2",
"rc-slider": "^9.7.1",
"react-hex-editor": "^0.3.0", "react-hex-editor": "^0.3.0",
"react-modal": "^3.12.1", "react-modal": "^3.12.1",
"react-ui-tree": "^4.0.0", "react-ui-tree": "^4.0.0"
"swipe-touch-events": "^1.0.2"
}, },
"devDependencies": { "devDependencies": {
"@latus/build": "1.x" "@flecks/fleck": "^1.3.0",
"@flecks/http": "^1.3.0"
} }
} }

View File

@ -1,16 +1,9 @@
import {connectRouter, routerMiddleware} from 'connected-react-router'; import {Hooks} from '@flecks/core';
import Persea from './components/persea'; import Persea from './components/persea';
import history from './components/persea/history';
export default { export default {
hooks: { [Hooks]: {
'@latus/react/components': () => Persea, '@flecks/react.roots': () => Persea,
'@latus/redux/slices': () => ({
router: connectRouter(history),
}),
'@latus/redux/store': (options) => {
options.middleware.push(routerMiddleware(history));
},
}, },
}; };

View File

@ -1,7 +1,7 @@
import './index.scss'; import './index.scss';
import {React} from '@latus/react'; import {React} from '@flecks/react';
import {useSelector} from '@latus/redux'; import {useSelector} from '@flecks/redux';
import {projectsSelector} from '../../state/projects'; import {projectsSelector} from '../../state/projects';
import ProjectItem from './project-item'; import ProjectItem from './project-item';

View File

@ -1,10 +1,10 @@
import './index.scss'; import './index.scss';
import { import {
Link,
PropTypes, PropTypes,
React, React,
} from '@latus/react'; } from '@flecks/react';
import {Link} from '@flecks/react/router';
import {propTypes as projectPropTypes} from '../../project'; import {propTypes as projectPropTypes} from '../../project';

View File

@ -1,3 +0,0 @@
import {createBrowserHistory} from 'history';
export default createBrowserHistory();

View File

@ -3,39 +3,34 @@ import './index.scss';
import { import {
React, React,
hot, hot,
Redirect, } from '@flecks/react';
import {
Navigate,
Route, Route,
Switch, Routes,
} from '@latus/react'; } from '@flecks/react/router';
import Login from '@latus/user/client/components/login'; import {useSelector} from '@flecks/redux';
import {useSelector} from '@latus/redux'; import {userIdSelector} from '@flecks/user';
import {ConnectedRouter} from 'connected-react-router'; import {UserLocalLogin} from '@flecks/user/local/client';
import {userIdSelector} from '../../state/user';
import Dashboard from '../dashboard'; import Dashboard from '../dashboard';
import ProjectRoute from '../project/route'; import ProjectRoute from '../project/route';
import history from './history';
const Persea = React.memo(() => { // eslint-disable-next-line arrow-body-style
const Persea = () => {
const isLoggedIn = useSelector(userIdSelector); const isLoggedIn = useSelector(userIdSelector);
return ( return (
<div className="persea"> <div className="persea">
<ConnectedRouter history={history}> <Routes>
<Switch> {!isLoggedIn && (<Navigate to="/login" />)}
<Route path="/login"> <Route exact path="/" element={<Navigate to="/dashboard" />} />
{isLoggedIn ? <Redirect to="/" /> : Login} <Route path="/login" element={isLoggedIn ? <Navigate to="/" /> : <UserLocalLogin />} />
</Route> <Route path="/dashboard" element={<Dashboard />} />
<Route path="/dashboard" component={Dashboard} /> <Route path="/project/*" element={<ProjectRoute />} />
<Route path="/project/:uuid:uri(/*)?" component={ProjectRoute} /> </Routes>
</Switch>
<Route exact path="/">
<Redirect to="/dashboard" />
</Route>
{!isLoggedIn && <Redirect to="/login" />}
</ConnectedRouter>
</div> </div>
); );
}); };
Persea.displayName = 'Persea'; Persea.displayName = 'Persea';

View File

@ -1,24 +1,28 @@
import { import {
classnames, classnames,
hot,
React, React,
} from '@latus/react'; } from '@flecks/react';
import {locals} from './index.module.scss'; import {
bottom,
buttons as buttonsClass,
organization,
resource,
} from './index.module.scss';
function Bottom() { function Bottom() {
const buttons = [ const buttons = [
<button className={classnames(locals.organization)} type="button"> <button className={classnames(organization)} type="button">
<svg height="512pt" viewBox="0 0 512 512" width="512pt" xmlns="http://www.w3.org/2000/svg"> <svg height="512pt" viewBox="0 0 512 512" width="512pt" xmlns="http://www.w3.org/2000/svg">
<path d="m512 312v-160h-230v62h-152v-54h100v-160h-230v160h90v294h192v58h230v-160h-230v62h-152v-160h152v58zm-472-272h150v80h-150zm282 352h150v80h-150zm0-200h150v80h-150zm0 0" /> <path d="m512 312v-160h-230v62h-152v-54h100v-160h-230v160h90v294h192v58h230v-160h-230v62h-152v-160h152v58zm-472-272h150v80h-150zm282 352h150v80h-150zm0-200h150v80h-150zm0 0" />
</svg> </svg>
</button>, </button>,
// eslint-disable-next-line jsx-a11y/control-has-associated-label // eslint-disable-next-line jsx-a11y/control-has-associated-label
<button className={classnames(locals.resource, 'active')} type="button" />, <button className={classnames(resource, 'active')} type="button" />,
]; ];
return ( return (
<div className={locals.bottom}> <div className={bottom}>
<div className={locals.buttons}> <div className={buttonsClass}>
{buttons} {buttons}
</div> </div>
</div> </div>
@ -31,4 +35,4 @@ Bottom.displayName = 'Bottom';
Bottom.propTypes = {}; Bottom.propTypes = {};
export default hot(module)(Bottom); export default Bottom;

View File

@ -1,20 +1,20 @@
import {
IconPages,
} from '@avocado/react';
import { import {
useResourceController, useResourceController,
} from '@avocado/resource-persea'; } from '@avocado/resource-persea';
import { import {
classnames, classnames,
hot,
IconPages,
PropTypes, PropTypes,
React, React,
Route,
useParams,
useRef, useRef,
useState, useState,
} from '@latus/react'; } from '@flecks/react';
import {useParams} from '@flecks/react/router';
import { import {
useSelector, useSelector,
} from '@latus/redux'; } from '@flecks/redux';
import {structureSelector} from '../../state/projects'; import {structureSelector} from '../../state/projects';
import ResourceRoute from '../resource/route'; import ResourceRoute from '../resource/route';
@ -23,7 +23,10 @@ import Organization from './organization';
import {locals} from './index.module.scss'; import {locals} from './index.module.scss';
function Project({uuid}) { function Project({uuid}) {
const {uri} = useParams(); const {'*': reactRouterV6IsStupid} = useParams();
const [, ...uriParts] = reactRouterV6IsStupid.split('/');
const uri = `/${uriParts.join('/')}`;
useParams().uri = uri;
const [currentPageIndex, setCurrentPageIndex] = useState(0); const [currentPageIndex, setCurrentPageIndex] = useState(0);
const ref = useRef(); const ref = useRef();
const {label, resourcePaths} = useSelector((state) => structureSelector(state, uuid)); const {label, resourcePaths} = useSelector((state) => structureSelector(state, uuid));
@ -50,9 +53,10 @@ function Project({uuid}) {
<div className={classnames(locals.resource, className)} /> <div className={classnames(locals.resource, className)} />
), ),
Page: ( Page: (
<Route path="/project/:uuid:uri(/*)" component={ResourceRoute} /> <ResourceRoute uri={uri} uuid={uuid} />
), ),
}); });
console.log(iconPages);
return ( return (
<div className={locals.project} ref={ref}> <div className={locals.project} ref={ref}>
<IconPages <IconPages
@ -67,6 +71,7 @@ function Project({uuid}) {
export const propTypes = PropTypes.shape({ export const propTypes = PropTypes.shape({
label: PropTypes.string.isRequired, label: PropTypes.string.isRequired,
// eslint-disable-next-line react/forbid-prop-types
resourcePaths: PropTypes.arrayOf(PropTypes.any).isRequired, resourcePaths: PropTypes.arrayOf(PropTypes.any).isRequired,
}); });
@ -76,4 +81,4 @@ Project.propTypes = {
uuid: PropTypes.string.isRequired, uuid: PropTypes.string.isRequired,
}; };
export default hot(module)(Project); export default Project;

View File

@ -1,4 +1,4 @@
import {PropTypes, React} from '@latus/react'; import {PropTypes, React} from '@flecks/react';
const OrganizationActions = ({ const OrganizationActions = ({
collapseAll, collapseAll,

View File

@ -5,13 +5,17 @@ import {
classnames, classnames,
PropTypes, PropTypes,
React, React,
useHistory, useFlecks,
useLatus,
useLocation,
useState, useState,
} from '@latus/react'; } from '@flecks/react';
import {createNextState} from '@latus/redux'; import {
import 'swipe-touch-events'; push,
useLocation,
} from '@flecks/react/router';
import {
createNextState,
useDispatch,
} from '@flecks/redux';
import OrganizationActions from './actions'; import OrganizationActions from './actions';
import './index.scss'; import './index.scss';
@ -22,8 +26,8 @@ const Organization = ({
resourcePaths, resourcePaths,
uuid, uuid,
}) => { }) => {
const history = useHistory(); const dispatch = useDispatch();
const latus = useLatus(); const flecks = useFlecks();
const location = useLocation(); const location = useLocation();
const [collapsed, __setCollapsed] = useState(JSON.parse(window.localStorage['@persea/core/explorer'] || '{}')); const [collapsed, __setCollapsed] = useState(JSON.parse(window.localStorage['@persea/core/explorer'] || '{}'));
const setCollapsed = (next) => { const setCollapsed = (next) => {
@ -66,7 +70,7 @@ const Organization = ({
activate={({value, nodes}) => { activate={({value, nodes}) => {
const path = join('/project', value); const path = join('/project', value);
if (!nodes) { if (!nodes) {
history.push(path); dispatch(push(path));
} }
else { else {
const next = createNextState(collapsed, (draft) => { const next = createNextState(collapsed, (draft) => {
@ -90,8 +94,8 @@ const Organization = ({
label={label} label={label}
nodes={nodesFromResourcePaths(label, uuid, resourcePaths)} nodes={nodesFromResourcePaths(label, uuid, resourcePaths)}
renderLabel={({label, nodes, value}) => { renderLabel={({label, nodes, value}) => {
const {displayName} = latus const {displayName} = flecks
.get('%resource-controllers') .get('$avocado/resource-persea.controllers')
.find(({matcher}) => value.match(matcher)) .find(({matcher}) => value.match(matcher))
.Component; .Component;
return ( return (
@ -120,8 +124,9 @@ Organization.defaultProps = {
}; };
Organization.propTypes = { Organization.propTypes = {
className: PropTypes.string.isRequired, className: PropTypes.string,
label: PropTypes.string.isRequired, label: PropTypes.string.isRequired,
// eslint-disable-next-line react/forbid-prop-types
resourcePaths: PropTypes.arrayOf(PropTypes.any).isRequired, resourcePaths: PropTypes.arrayOf(PropTypes.any).isRequired,
uuid: PropTypes.string.isRequired, uuid: PropTypes.string.isRequired,
}; };

View File

@ -3,23 +3,20 @@ import './index.scss';
import {join} from 'path'; import {join} from 'path';
import {Resource} from '@avocado/resource'; import {Resource} from '@avocado/resource';
import {PropTypes, React} from '@latus/react'; import {React} from '@flecks/react';
import {useParams} from '@flecks/react/router';
import Project from '../index'; import Project from '../index';
const ProjectRoute = ({match: {params: {uuid}}}) => { const ProjectRoute = () => {
const {'*': reactRouterV6IsStupid} = useParams();
const [uuid] = reactRouterV6IsStupid.split('/');
Resource.root = join('/projects', uuid); Resource.root = join('/projects', uuid);
return <Project uuid={uuid} />; return <Project uuid={uuid} />;
}; };
ProjectRoute.displayName = 'ProjectRoute'; ProjectRoute.displayName = 'ProjectRoute';
ProjectRoute.propTypes = { ProjectRoute.propTypes = {};
match: PropTypes.shape({
params: PropTypes.shape({
uuid: PropTypes.string,
}),
}).isRequired,
};
export default ProjectRoute; export default ProjectRoute;

View File

@ -1,36 +1,32 @@
import './index.scss'; import './index.scss';
import {Resource} from '@avocado/resource-persea'; import {Resource} from '@avocado/resource-persea';
import {PropTypes, React} from '@latus/react'; import {PropTypes, React} from '@flecks/react';
import { import {
useDispatch, useDispatch,
useSelector, useSelector,
} from '@latus/redux'; } from '@flecks/redux';
import { import {
fetchProjectResource, fetchProjectResource,
resourceSelector, resourceSelector,
} from '../../../state/projects'; } from '../../../state/projects';
const ResourceRoute = ({match: {params: {uri, uuid}}}) => { const ResourceRoute = ({uri, uuid}) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const resource = useSelector((state) => resourceSelector(state, uuid, uri)); const resource = useSelector((state) => resourceSelector(state, uuid, uri));
if (!resource) { if (!resource) {
dispatch(fetchProjectResource({uri, uuid})); dispatch(fetchProjectResource({uri, uuid}));
return null; return null;
} }
console.log({resource});
return <Resource resource={resource} />; return <Resource resource={resource} />;
}; };
ResourceRoute.displayName = 'ResourceRoute'; ResourceRoute.displayName = 'ResourceRoute';
ResourceRoute.propTypes = { ResourceRoute.propTypes = {
match: PropTypes.shape({ uri: PropTypes.string.isRequired,
params: PropTypes.shape({ uuid: PropTypes.string.isRequired,
uri: PropTypes.string,
uuid: PropTypes.string,
}),
}).isRequired,
}; };
export default ResourceRoute; export default ResourceRoute;

View File

@ -1,22 +1,22 @@
import {patchJsonResource} from '@avocado/resource-persea'; import {patchJsonResource} from '@avocado/resource-persea';
import {Hooks} from '@flecks/core';
import {projects, user} from './state'; import {projects} from './state';
export * from './state'; export * from './state';
export default { export default {
hooks: { [Hooks]: {
'@latus/redux/effects': (latus) => { '@flecks/redux.effects': (flecks) => {
const withSocket = (fn) => (...args) => fn(...args.concat(latus.get('%socket'))); const withSocket = (fn) => (...args) => fn(...args.concat(flecks.get('$flecks/socket.socket')));
return { return {
[patchJsonResource]: withSocket((store, action, socket) => { [patchJsonResource]: withSocket((store, action, socket) => {
socket.send(['Action', action]); socket.send(['Action', action]);
}), }),
}; };
}, },
'@latus/redux/slices': () => ({ '@flecks/redux.slices': () => ({
projects, projects,
user,
}), }),
}, },
}; };

View File

@ -1,64 +1,23 @@
import fs from 'fs';
import {join} from 'path'; import {join} from 'path';
import {promisify} from 'util';
import {decorateWithLatus, gatherWithLatus} from '@latus/core'; import {Flecks, Hooks} from '@flecks/core';
import express from 'express'; import express from 'express';
import {applyPatch} from 'fast-json-patch';
import projectsState from './state/projects'; import startFlush from './start-flush';
const readFile = promisify(fs.readFile);
const writeFile = promisify(fs.writeFile);
const resources = express.static(join(process.cwd(), 'projects')); const resources = express.static(join(process.cwd(), 'projects'));
export default { export default {
hooks: { [Hooks]: {
'@latus/core/starting': (latus) => { '@flecks/core.starting': (flecks) => {
latus.set('%patches', []); flecks.set('$persea/core.patches', []);
const flushPatches = async () => { startFlush(flecks);
const patches = latus.get('%patches');
if (patches.length > 0) {
const patching = {};
while (patches.length > 0) {
const {patch, project, uri} = patches.shift();
const path = join(process.cwd(), 'projects', project, uri);
if (!patching[path]) {
const {toBuffer, fromBuffer} = latus.get('%resource-controllers')
.find(({matcher}) => uri.match(matcher));
patching[path] = new Promise((resolve) => {
readFile(path).then((buffer) => {
resolve({
toBuffer,
json: fromBuffer(buffer, latus),
});
});
});
}
// 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 {toBuffer, json} = await promise;
return writeFile(path, toBuffer(json, latus));
}),
);
}
setTimeout(flushPatches, 0);
};
setTimeout(flushPatches, 0);
}, },
'@latus/db/server/models': gatherWithLatus( '@flecks/db/server.models': Flecks.provide(require.context('./models', false, /\.js$/)),
require.context('./models', false, /\.js$/), '@flecks/db/server.models.decorate': (
Flecks.decorate(require.context('./models/decorators', false, /\.js$/))
), ),
'@latus/db/server/models.decorate': decorateWithLatus( '@flecks/http/server.request.socket': () => (req, res, next) => {
require.context('./models/decorators', false, /\.js$/),
),
'@latus/http/server/request.socket': () => (req, res, next) => {
if (req.url.startsWith('/projects')) { if (req.url.startsWith('/projects')) {
resources(req, res, next); resources(req, res, next);
return; return;
@ -68,21 +27,8 @@ export default {
} }
next(); next();
}, },
'@latus/redux/defaultState': async (req, latus) => ({ '@flecks/socket.packets.decorate': (
projects: await projectsState( Flecks.decorate(require.context('./packets/decorators', false, /\.js$/))
req
? await req.user.projectsResourcePaths()
: {},
latus,
),
user: {
id: req
? req.user.id
: 0,
},
}),
'@latus/socket/packets.decorate': decorateWithLatus(
require.context('./packets/decorators', false, /\.js$/),
), ),
}, },
}; };

View File

@ -2,7 +2,7 @@ import fs from 'fs';
import {join} from 'path'; import {join} from 'path';
import {promisify} from 'util'; import {promisify} from 'util';
import {Model, Sequelize, Types} from '@latus/db/server'; import {Model, Sequelize, Types} from '@flecks/db/server';
import natsort from 'natsort'; import natsort from 'natsort';
import G from 'glob'; import G from 'glob';

View File

@ -1,12 +1,12 @@
import {patchJsonResource} from '@avocado/resource-persea'; import {patchJsonResource} from '@avocado/resource-persea';
export default (Action, latus) => class ProjectAction extends Action { export default (Action, flecks) => class ProjectAction extends Action {
static async respond(packet, socket) { static async respond(packet, socket) {
const {data: {type, payload}} = packet; const {data: {type, payload}} = packet;
switch (type) { switch (type) {
case patchJsonResource.toString(): { case patchJsonResource.toString(): {
latus.get('%patches').push(payload); flecks.get('$persea/core.patches').push(payload);
break; break;
} }
default: default:

View File

@ -0,0 +1,47 @@
import fs from 'fs';
import {join} from 'path';
import {promisify} from 'util';
import {applyPatch} from 'fast-json-patch';
const readFile = promisify(fs.readFile);
const writeFile = promisify(fs.writeFile);
const startFlush = (flecks) => {
const flushPatches = async () => {
const patches = flecks.get('$persea/core.patches');
if (patches.length > 0) {
const patching = {};
while (patches.length > 0) {
const {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({
toBuffer,
json: fromBuffer(buffer, flecks),
});
});
});
}
// 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 {toBuffer, json} = await promise;
return writeFile(path, toBuffer(json, flecks));
}),
);
}
setTimeout(flushPatches, 0);
};
setTimeout(flushPatches, 0);
};
export default startFlush;

View File

@ -1,37 +0,0 @@
import fs from 'fs';
import {join} from 'path';
import {promisify} from 'util';
const readFile = promisify(fs.readFile).bind(fs);
const projectsStructure = async (projectsResourcePaths) => (
Object.fromEntries(
await Promise.all(
Object.entries(projectsResourcePaths)
.map(async ([uuid, resourcePaths]) => {
let label;
try {
const buffer = await readFile(join(process.cwd(), 'projects', `${uuid}.json`));
const config = JSON.parse(buffer.toString());
label = config.name;
}
catch (error) {
label = uuid;
}
return [
uuid,
{
label,
resourcePaths,
},
];
}),
),
)
);
export default async (projectsResourcePaths) => ({
pending: {},
structure: await projectsStructure(projectsResourcePaths),
resources: {},
});

View File

@ -1,4 +1,2 @@
export * from './projects'; export * from './projects';
export {default as projects} from './projects'; export {default as projects} from './projects';
export * from './user';
export {default as user} from './user';

View File

@ -3,18 +3,21 @@ import {
createAsyncThunk, createAsyncThunk,
createSelector, createSelector,
createSlice, createSlice,
} from '@latus/redux'; hydrateServer,
} from '@flecks/redux';
const HydrateServer = Symbol.for('$persea/core.projectsStructure');
export const projectsSelector = (state) => state.projects; export const projectsSelector = (state) => state.projects;
export const fetchProjectResource = createAsyncThunk( export const fetchProjectResource = createAsyncThunk(
'persea/projects/fetchResource', 'persea/projects/fetchResource',
async ({uri}, {extra: latus}) => { async ({uri}, {extra: flecks}) => {
const buffer = await Resource.read(uri); const buffer = await Resource.read(uri);
const {fromBuffer} = latus.get('%resource-controllers') const {fromBuffer} = flecks.get('$avocado/resource-persea.controllers')
.find(({matcher}) => uri.match(matcher)); .find(({matcher}) => uri.match(matcher));
try { try {
return fromBuffer(Buffer.from(buffer), latus); return fromBuffer(Buffer.from(buffer), flecks);
} }
catch (error) { catch (error) {
throw new Error(`Encoding ${uri}: ${error.stack}`); throw new Error(`Encoding ${uri}: ${error.stack}`);
@ -46,16 +49,20 @@ const slice = createSlice({
resources: {}, resources: {},
}, },
/* eslint-disable no-param-reassign */ /* eslint-disable no-param-reassign */
extraReducers: { extraReducers: (builder) => {
[fetchProjectResource.pending]: ({pending}, action) => { builder.addCase(hydrateServer, (state, action) => {
const {req} = action.payload;
state.structure = req[HydrateServer];
});
builder.addCase(fetchProjectResource.pending, ({pending}, action) => {
const {uri} = action.meta.arg; const {uri} = action.meta.arg;
pending[uri] = true; pending[uri] = true;
}, });
[fetchProjectResource.fulfilled]: ({pending, resources}, action) => { builder.addCase(fetchProjectResource.fulfilled, ({pending, resources}, action) => {
const {uri, uuid} = action.meta.arg; const {uri, uuid} = action.meta.arg;
delete pending[uri]; delete pending[uri];
resources[`${uuid}${uri}`] = action.payload; resources[`${uuid}${uri}`] = action.payload;
}, });
}, },
reducers: { reducers: {
// createProject: ({projects}, {payload: {label, resourcePaths, uuid}}) => { // createProject: ({projects}, {payload: {label, resourcePaths, uuid}}) => {
@ -82,7 +89,35 @@ const slice = createSlice({
/* eslint-enable no-param-reassign */ /* eslint-enable no-param-reassign */
}); });
slice.reducer.storage = slice.reducer; slice.reducer.hydrateServer = async (req) => {
const fs = __non_webpack_require__('fs');
const {join} = __non_webpack_require__('path');
const {promisify} = __non_webpack_require__('util');
const readFile = promisify(fs.readFile).bind(fs);
req[HydrateServer] = Object.fromEntries(
await Promise.all(
Object.entries(await req.user.projectsResourcePaths())
.map(async ([uuid, resourcePaths]) => {
let label;
try {
const buffer = await readFile(join(process.cwd(), 'projects', `${uuid}.json`));
const config = JSON.parse(buffer.toString());
label = config.name;
}
catch (error) {
label = uuid;
}
return [
uuid,
{
label,
resourcePaths,
},
];
}),
),
);
};
// export const { // export const {
// createProject, // createProject,

View File

@ -1,25 +0,0 @@
import {
createSlice,
} from '@latus/redux';
export const userSelector = ({user}) => user;
export const userIdSelector = ({user}) => user.id;
const slice = createSlice({
name: 'persea/user',
initialState: {
id: 0,
},
/* eslint-disable no-param-reassign */
reducers: {
},
extraReducers: {
},
/* eslint-enable no-param-reassign */
});
// export const {
// } = slice.actions;
export default slice.reducer;

View File

@ -1,5 +0,0 @@
import {expect} from 'chai';
it('exists', () => {
expect(true).to.be.true;
});

File diff suppressed because it is too large Load Diff

View File

@ -1 +0,0 @@
module.exports = require('@latus/build/build/app.webpack.config');

8128
yarn.lock

File diff suppressed because it is too large Load Diff