Skip to content

Commit 370e966

Browse files
authored
Merge pull request #94 from adorableio/ts-refactors
Refactors on top of typescript
2 parents 21d8b1a + cd25bcd commit 370e966

File tree

13 files changed

+128
-153
lines changed

13 files changed

+128
-153
lines changed

index.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
type ImageType = 'eyes' | 'nose' | 'mouth';
2+
type FaceParts = ImageType | 'color';
3+
4+
interface Face {
5+
color: string;
6+
eyes: string;
7+
nose: string;
8+
mouth: string;
9+
}

package.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,18 @@
66
"node": "9.4.x"
77
},
88
"scripts": {
9-
"test": "mocha --exit",
9+
"test": "TS_NODE_FILES=true mocha --exit",
1010
"build": "tsc && npm run build:assets",
1111
"build:assets": "cp -r {src,dist}/img",
1212
"dev": "concurrently --kill-others --prefix=name --names=server,eslint --prefix-colors=green,magenta \"npm run dev:server\" \"npm run dev:lint\"",
13-
"dev:server": "onchange -i -k 'src/**/*.ts' -- ts-node test/server.ts",
13+
"dev:server": "TS_NODE_FILES=true onchange -i -k 'src/**/*.ts' -- ts-node test/server.ts",
1414
"dev:lint": "onchange -i -k 'src/**/*.ts' -- tslint -t stylish 'src/**/*.ts'",
1515
"prepublishOnly": "npm run build"
1616
},
1717
"author": "",
1818
"license": "MIT",
1919
"main": "dist/index.js",
20+
"types": "dist/index.d.ts",
2021
"files": [
2122
"dist"
2223
],

src/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1-
import routes from './routes/avatars';
1+
import routes from './routes';
22

33
export default routes;
4+
(module as any).exports = routes;

src/lib/hashingFunctions.ts

Lines changed: 8 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,10 @@
1-
const _addition = (a, b) => {
2-
return a + b;
3-
};
1+
const isEven: (num: number) => boolean = num => num % 2 === 0;
42

5-
const _subtraction = (a, b) => {
6-
return a - b;
7-
};
3+
export const sum: (array: number[]) => number = arr =>
4+
arr.reduce((a, b) => a + b, 0);
85

9-
const _multiplication = (a, b) => {
10-
return a * b;
11-
};
12-
13-
export const sum = array => {
14-
return array.reduce(_addition, 0);
15-
};
16-
17-
export const sumAndDiff = array => {
18-
return array.reduce((prev, curr, index) => {
19-
if (index % 2 === 0) {
20-
return _addition(prev, curr);
21-
} else {
22-
return _subtraction(prev, curr);
23-
}
24-
}, 0);
25-
};
26-
27-
export const product = array => {
28-
return array.reduce(_multiplication, 1);
29-
};
6+
export const sumAndDiff: (array: number[]) => number = array =>
7+
array.reduce(
8+
(prev, curr, index) => (isEven(index) ? prev + curr : prev - curr),
9+
0,
10+
);

src/lib/imageFiles.ts

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,23 @@
11
import fs from 'fs';
22
import path from 'path';
33

4-
const DEFAULT_IMAGE_DIR = path.join(__dirname, '..', 'img');
4+
const IMAGE_DIR = path.join(__dirname, '..', 'img');
55

6-
export const dirFor = (type, imageDir = DEFAULT_IMAGE_DIR) => {
7-
if (type) {
8-
return path.join(imageDir, type);
9-
}
6+
const imageFiles: (path: string) => string[] = p =>
7+
fs.readdirSync(p).filter(fileName => fileName.match(/\.png$/));
108

11-
return imageDir;
12-
};
9+
const imageDir: (type: ImageType) => string = type =>
10+
type ? path.join(IMAGE_DIR, type) : IMAGE_DIR;
1311

14-
export const allNames = (type, imageDir = DEFAULT_IMAGE_DIR) => {
15-
return fs
16-
.readdirSync(dirFor(type, imageDir))
17-
.filter(imageFileName => {
18-
return imageFileName.match(/\.png/);
19-
})
20-
.map(imageFileName => {
21-
return imageFileName.replace(/\.png/, '');
22-
});
23-
};
12+
export const allNames: (type: ImageType) => string[] = type =>
13+
imageFiles(imageDir(type)).map(imageFileName =>
14+
imageFileName.replace(/\.png/, ''),
15+
);
2416

