Migrate all the things

* Migrates from Mongo to Postgres.
* Migrates from JSPM to Webpack.
* Migrates from React to Vuejs.
* Migrates from Bootstrap to Bulma.

Also:
* Fixes rendering of meta data in the document head tag.
This commit is contained in:
Jonathan Cremin 2016-10-03 13:31:29 +01:00
parent 09706778d9
commit 7bb0497ff4
76 changed files with 6741 additions and 1760 deletions

View file

@ -1,38 +0,0 @@
import React from 'react';
import { renderPage } from './react-handler';
import debuglog from 'debug';
const debug = debuglog('match.audio');
export default function (routes) {
return function* (next) {
this.set('Server', 'Nintendo 64');
try {
yield next;
} catch (err) {
if (err.status === 404) {
this.body = yield renderPage(routes, this.request.url, {});
} else {
debug('Error: %o', err);
throw err;
}
}
if (404 != this.status) return;
switch (this.accepts('html', 'json')) {
case 'html':
this.type = 'html';
this.body = yield renderPage(routes, this.request.url, {});
break;
case 'json':
this.body = {
message: 'Page Not Found'
};
break;
default:
this.type = 'text';
this.body = 'Page Not Found';
}
}
}

34
lib/react-handler.js vendored
View file

@ -1,34 +0,0 @@
import React from 'react';
import { renderToString } from 'react-dom/server';
import { RoutingContext, match } from 'react-router';
import createLocation from 'history/lib/createLocation';
export function matchRoute(routes, url) {
const location = createLocation(url);
return new Promise((resolve, reject) => {
match({ routes, location }, (error, redirectLocation, renderProps) => {
resolve({error, redirectLocation, renderProps});
});
});
}
export function* renderPage(routes, url, state) {
const { error, redirectLocation, renderProps } = yield matchRoute(routes, url);
if (error) {
throw new Error(error.message);
} else if (redirectLocation) {
return redirectLocation.pathname + redirectLocation.search;
} else if (renderProps === null) {
return false;
}
const content = renderToString(<RoutingContext {...renderProps} />);
return '<!doctype html>\n' + content.replace('</body></html>', `<script>window.STATE = ${JSON.stringify(state)}</script>
<script src='/jspm_packages/system.js'></script>
<script src='/config.js'></script>
<script>System.import('babel/external-helpers')</script>
<script>System.import('views/app')</script>
</body></html>`);
}

16
lib/render.js Normal file
View file

@ -0,0 +1,16 @@
import fs from 'fs';
import { createBundleRenderer } from 'vue-server-renderer';
const app = fs.readFileSync('./public/dist/js/build-server.js', 'utf8');
export default function(url, initialState) {
const renderer = createBundleRenderer(app);
return new Promise((resolve, reject) => {
renderer.renderToString({ url, initialState }, (error, html) => {
if(error) {
return reject(error);
}
resolve(html);
});
});
}

View file

@ -51,7 +51,7 @@ function formatResponse(res) {
purchaseUrl: null,
artwork: {
small: result.ImageUrl.replace('http://', 'https://') + '&w=250&h=250',
large: result.ImageUrl.replace('http://', 'https://') + '&w=500&h=250'
large: result.ImageUrl.replace('http://', 'https://') + '&w=500&h=500'
},
artist: {
name: result.Artists[0].Artist.Name

91
lib/share.js Normal file
View file

@ -0,0 +1,91 @@
import co from 'co';
import debuglog from 'debug';
import models from '../models';
import services from '../lib/services';
const debug = debuglog('match.audio:share');
export function find(music) {
return models[music.type].findOne({
where: {
externalId: music.id,
},
include: [
{ model: models.artist },
{ model: models.match },
],
});
}
export function create(music) {
return models[music.type].create({
externalId: music.id,
service: music.service,
name: music.name,
albumName: music.type === 'track' ? music.album.name : null,
artist: {
name: music.artist.name,
artworkSmall: null,
artworkLarge: null,
},
matches: [
{
externalId: music.id,
service: music.service,
name: music.name,
streamUrl: music.streamUrl,
purchaseUrl: music.purchaseUrl,
artworkSmall: music.artwork.small,
artworkLarge: music.artwork.large,
},
],
}, {
include: [
{ model: models.artist },
{ model: models.match },
],
});
}
export function findMatchesAsync(share) {
process.nextTick(() => {
for (const service of services) {
if (service.id === share.service) {
continue; // eslint-disable-line no-continue
}
co(function* gen() { // eslint-disable-line no-loop-func
const match = yield service.search(share);
console.log(service.id)
console.log(match)
if (match.id) {
models.match.create({
trackId: share.albumName ? share.id : null,
albumId: share.albumName ? null : share.id,
externalId: match.id,
service: match.service,
name: match.name,
streamUrl: match.streamUrl,
purchaseUrl: match.purchaseUrl,
artworkSmall: match.artwork.small,
artworkLarge: match.artwork.large,
});
} else {
models.match.create({
trackId: share.trackId ? share.id : null,
albumId: share.albumId ? share.id : null,
externalId: null,
service: match.service,
name: null,
streamUrl: null,
purchaseUrl: null,
artworkSmall: null,
artworkLarge: null,
});
}
}).catch((err) => {
debug(err);
});
}
});
}