Skip to content

Commit db160c7

Browse files
committedMar 18, 2017
Initial commit.
0 parents  commit db160c7

23 files changed

+3502
-0
lines changed
 

‎.editorconfig

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# editorconfig.org
2+
3+
root = true
4+
5+
[*]
6+
charset = utf-8
7+
end_of_line = lf
8+
indent_size = 2
9+
indent_style = space
10+
insert_final_newline = true
11+
trim_trailing_whitespace = true
12+
13+
[*.md]
14+
trim_trailing_whitespace = false

‎.gitignore

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
# Numerous always-ignore extensions
2+
*.diff
3+
*.err
4+
*.log
5+
*.orig
6+
*.rej
7+
*.swo
8+
*.swp
9+
*.vi
10+
*.zip
11+
*~
12+
13+
# OS or Editor folders
14+
._*
15+
.cache
16+
.DS_Store
17+
.idea
18+
.project
19+
.settings
20+
.tmproj
21+
*.esproj
22+
*.sublime-project
23+
*.sublime-workspace
24+
nbproject
25+
Thumbs.db
26+
27+
# Folders to ignore
28+
app
29+
node_modules

‎CONTRIBUTING.md

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
## Reporting Issues
2+
Found a problem? Want a new feature?
3+
4+
- See if your issue or idea has [already been reported].
5+
- Provide a [reduced test case] or a [live example].
6+
7+
Remember, a bug is a *demonstrable problem* caused by *our* code.
8+
9+
## Submitting Pull Requests
10+
Pull requests are the greatest contributions, so be sure they are focused in scope, and do avoid unrelated commits.
11+
12+
1. To begin, [fork this project], clone your fork, and add our upstream.
13+
```bash
14+
# Clone your fork of the repo into the current directory
15+
git clone https://github.com/<your-username>/typescript-database-abstraction
16+
# Navigate to the newly cloned directory
17+
cd typescript-database-abstraction
18+
# Assign the original repo to a remote called "upstream"
19+
git remote add upstream https://github.com/maoberlehner/typescript-database-abstraction
20+
# Install the tools necessary for development
21+
npm install
22+
```
23+
2. Create a branch for your feature or hotfix:
24+
```bash
25+
# Move into a new branch for a feature
26+
git checkout -b feature/thing
27+
```
28+
```bash
29+
# Move into a new branch for a hotfix
30+
git checkout -b hotfix/something
31+
```
32+
3. Push your branch up to your fork:
33+
```bash
34+
# Push a feature branch
35+
git push origin feature/thing
36+
```
37+
```bash
38+
# Push a hotfix branch
39+
git push origin hotfix/something
40+
```
41+
4. Now [open a pull request] with a clear title and description.
42+
43+
[already been reported]: https://github.com/maoberlehner/typescript-database-abstraction/issues
44+
[fork this project]: https://github.com/maoberlehner/typescript-database-abstraction/fork
45+
[live example]: http://codepen.io/pen
46+
[open a pull request]: https://help.github.com/articles/using-pull-requests/
47+
[reduced test case]: https://css-tricks.com/reduced-test-cases/

‎LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License (MIT)
2+
3+
Copyright (c) 2016 Markus Oberlehner
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

‎README.md

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# typescript-database-abstraction
2+
This is an example repository created for the following blog article: <LINK>.
3+
4+
## Getting started
5+
- `yarn start` Runs the TypeScript compiler in watch mode.
6+
7+
## Build
8+
- `yarn run build-app`
9+
10+
## Run the demo code
11+
- `node app/index.js`
12+
13+
## Lint
14+
- `yarn run lint`
15+
16+
## Test
17+
- `yarn test`
18+
19+
## About
20+
### Author
21+
Markus Oberlehner
22+
Website: https://markus.oberlehner.net
23+
Twitter: https://twitter.com/MaOberlehner
24+
PayPal.me: https://paypal.me/maoberlehner
25+
26+
### License
27+
MIT

