Skip to content
This repository was archived by the owner on Jan 20, 2020. It is now read-only.

Commit 6b218be

Browse files
author
Luciano Nooijen
committed
Added first working version of CLI
1 parent 57b8dcd commit 6b218be

File tree

4 files changed

+77
-32
lines changed

4 files changed

+77
-32
lines changed

README.md

+4-23
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const nodeBlog = require('nodejs-blog');
3636
const { authors, auth, users, categories, articles } = require('nodejs-blog');
3737
```
3838

39-
to start using the package, create a new instance of the NodeBlog class
39+
to start using the package, create a new blog object:
4040

4141
```js
4242
const client = 'YOUR_DB_CLIENT'; // for more info, see https://knexjs.org/
@@ -99,11 +99,11 @@ articles.delete(blog, id)
9999

100100
We recommend creating a single file that will create the NodeBlog instance, and `export` this instance, and `import` in all other files where you want to use NodeJS Blog.
101101

102-
For security reasons we recommend using environment variables for loading the configuration. This is also in compliance with the [12 factor app Config guidelines](https://12factor.net/config)
102+
For security reasons we recommend using environment variables for loading the configuration. This is also in compliance with the [12 factor app Config guidelines](https://12factor.net/config).
103103

104104
Note: NodeJS blog was made to be used with PostgreSQL, but it should(/could) also be compatible with other databases, as it uses [KnexJS](https://knexjs.org) under the hood.
105105

106-
*A demo application is currently in development*
106+
*A demo application and a standalone CLI are currently in development*
107107

108108
## Running the API as a standalone service (still in development, might not work 100%)
109109

@@ -124,6 +124,7 @@ For development, the following commands are available:
124124
| Command | Functionality |
125125
| - | - |
126126
| `yarn run dev` | Runs a `nodemon` server for the `server/server.js` file, and exposing the standalone service to your `localhost` |
127+
| `yarn run cli` | Runs the CLI tool created for simple CRUD operations without accessing the database directly |
127128
| `yarn run lint` | Runs ESLint, for PRs this should always pass |
128129
| `yarn run test` | Runs Jest once, for PRs this should always pass. Your database must be available as it is used to run tests on (beware: all existing data will be wiped, we recommend using a separate test-database, this can be set in the `.env` file) |
129130
| `yarn run test:watch` | Same as `yarn run test`, but it Jest watches for changes |
@@ -132,26 +133,6 @@ For development, the following commands are available:
132133
| `yarn run reinstall` | Deletes the `node_modules/` folder and reinstalls everything, if you get some stange dependency errors, run this command |
133134
| `yarn run clean` | Deletes folders `build/`, `dist/` and `coverage/` |
134135

135-
### Folder structure
136-
137-
```md
138-
.
139-
├── controllers Controllers for the module based API
140-
├── database All database related files
141-
│   ├── migrations
142-
│   └── seeds
143-
├── helpers Helper files, for example: logger, database instance
144-
├── server
145-
│   ├── controllers
146-
│   ├── middleware
147-
│   │   └── modules
148-
│   └── routes
149-
├── src Source directory for the API exposed by the module
150-
└── tests All tests written
151-
├── config
152-
└── database
153-
```
154-
155136
### Node Environments
156137

157138
The following NodeJS Environments are integrated:

cli/add-post.ts

+41-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,43 @@
1-
function addPost() {
2-
console.log('AddPost Working!');
3-
}
1+
/* tslint:disable: no-console */
2+
3+
import chalk from 'chalk';
4+
import inquirer from 'inquirer';
5+
import articles = require('../controllers/articles');
6+
7+
const { addArticle, getArticle } = articles;
8+
9+
const prompt = inquirer.createPromptModule();
10+
11+
const addPostQuestions = [
12+
{ type: 'input', name: 'title', message: 'What is the post title' },
13+
{ type: 'input', name: 'subtitle', message: 'And the post subtitle' },
14+
{ type: 'input', name: 'slug', message: 'And the post slug' },
15+
{ type: 'input', name: 'author', message: 'What is the author id' },
16+
{ type: 'input', name: 'category', message: 'What is the category id' },
17+
{ type: 'input', name: 'summary', message: 'Please give a short summary' },
18+
{ type: 'input', name: 'image_url', message: 'What is the image url' },
19+
{ type: 'input', name: 'html_content', message: 'Minified HTML string' },
20+
{ type: 'input', name: 'related_articles',
21+
message: 'Related articles, comma seperated, no spaces, ("1,2,3")' },
22+
];
23+
24+
const createPostDataObject = input => {
25+
const relatedArticleString = input.related_articles;
26+
const relatedArticlesArray = relatedArticleString.split(',');
27+
const postData = { ...input, related_articles: relatedArticlesArray };
28+
return postData;
29+
};
30+
31+
const addPost = async knex => {
32+
const postDataInputRaw = await prompt(addPostQuestions);
33+
const postDataInput = createPostDataObject(postDataInputRaw);
34+
try {
35+
const addedArticle = await addArticle(knex, postDataInput);
36+
console.log(`${chalk.green('Success')}: article added!`);
37+
} catch (err) {
38+
console.log(`${chalk.red('Error')}: the CLI failed you :(`);
39+
console.log(err);
40+
}
41+
};
442

543
export default addPost;

cli/index.ts

+31-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
/* tslint:disable: no-console */
1+
/* tslint:disable: no-console import-name */
22

33
import chalk from 'chalk';
44
import figlet from 'figlet';
55
import inquirer from 'inquirer';
6+
import knexGenerator from 'knex';
67

8+
import generateKnexfile = require('../database/generate-knexfile');
79
import addPost from './add-post';
810

911
const prompt = inquirer.createPromptModule();
@@ -22,16 +24,40 @@ const intro = () => {
2224
figlet.textSync('NodeJS Blog', { horizontalLayout: 'full' })));
2325
};
2426

25-
const promptHandler = async () => {
27+
const promptHandler = async knex => {
2628
const answer = await prompt([question]) as any; // Hack to avoid error...
2729
if (answer.action === 'Add post') {
28-
addPost();
30+
addPost(knex);
2931
}
3032
};
3133

32-
const cli = async () => {
34+
const createKnexInstance = config => {
35+
const knexfile = generateKnexfile(config);
36+
const knex = knexGenerator(knexfile);
37+
return knex;
38+
};
39+
40+
const cli = async (
41+
client = process.env.DB_CLIENT_TEST,
42+
host = process.env.DB_HOST_TEST,
43+
user = process.env.DB_USER_TEST,
44+
database = process.env.DB_NAME_TEST,
45+
password = process.env.DB_PASS_TEST,
46+
debug = process.env.KNEX_DEBUG === 'true',
47+
) => {
3348
intro();
34-
await promptHandler();
49+
50+
try {
51+
// TODO: Load the config using a promt
52+
const config = { client, host, user, database, password, debug };
53+
const knex = createKnexInstance(config);
54+
await promptHandler(knex);
55+
} catch (err) {
56+
console.log(`${chalk.red('Error')}: the CLI failed you :(`);
57+
console.log(err);
58+
}
3559
};
3660

61+
// Run CLI
62+
require('dotenv').config(); // Load .env file
3763
cli();

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
"dev": "nodemon",
3737
"cli": "ts-node cli/index.ts",
3838
"start": "ts-node server/server.ts",
39-
"build": "tsc",
39+
"build": "yarn run clean && tsc",
4040
"lint": "yarn run lint:js && yarn run lint:ts",
4141
"lint:js": "eslint --ext .js,.jsx .",
4242
"lint:ts": "tslint --project .",

0 commit comments

Comments
 (0)