unistore sucks i think

This commit is contained in:
ntr committed 2022-08-01 18:29:23 +10:00
1 parent baeaead650
commit 02aadcf2db
21 files changed
+4467 -1353

No files matched your search

+4197 -1207
View File
File diff suppressed because it is too large. Load diff
+6 -2
View File
@@ -21,16 +21,20 @@
"dependencies": { "dependencies": {
"preact": "^10.10.0", "preact": "^10.10.0",
"preact-render-to-string": "^5.2.1", "preact-render-to-string": "^5.2.1",
"preact-router": "^3.2.1" "preact-router": "^3.2.1",
"redux": "^4.2.0",
"unistore": "^3.5.2"
}, },
"devDependencies": { "devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.30.6", "@typescript-eslint/eslint-plugin": "^5.30.6",
"@typescript-eslint/parser": "^5.30.6", "@typescript-eslint/parser": "^5.30.6",
"eslint": "^8.20.0", "eslint": "^8.20.0",
"eslint-config-preact": "^1.3.0", "eslint-config-preact": "^1.3.0",
"eslint-plugin-jest": "^26.7.0",
"jest": "^28.1.3",
"less": "^4.1.3", "less": "^4.1.3",
"less-loader": "^7.3.0", "less-loader": "^7.3.0",
"preact-cli": "^3.4.0", "preact-cli": "^3.4.1",
"typescript": "^4.5.2" "typescript": "^4.5.2"
} }
} }
+10
View File
@@ -0,0 +1,10 @@
import axios from 'axios';
const actions = store => ({
getBundles: async () => {
const { data: bundles } = await axios.get('http://localhost:41337/bundles');
return { bundles };
},
});
export default actions;
+30
View File
@@ -0,0 +1,30 @@
import { h } from 'preact';
import { Route, Router } from 'preact-router';
import { Provider } from 'unistore/preact'
import mcratesStore from './store';
import actions from './actions';
import Header from './components/header';
import Home from './routes/home';
import Profile from './routes/profile';
const store = mcratesStore();
console.log(Home);
const App = () => (
<Provider store={store}>
<div id="app">
<Header />
<Router>
<Route path="/" component={Home} />
<Route path="/profile/" component={Profile} user="me" />
<Route path="/profile/:user" component={Profile} />
</Router>
</div>
</Provider>
);
export default App;
-21
View File
@@ -1,21 +0,0 @@
import { h } from 'preact';
import { Route, Router } from 'preact-router';
import Header from './header';
// Code-splitting is automated for `routes` directory
import Home from '../routes/home';
import Profile from '../routes/profile';
const App = () => (
<div id="app">
<Header />
<Router>
<Route path="/" component={Home} />
<Route path="/profile/" component={Profile} user="me" />
<Route path="/profile/:user" component={Profile} />
</Router>
</div>
);
export default App;
+15
View File
@@ -0,0 +1,15 @@
import { h } from 'preact';
import { Link } from 'preact-router/match';
const Header = () => (
<header class={'header'}>
<h1>Mates Crates</h1>
<nav>
<Link activeClassName={'active'} href="/">Home</Link>
<Link activeClassName={'active'} href="/profile">Me</Link>
<Link activeClassName={'active'} href="/profile/john">John</Link>
</nav>
</header>
);
export default Header;
-16
View File
@@ -1,16 +0,0 @@
import { h } from 'preact';
import { Link } from 'preact-router/match';
import style from './style.less';
const Header = () => (
<header class={style.header}>
<h1>Mates Crates</h1>
<nav>
<Link activeClassName={style.active} href="/">Home</Link>
<Link activeClassName={style.active} href="/profile">Me</Link>
<Link activeClassName={style.active} href="/profile/john">John</Link>
</nav>
</header>
);
export default Header;
-48
View File
@@ -1,48 +0,0 @@
.header {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 56px;
padding: 0;
background: #673AB7;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
z-index: 50;
}
.header h1 {
float: left;
margin: 0;
padding: 0 15px;
font-size: 24px;
line-height: 56px;
font-weight: 400;
color: #FFF;
}
.header nav {
float: right;
font-size: 100%;
}
.header nav a {
display: inline-block;
height: 56px;
line-height: 56px;
padding: 0 15px;
min-width: 50px;
text-align: center;
background: rgba(255,255,255,0);
text-decoration: none;
color: #FFF;
will-change: background-color;
}
.header nav a:hover,
.header nav a:active {
background: rgba(0,0,0,0.2);
}
.header nav a.active {
background: rgba(0,0,0,0.4);
}
+1 -1
View File
@@ -1,4 +1,4 @@
import './style/index.less'; import './style/index.less';
import App from './components/app'; import App from './app';
export default App; export default App;
+24
View File
@@ -0,0 +1,24 @@
import { h } from 'preact';
import { connect } from 'unistore/preact'
import actions from './../actions';
function Home({ bundles, getBundles }) {
if (!bundles.length) {
getBundles();
return (
<div class={'home'}>
loading...
</div>
);
}
return (
<div class={'home'}>
{JSON.stringify(bundles)}
</div>
);
}
export default connect('bundles', actions)(Home);
-11
View File
@@ -1,11 +0,0 @@
import { h } from 'preact';
import style from './style.less';
const Home = () => (
<div class={style.home}>
<h1>Home</h1>
<p>This is the Home component.</p>
</div>
);
export default Home;
-5
View File
@@ -1,5 +0,0 @@
.home {
padding: 56px 20px;
min-height: 100%;
width: 100%;
}
@@ -6,7 +6,6 @@ interface Props {
user: string; user: string;
} }
// Note: `user` comes from the URL, courtesy of our router
const Profile = ({ user }: Props) => { const Profile = ({ user }: Props) => {
const [time, setTime] = useState<number>(Date.now()); const [time, setTime] = useState<number>(Date.now());
const [count, setCount] = useState<number>(0); const [count, setCount] = useState<number>(0);
@@ -18,7 +17,7 @@ const Profile = ({ user }: Props) => {
}, []); }, []);
return ( return (
<div class={style.profile}> <div class={'profile'}>
<h1>Profile: {user}</h1> <h1>Profile: {user}</h1>
<p>This is the user profile for a user named { user }.</p> <p>This is the user profile for a user named { user }.</p>
-5
View File
@@ -1,5 +0,0 @@
.profile {
padding: 56px 20px;
min-height: 100%;
width: 100%;
}
+6
View File
@@ -0,0 +1,6 @@
import createStore from 'unistore'
export default function mcratesStore() {
return createStore({ bundles: [] })
}
+64
View File
@@ -18,3 +18,67 @@ html, body {
#app { #app {
height: 100%; height: 100%;
} }
.home {
padding: 56px 20px;
min-height: 100%;
width: 100%;
}
.profile {
padding: 56px 20px;
min-height: 100%;
width: 100%;
}
.header {
position: fixed;
left: 0;
top: 0;
width: 100%;
height: 56px;
padding: 0;
background: #673AB7;
box-shadow: 0 0 5px rgba(0, 0, 0, 0.5);
z-index: 50;
}
.header {
h1 {
float: left;
margin: 0;
padding: 0 15px;
font-size: 24px;
line-height: 56px;
font-weight: 400;
color: #FFF;
}
nav {
float: right;
font-size: 100%;
}
nav a {
display: inline-block;
height: 56px;
line-height: 56px;
padding: 0 15px;
min-width: 50px;
text-align: center;
background: rgba(255,255,255,0);
text-decoration: none;
color: #FFF;
will-change: background-color;
}
nav a:hover,
nav a:active {
background: rgba(0,0,0,0.2);
}
nav a.active {
background: rgba(0,0,0,0.4);
}
}
+1 -1
View File
@@ -21,7 +21,7 @@
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */ /* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */ "strict": false, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */ // "strictNullChecks": true, /* Enable strict null checks. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
+9 -34
View File
@@ -8,40 +8,13 @@ import discogsService from './src/discogs';
import pgService from './src/pg'; import pgService from './src/pg';
import { logAxiosError } from './src/utils'; import { logAxiosError } from './src/utils';
import createLog from './src/log'; import createLog from './src/log';
import createApi from './src/api';
async function start(log) { async function start(log) {
const prisma = new PrismaClient(); const prisma = new PrismaClient();
const pg = pgService(log, prisma); const pg = pgService(log, prisma);
const discogs = discogsService(log, pg); const discogs = discogsService(log, pg);
const api = createApi(log, pg);
async function getBundles() {
const bundles = await pg.bundleCandidates();
bundles.forEach(b => {
const data = b.map(l => l.data) as any[];
const wants = b.map(l => l.wantId);
const total = data.reduce((acc, l) => acc + l.price.value, 0);
const items = data.map(l => ({
id: l.id,
description: l.release.description,
price: l.price.value,
condition: l.condition,
uri: l.uri,
}));
const username = data[0]?.seller.username
const seller = data[0]?.seller.id
const shipsFrom = data[0]?.ships_from;
const currency = data[0]?.price.currency;
const shipping = data[0]?.seller.shipping;
const mentionsAustralia = shipping.toLowerCase().includes('australia');
const mentionsWorldwide = shipping.toLowerCase().includes('world');
log.info({ count: b.length, currency, total, items, username, seller, shipsFrom, mentionsAustralia, mentionsWorldwide });
});
// return bundles;
}
const usernames = [ const usernames = [
'vanderbabe', 'vanderbabe',
@@ -65,12 +38,14 @@ async function start(log) {
}); });
} }
await Promise.mapSeries(usernames, async u => { // await Promise.mapSeries(usernames, async u => {
const user = await discogs.user(u) // const user = await discogs.user(u)
return populateUserListings(user); // return populateUserListings(user);
}); // });
return getBundles(); await api.listen();
// return getBundles();
} }
async function run() { async function run() {
+35
View File
@@ -13,6 +13,7 @@
"axios": "^0.27.2", "axios": "^0.27.2",
"bluebird": "^3.7.2", "bluebird": "^3.7.2",
"bunyan": "^1.8.15", "bunyan": "^1.8.15",
"cors": "^2.8.5",
"express": "^4.18.1", "express": "^4.18.1",
"lodash": "^4.17.21" "lodash": "^4.17.21"
}, },
@@ -397,6 +398,18 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
}, },
"node_modules/cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"dependencies": {
"object-assign": "^4",
"vary": "^1"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/create-require": { "node_modules/create-require": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
@@ -1118,6 +1131,14 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object-inspect": { "node_modules/object-inspect": {
"version": "1.12.2", "version": "1.12.2",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
@@ -1983,6 +2004,15 @@
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
}, },
"cors": {
"version": "2.8.5",
"resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz",
"integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==",
"requires": {
"object-assign": "^4",
"vary": "^1"
}
},
"create-require": { "create-require": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
@@ -2521,6 +2551,11 @@
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"dev": true "dev": true
}, },
"object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg=="
},
"object-inspect": { "object-inspect": {
"version": "1.12.2", "version": "1.12.2",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.2.tgz",
+1
View File
@@ -23,6 +23,7 @@
"axios": "^0.27.2", "axios": "^0.27.2",
"bluebird": "^3.7.2", "bluebird": "^3.7.2",
"bunyan": "^1.8.15", "bunyan": "^1.8.15",
"cors": "^2.8.5",
"express": "^4.18.1", "express": "^4.18.1",
"lodash": "^4.17.21" "lodash": "^4.17.21"
} }
+67
View File
@@ -0,0 +1,67 @@
import express from 'express';
import http from 'http';
import cors from 'cors';
import type Log from 'bunyan';
import { Pg } from './pg';
export default function createApi(log: Log, pg: Pg) {
const PORT = 41337;
const app = express();
const server = http.createServer(app);
async function getBundles() {
const bundles = await pg.bundleCandidates();
bundles.forEach(b => {
const data = b.map(l => l.data) as any[];
const wants = b.map(l => l.wantId);
const total = data.reduce((acc, l) => acc + l.price.value, 0);
const items = data.map(l => ({
id: l.id,
description: l.release.description,
price: l.price.value,
condition: l.condition,
uri: l.uri,
}));
const username = data[0]?.seller.username
const seller = data[0]?.seller.id
const shipsFrom = data[0]?.ships_from;
const currency = data[0]?.price.currency;
const shipping = data[0]?.seller.shipping;
const mentionsAustralia = shipping.toLowerCase().includes('australia');
const mentionsWorldwide = shipping.toLowerCase().includes('world');
log.info({ count: b.length, currency, total, items, username, seller, shipsFrom, mentionsAustralia, mentionsWorldwide });
});
return bundles;
}
function listen() {
return new Promise((resolve, reject) => {
server.on('error', err => {
this.reject(err);
})
server.listen(PORT, () => {
log.info('listening', { PORT });
});
});
}
app.use(cors());
app.get('/bundles', async (req, res, next) => {
const bundles = await getBundles();
res.json(bundles);
})
return {
app,
listen,
};
}