‎package.json

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"name": "typescript-database-abstraction",
3+
"version": "0.0.1",
4+
"author": "Markus Oberlehner",
5+
"homepage": "https://github.com/avalanchesass/typescript-database-abstraction",
6+
"license": "MIT",
7+
"repository": {
8+
"type": "git",
9+
"url": "https://github.com/avalanchesass/typescript-database-abstraction"
10+
},
11+
"bugs": {
12+
"url": "https://github.com/avalanchesass/typescript-database-abstraction/issues"
13+
},
14+
"devDependencies": {
15+
"@types/glob": "^5.0.30",
16+
"@types/js-yaml": "^3.5.29",
17+
"@types/node": "^7.0.8",
18+
"@types/sinon": "^1.16.35",
19+
"ava": "^0.18.2",
20+
"glob": "^7.1.1",
21+
"js-yaml": "^3.8.2",
22+
"sinon": "^2.0.0",
23+
"tslint": "^4.5.1",
24+
"typescript": "^2.2.1"
25+
},
26+
"scripts": {
27+
"start": "yarn run clean-app && tsc -w",
28+
"build-app": "yarn run clean-app && tsc",
29+
"clean-app": "rm -Rf app",
30+
"lint": "tslint 'src/**/*.ts'",
31+
"test": "yarn run build-app && ava app/**/*.spec.js"
32+
}
33+
}

‎resources/articles/an-article.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
title: "An article"
3+
description: "This is an article."
4+
---
5+
6+
# An article
7+
Content of an article.

‎resources/articles/another-article.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
title: "Another article"
3+
description: "This is another article."
4+
---
5+
6+
# Another article
7+
Content of another article.

‎src/classes/Database.spec.ts

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import test from 'ava';
2+
import * as sinon from 'sinon';
3+
4+
import { Database } from './Database';
5+
6+
test('should be a function', (t) => {
7+
t.is(typeof Database, 'function');
8+
});
9+
10+
test('should call the drivers getAll method', (t) => {
11+
const MockDriver = {
12+
getAll: sinon.spy(),
13+
getById: () => ({}),
14+
};
15+
const db = new Database(MockDriver);
16+
db.getAll(`some-table`);
17+
18+
t.true(MockDriver.getAll.called);
19+
});
20+
21+
test('should call the drivers getById method', (t) => {
22+
const MockDriver = {
23+
getAll: () => [],
24+
getById: sinon.spy(),
25+
};
26+
const db = new Database(MockDriver);
27+
db.getById(`some-id`, `some-table`);
28+
29+
t.true(MockDriver.getById.called);
30+
});

‎src/classes/Database.ts

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import IDatabase from '../interfaces/IDatabase';
2+
3+
export class Database implements IDatabase {
4+
private driver: IDatabase;
5+
6+
/**
7+
* Database
8+
* @param driver
9+
*/
10+
constructor(driver: IDatabase) {
11+
this.driver = driver;
12+
}
13+
14+
public getAll(table: string) {
15+
return this.driver.getAll(table);
16+
}
17+
18+
public getById(id: any, table: string) {
19+
return this.driver.getById(id, table);
20+
}
21+
}
22+
23+
/**
24+
* databaseFactory
25+
* @param driver
26+
*/
27+
export default function databaseFactory(driver: IDatabase) {
28+
return new Database(driver);
29+
}

