added init and version commands

This commit is contained in:
Umed Khudoiberdiev 2017-09-13 21:40:34 +05:00
parent f919ded673
commit fb87751156
8 changed files with 360 additions and 3 deletions

View File

@ -1,4 +1,4 @@
version: '2'
version: '3'
services:
# mysql

1
docs/changelog.md Normal file
View File

@ -0,0 +1 @@
# Changelog

View File

@ -23,7 +23,7 @@ Its all possible with TypeORM:
* automatic migrations generation
* replication
* connection pooling
* caching [TBD]
* query caching
* CLI to simplify and automate your work with database
And more...

View File

@ -1,5 +1,6 @@
# Using CLI
* [Initialize a new TypeORM project](#initialize-a-new-typeorm-project)
* [Create a new entity](#create-a-new-entity)
* [Create a new subscriber](#create-a-new-subscriber)
* [Create a new migration](#create-a-new-migration)
@ -10,8 +11,46 @@
* [Log sync database schema queries without actual running them](#log-sync-database-schema-queries-without-actual-running-them)
* [Drop database schema](#drop-database-schema)
* [Run any sql query](#run-any-sql-query)
* [Check version](#check-version)
* Create database backup [TBD]
## Initialize a new TypeORM project
You can create a new project with everything already setup using following command:
```
typeorm init
```
It creates all files needed for a basic project with TypeORM:
* package.json
* README.md
* tsconfig.json
* ormconfig.json
* src/entity/User.ts
* src/index.ts
Then you can run `npm install` to install all dependencies.
Once all dependencies are installed you need to modify `ormconfig.json` and insert your own database settings.
After that you can run your application by running `npm start` command.
All files are generated inside current directory where you are.
If you want to generate in a specific directory you can use `--name` option:
```
typeorm init --name my-project
```
You can also generate a `docker-compose.yml` file if you want to use `docker` in your project by running following command:
```
typeorm init --docker
```
Using `typeorm init` command is the easiest and fastest way to setup a TypeORM project.
## Create a new entity
You can create a new entity using CLI:
@ -175,3 +214,11 @@ You can execute any sql query you want directly in the database using following
```
typeorm query "SELECT * FROM USERS"
```
## Check version
You can check what typeorm version you have installed (both local and global) by running following command:
```
typeorm version
```

View File

@ -10,6 +10,8 @@ import {MigrationRevertCommand} from "./commands/MigrationRevertCommand";
import {SubscriberCreateCommand} from "./commands/SubscriberCreateCommand";
import {SchemaLogCommand} from "./commands/SchemaLogCommand";
import {MigrationGenerateCommand} from "./commands/MigrationGenerateCommand";
import {VersionCommand} from "./commands/VersionCommand";
import {InitCommand} from "./commands/InitCommand";
require("yargs")
.usage("Usage: $0 <command> [options]")
@ -23,6 +25,8 @@ require("yargs")
.command(new MigrationGenerateCommand())
.command(new MigrationRunCommand())
.command(new MigrationRevertCommand())
.command(new VersionCommand())
.command(new InitCommand())
.demand(1)
.version(() => require("./package.json").version)
.alias("v", "version")

View File

@ -17,11 +17,23 @@ export class CommandUtils {
/**
* Creates a file with the given content in the given path.
*/
static async createFile(filePath: string, content: string): Promise<void> {
static async createFile(filePath: string, content: string, override: boolean = true): Promise<void> {
await CommandUtils.createDirectories(path.dirname(filePath));
return new Promise<void>((ok, fail) => {
if (override === false && fs.existsSync(filePath))
return ok();
fs.writeFile(filePath, content, err => err ? fail(err) : ok());
});
}
/**
* Reads everything from a given file and returns its content as a string.
*/
static async readFile(filePath: string): Promise<string> {
return new Promise<string>((ok, fail) => {
fs.readFile(filePath, (err, data) => err ? fail(err) : ok(data.toString()));
});
}
}

245
src/commands/InitCommand.ts Normal file
View File

@ -0,0 +1,245 @@
import {CommandUtils} from "./CommandUtils";
const chalk = require("chalk");
/**
* Generates a new project with TypeORM.
*/
export class InitCommand {
command = "init";
describe = "Generates initial TypeORM project structure. " +
"If name specified then creates files inside directory called as name. " +
"If its not specified then creates files inside current directory.";
builder(yargs: any) {
return yargs
.option("c", {
alias: "connection",
default: "default",
describe: "Name of the connection on which to run a query"
})
.option("n", {
alias: "name",
describe: "Name of the project directory."
})
.option("d", {
alias: "docker",
describe: "Set to true if docker-compose must be generated as well. False by default."
});
}
async handler(argv: any) {
try {
const isDocker = argv.docker !== undefined ? true : false;
const basePath = process.cwd() + (argv.name ? ("/" + argv.name) : "");
await CommandUtils.createFile(basePath + "/package.json", InitCommand.getPackageJsonTemplate(), false);
if (isDocker)
await CommandUtils.createFile(basePath + "/docker-compose.yml", InitCommand.getDockerComposeTemplate(), false);
await CommandUtils.createFile(basePath + "/README.md", InitCommand.getReadmeTemplate({ docker: isDocker }), false);
await CommandUtils.createFile(basePath + "/tsconfig.json", InitCommand.getTsConfigTemplate());
await CommandUtils.createFile(basePath + "/ormconfig.json", InitCommand.getOrmConfigTemplate());
await CommandUtils.createFile(basePath + "/src/entity/User.ts", InitCommand.getUserEntityTemplate());
await CommandUtils.createFile(basePath + "/src/index.ts", InitCommand.getAppIndexTemplate());
await CommandUtils.createDirectories(basePath + "/src/migration");
const packageJsonContents = await CommandUtils.readFile(basePath + "/package.json");
await CommandUtils.createFile(basePath + "/package.json", InitCommand.appendPackageJson(packageJsonContents));
if (argv.name) {
console.log(chalk.green(`Project created inside ${chalk.blue(basePath)} directory.`));
} else {
console.log(chalk.green(`Project created inside current directory.`));
}
} catch (err) {
console.log(chalk.black.bgRed("Error during project initialization:"));
console.error(err);
}
}
// -------------------------------------------------------------------------
// Protected Static Methods
// -------------------------------------------------------------------------
/**
* Gets contents of the ormconfig file.
*/
protected static getOrmConfigTemplate(): string {
return JSON.stringify({
type: "mysql",
host: "localhost",
port: 3306,
username: "test",
password: "test",
database: "test",
syncrhonize: true,
logging: false,
entities: [
"src/entity/**/*.ts"
],
migrations: [
"src/migration/**/*.ts"
],
subscribers: [
"src/subscriber/**/*.ts"
]
}, undefined, 3);
}
/**
* Gets contents of the ormconfig file.
*/
protected static getTsConfigTemplate(): string {
return JSON.stringify({
compilerOptions: {
lib: ["es5", "es6"],
target: "es5",
module: "commonjs",
moduleResolution: "node",
emitDecoratorMetadata: true,
experimentalDecorators: true,
sourceMap: true
}
}
, undefined, 3);
}
/**
* Gets contents of the user entity.
*/
protected static getUserEntityTemplate(): string {
return `import {Entity, PrimaryGeneratedColumn, Column} from "typeorm";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
firstName: string;
@Column()
lastName: string;
@Column()
age: number;
}
`;
}
/**
* Gets contents of the main (index) application file.
*/
protected static getAppIndexTemplate(): string {
return `import "reflect-metadata";
import {createConnection} from "typeorm";
import {User} from "./entity/User";
createConnection().then(async connection => {
console.log("Inserting a new user into the database...");
const user = new User();
user.firstName = "Timber";
user.lastName = "Saw";
user.age = 25;
await connection.manager.save(user);
console.log("Saved a new user with id: " + user.id);
console.log("Loading users from the database...");
const users = await connection.manager.find(User);
console.log("Loaded users: ", users);
console.log("Here you can setup and run express/koa/any other framework.");
});
`;
}
/**
* Gets contents of the new package.json file.
*/
protected static getPackageJsonTemplate(): string {
return JSON.stringify({
name: "typeorm",
version: "0.0.1",
description: "Awesome project developed with TypeORM.",
devDependencies: {
},
dependencies: {
},
scripts: {
}
}, undefined, 3);
}
/**
* Gets contents of the new docker-compose.yml file.
*/
protected static getDockerComposeTemplate(): string {
return `version: '3'
services:
mysql:
image: "mysql:5.7.10"
container_name: "typeorm-mysql"
ports:
- "3306:3306"
environment:
MYSQL_ROOT_PASSWORD: "admin"
MYSQL_USER: "test"
MYSQL_PASSWORD: "test"
MYSQL_DATABASE: "test"
`;
}
/**
* Gets contents of the new readme.md file.
*/
protected static getReadmeTemplate(options: { docker: boolean }): string {
let template = `# Awesome Project Build with TypeORM
Steps to run this project:
1. Run \`npm i\` command
`;
if (options.docker) {
template += `2. Run \`docker-compose up\` command
`;
} else {
template += `2. Setup database settings inside \`ormconfig.json\` file
`;
}
template += `3. Run \`npm start\` command
`;
return template;
}
/**
* Appends to a given package.json template everything needed.
*/
protected static appendPackageJson(packageJsonContents: string/*, docker: boolean*/): string {
const packageJson = JSON.parse(packageJsonContents);
if (!packageJson.devDependencies) packageJson.devDependencies = {};
Object.assign(packageJson.devDependencies, {
"ts-node": "3.3.0",
typescript: "2.5.2"
});
if (!packageJson.dependencies) packageJson.dependencies = {};
Object.assign(packageJson.dependencies, {
typeorm: "0.1.0-alpha.42" // require("../package.json").version
});
if (!packageJson.scripts) packageJson.scripts = {};
Object.assign(packageJson.scripts, {
start: /*(docker ? "docker-compose up && " : "") + */"ts-node src/index.ts"
});
return JSON.stringify(packageJson, undefined, 3);
}
}

View File

@ -0,0 +1,48 @@
const exec = require("child_process").exec;
/**
* Shows typeorm version.
*/
export class VersionCommand {
command = "version";
describe = "Prints TypeORM version this project uses.";
async handler(argv: any) {
const localNpmList = await this.executeCommand("npm list --depth=0");
const localMatches = localNpmList.match(/ typeorm@(.*)\n/);
const localNpmVersion = (localMatches && localMatches[1] ? localMatches[1] : "").replace(/"invalid"/gi, "").trim();
const globalNpmList = await this.executeCommand("npm list -g --depth=0");
const globalMatches = globalNpmList.match(/ typeorm@(.*)\n/);
const globalNpmVersion = (globalMatches && globalMatches[1] ? globalMatches[1] : "").replace(/"invalid"/gi, "").trim();
if (localNpmVersion) {
console.log("Local installed version:", localNpmVersion);
} else {
console.log("No local installed TypeORM was found.");
}
if (globalNpmVersion) {
console.log("Global installed TypeORM version:", globalNpmVersion);
} else {
console.log("No global installed was found.");
}
if (localNpmVersion && globalNpmVersion && localNpmVersion !== globalNpmVersion) {
console.log("To avoid issues with CLI please make sure your global and local TypeORM versions match, " +
"or you are using locally installed TypeORM instead of global one.");
}
}
protected executeCommand(command: string) {
return new Promise<string>((ok, fail) => {
exec(command, (error: any, stdout: any, stderr: any) => {
if (stdout) return ok(stdout);
if (stderr) return ok(stderr);
if (error) return fail(error);
ok("");
});
});
}
}