unistore sucks i think
This commit is contained in:
1 parent
baeaead650
commit
02aadcf2db
21 files changed
+4468
-1354
No files matched your search
Generated
+4198
-1208
File diff suppressed because it is too large.
Load diff
+6
-2
@@ -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"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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;
|
||||||
@@ -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;
|
||||||
@@ -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;
|
|
||||||
@@ -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;
|
||||||
@@ -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;
|
|
||||||
@@ -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
@@ -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;
|
||||||
@@ -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);
|
||||||
@@ -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;
|
|
||||||
@@ -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>
|
||||||
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
.profile {
|
|
||||||
padding: 56px 20px;
|
|
||||||
min-height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
import createStore from 'unistore'
|
||||||
|
|
||||||
|
export default function mcratesStore() {
|
||||||
|
return createStore({ bundles: [] })
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -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
@@ -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() {
|
||||||
|
|||||||
Generated
+35
@@ -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",
|
||||||
|
|||||||
@@ -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"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in new issue
Block a user