‎src/classes/FileDriver.spec.ts

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// TODO: Refactor to promises.
2+
import test from 'ava';
3+
import * as path from 'path';
4+
import * as sinon from 'sinon';
5+
6+
import { FileDriver } from './FileDriver';
7+
8+
test('should be a function', (t) => {
9+
t.is(typeof FileDriver, 'function');
10+
});
11+
12+
test('should load files from the file system and extract data', (t) => {
13+
const files = [
14+
`file/a.md`,
15+
`file/b.md`,
16+
];
17+
const glob = {
18+
sync: sinon.stub().returns(files),
19+
};
20+
const fs = {
21+
readFileSync: sinon.stub().returns(`fake-content`),
22+
};
23+
const extractData = sinon.spy();
24+
const extractor = sinon.stub().returns({ extractData });
25+
const driver = new FileDriver(glob, path, fs, extractor, `/some/cwd`);
26+
27+
driver.getAll(`some-table`);
28+
29+
t.true(glob.sync.calledOnce);
30+
31+
t.true(fs.readFileSync.calledTwice);
32+
t.true(fs.readFileSync.calledWith(`file/a.md`));
33+
t.true(fs.readFileSync.calledWith(`file/b.md`));
34+
35+
t.true(extractor.calledTwice);
36+
t.true(extractor.calledWith(`fake-content`));
37+
38+
t.true(extractData.calledTwice);
39+
});
40+
41+
test('should load file from the file system and extract data', (t) => {
42+
const glob = { sync: () => ([]) };
43+
const fs = {
44+
readFileSync: sinon.stub().returns(`fake-content`),
45+
};
46+
const extractData = sinon.spy();
47+
const extractor = sinon.stub().returns({ extractData });
48+
const cwd = `/some/cwd`;
49+
const table = `some-table`;
50+
const id = `some-id`;
51+
const driver = new FileDriver(glob, path, fs, extractor, cwd);
52+
53+
driver.getById(id, table);
54+
55+
t.true(fs.readFileSync.calledWith(`${cwd}/resources/${table}/${id}.md`));
56+
t.true(extractor.calledWith(`fake-content`));
57+
});

‎src/classes/FileDriver.ts

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
import * as fs from 'fs';
2+
import * as glob from 'glob';
3+
import * as path from 'path';
4+
5+
import IDatabase from '../interfaces/IDatabase';
6+
import IExtractor from '../interfaces/IExtractor';
7+
8+
export class FileDriver implements IDatabase {
9+
private glob: any;
10+
private path: any;
11+
private fs: any;
12+
private extractor: (fileContent: string) => IExtractor;
13+
private cwd: string;
14+
15+
/**
16+
* FileDriver
17+
* @param glob
18+
* @param path
19+
* @param fs
20+
* @param extractor
21+
* @param cwd
22+
*/
23+
constructor(
24+
glob,
25+
path,
26+
fs,
27+
extractor,
28+
cwd: string,
29+
) {
30+
this.glob = glob;
31+
this.path = path;
32+
this.fs = fs;
33+
this.extractor = extractor;
34+
this.cwd = cwd;
35+
}
36+
37+
public getAll(table: string): Array<object> {
38+
const globPattern = path.resolve(this.cwd, `resources/${table}/*.md`);
39+
return this.glob.sync(globPattern)
40+
.map((file) => {
41+
const fileContent: string = this.readFile(file);
42+
return this.extractData(fileContent);
43+
});
44+
}
45+
46+
public getById(id: string, table: string): object {
47+
const file = this.path.resolve(this.cwd, `resources/${table}/${id}.md`);
48+
const fileContent: string = this.readFile(file);
49+
50+
return this.extractData(fileContent);
51+
}
52+
53+
private readFile(file: string): string {
54+
return this.fs.readFileSync(file, `utf8`);
55+
}
56+
57+
private extractData(fileContent: string): object {
58+
return this.extractor(fileContent).extractData();
59+
}
60+
}
61+
62+
/**
63+
* fileDriverFactory
64+
* @param extractor
65+
* @param cwd
66+
*/
67+
export default function fileDriverFactory(
68+
extractor,
69+
cwd: string,
70+
): FileDriver {
71+
return new FileDriver(
72+
glob,
73+
path,
74+
fs,
75+
extractor,
76+
cwd,
77+
);
78+
}

0 commit comments

Comments
 (0)
Please sign in to comment.