25-
export const allPaths = (type, imageDir = DEFAULT_IMAGE_DIR) => {
26-
const dir = dirFor(type, imageDir);
27-
return allNames(type, imageDir).map(name => path.join(dir, name + '.png'));
17+
export const allPaths: (type: ImageType) => string[] = type => {
18+
const dir = imageDir(type);
19+
return imageFiles(dir).map(file => path.join(dir, file));
2820
};
2921

30-
export const pathFor = (type, fileName, imageDir = DEFAULT_IMAGE_DIR) => {
31-
return path.join(dirFor(type, imageDir), fileName + '.png');
32-
};
22+
export const pathTo: (type: ImageType, name: string) => string = (type, name) =>
23+
path.join(imageDir(type), name + '.png');

src/lib/potato.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// our libs
21
import { sumAndDiff } from './hashingFunctions';
32
import { allPaths } from './imageFiles';
43
import SlotMachine from './slotMachine';
@@ -23,8 +22,7 @@ class Potato {
2322
private mouthMachine = new SlotMachine(allPaths('mouth'), sumAndDiff),
2423
) {}
2524

26-
// Construct Faces Parts
27-
parts(string) {
25+
parts(string): Face {
2826
return {
2927
color: this.colorMachine.pull(string),
3028
eyes: this.eyesMachine.pull(string),

src/lib/slotMachine.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,25 @@
11
import { sum } from './hashingFunctions';
22

33
class SlotMachine<T> {
4-
private slots: T[];
54
private numSlots: number;
6-
private hashingFn: (items: number[]) => number;
75

8-
constructor(slots: T[], hashingFn?) {
9-
this.slots = slots;
10-
this.numSlots = this.slots.length;
11-
this.hashingFn = hashingFn || sum;
6+
constructor(private slots: T[], private hash = sum) {
7+
this.numSlots = slots.length;
128
}
139

1410
pull(string) {
1511
const str = string.replace(/\.(png|jpg|gif|)$/g, '');
1612
const stringArray = str.split('');
17-
return this.slots[this._indexFor(stringArray)];
13+
return this.slots[this.indexFor(stringArray)];
1814
}
1915

20-
_indexFor(array) {
21-
const intArray = array.map(this._getCharInt);
22-
const index = (this.hashingFn(intArray) + intArray.length) % this.numSlots;
16+
private indexFor(array) {
17+
const intArray = array.map(this.getCharInt);
18+
const index = (this.hash(intArray) + intArray.length) % this.numSlots;
2319
return Math.abs(index);
2420
}
2521

26-
_getCharInt(char) {
22+
private getCharInt(char) {
2723
return parseInt(char.charCodeAt(0) || 0, 10);
2824
}
2925
}

src/routes/avatars.ts

Lines changed: 0 additions & 71 deletions
This file was deleted.

src/routes/common.ts

Lines changed: 0 additions & 9 deletions
This file was deleted.

src/routes/index.ts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import Router from 'express';
2+
import uuid from 'uuid';
3+
4+
import { allNames, pathTo } from '../lib/imageFiles';
5+
import { combine } from '../lib/imager';
6+
import potato from '../lib/potato';
7+
8+
const imageTypes: ImageType[] = ['eyes', 'nose', 'mouth'];
9+
10+
const router = Router();
11+
12+
const sendImage = ({ stdout, response }) => {
13+
response.setHeader('Expires', new Date(Date.now() + 604800000));
14+
response.setHeader('Content-Type', 'image/png');
15+
stdout.pipe(response);
16+
};
17+
18+
router.get('/list', (req, res) => {
19+
const face = {};
20+
imageTypes.forEach(type => (face[type] = allNames(type)));
21+
22+
return res.set('Content-Type', 'application/json').send({ face });
23+
});
24+
25+
router.get('/:size?/random', (req, res) => {
26+
const faceParts = potato.parts(uuid.v4());
27+
28+
return combine(faceParts, req.params.size, (err, stdout) =>
29+
sendImage({ stdout, response: res }),
30+
);
31+
});
32+
33+
router.get('/:size?/:id', (req, res, next) => {
34+
const faceParts = potato.parts(req.params.id);
35+
36+
return combine(faceParts, req.params.size, (err, stdout) =>
37+
sendImage({ stdout, response: res }),
38+
);
39+
});
40+
41+
router.get('/face/:eyes/:nose/:mouth/:color/:size?', (req, res, next) => {
42+
const faceParts = { color: `#${req.params.color}` };
43+
44+
imageTypes.forEach(type => {
45+
const requestedName = req.params[type];
46+
const names = allNames(type);
47+
let name = names[0];
48+
49+
if (names.includes(requestedName)) {
50+
name = requestedName;
51+
} else if (requestedName === 'x') {
52+
name = '';
53+
}
54+
55+
faceParts[type] = pathTo(type, name);
56+
});
57+
58+
return combine(faceParts, req.params.size, (err, stdout) =>
59+
sendImage({ stdout, response: res }),
60+
);
61+
});
62+
63+
export default router;

0 commit comments

Comments
 (0)