typesql-cli
Advanced tools
Comparing version 0.4.0 to 0.4.1
39
cli.js
@@ -23,2 +23,3 @@ #!/usr/bin/env node | ||
const sql_generator_1 = require("./sql-generator"); | ||
const Either_1 = require("fp-ts/lib/Either"); | ||
function parseArgs() { | ||
@@ -33,2 +34,12 @@ return yargs_1.default | ||
}) | ||
.command('init', 'generate config file', () => { | ||
const config = { | ||
"databaseUri": "mysql://root:password@localhost/mydb", | ||
"sqlDir": "./sqls", | ||
"target": "node" | ||
}; | ||
const configPath = "./typesql.json"; | ||
code_generator_1.writeFile(configPath, JSON.stringify(config, null, 4)); | ||
console.log("Init file generated:", configPath); | ||
}) | ||
.command(['compile [options]', 'c [options]'], 'Compile the queries and generate ts files', yargs => { | ||
@@ -46,3 +57,3 @@ return yargs | ||
}) | ||
.command(['generate <option> <sql-name>', 'g <option> <sql-name>'], 'generate sql files templates', yargs => { | ||
.command(['generate <option> <sql-name>', 'g <option> <sql-name>'], 'generate sql queries', yargs => { | ||
return yargs | ||
@@ -103,3 +114,7 @@ .positional('option', { | ||
const client = new queryExectutor_1.DbClient(); | ||
yield client.connect(databaseUri); | ||
const result = yield client.connect(databaseUri); | ||
if (Either_1.isLeft(result)) { | ||
console.error(`Error: ${result.left.description}.`); | ||
return; | ||
} | ||
const filesGeneration = sqlFiles.map(sqlFile => code_generator_1.generateTsFile(client, sqlFile, target)); | ||
@@ -120,4 +135,18 @@ yield Promise.all(filesGeneration); | ||
const client = new queryExectutor_1.DbClient(); | ||
yield client.connect(databaseUri); | ||
const columns = yield client.loadTableSchema(tableName); | ||
const connectionResult = yield client.connect(databaseUri); | ||
if (Either_1.isLeft(connectionResult)) { | ||
console.error(connectionResult.left.name); | ||
return false; | ||
} | ||
const columnsOption = yield client.loadTableSchema(tableName); | ||
if (Either_1.isLeft(columnsOption)) { | ||
console.error(columnsOption.left.description); | ||
return false; | ||
} | ||
const columns = columnsOption.right; | ||
if (columns.length == 0) { | ||
console.error(`Got no columns for table '${tableName}'. Did you type the table name correclty?`); | ||
client.closeConnection(); | ||
return false; | ||
} | ||
client.closeConnection(); | ||
@@ -127,2 +156,4 @@ let generatedSql = generateSql(stmtType, tableName, columns); | ||
code_generator_1.writeFile(filePath, generatedSql); | ||
console.log("Generated file:", filePath); | ||
return true; | ||
}); | ||
@@ -129,0 +160,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import { SchemaDef, InvalidSqlError, PreprocessedSql } from "./types"; | ||
import { SchemaDef, TypeSqlError, PreprocessedSql } from "./types"; | ||
import { DbClient } from "./queryExectutor"; | ||
@@ -8,4 +8,4 @@ import { Either } from "fp-ts/lib/Either"; | ||
export declare function verifyNotInferred(type: InferType): MySqlType; | ||
export declare function parseSql(client: DbClient, sql: string): Promise<Either<InvalidSqlError, SchemaDef>>; | ||
export declare function parseSql(client: DbClient, sql: string): Promise<Either<TypeSqlError, SchemaDef>>; | ||
export declare function preprocessSql(sql: string): PreprocessedSql; | ||
//# sourceMappingURL=describe-query.d.ts.map |
@@ -137,4 +137,7 @@ "use strict"; | ||
const dbSchema = yield client.loadDbSchema(); | ||
if (Either_1.isLeft(dbSchema)) { | ||
return Either_1.left(dbSchema.left); | ||
} | ||
try { | ||
const result = describeSql(dbSchema, processedSql, namedParameters); | ||
const result = describeSql(dbSchema.right, processedSql, namedParameters); | ||
return Either_1.right(result); | ||
@@ -141,0 +144,0 @@ } |
{ | ||
"name": "typesql-cli", | ||
"version": "0.4.0", | ||
"version": "0.4.1", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -1,19 +0,14 @@ | ||
import { FieldPacket } from "mysql2/promise"; | ||
import { Either } from "fp-ts/lib/Either"; | ||
import { FieldDescriptor, InvalidSqlError } from "./types"; | ||
import { TypeSqlError } from "./types"; | ||
import { ColumnSchema, ColumnSchema2 } from "./mysql-query-analyzer/types"; | ||
export declare class DbClient { | ||
private connection; | ||
connect(connectionUri: string): Promise<void>; | ||
connect(connectionUri: string): Promise<Either<TypeSqlError, true>>; | ||
closeConnection(): Promise<void>; | ||
loadDbSchema(): Promise<ColumnSchema[]>; | ||
loadTableSchema(tableName: string): Promise<ColumnSchema2[]>; | ||
loadDbSchema(): Promise<Either<TypeSqlError, ColumnSchema[]>>; | ||
loadTableSchema(tableName: string): Promise<Either<TypeSqlError, ColumnSchema2[]>>; | ||
createParams(sql: string, paramValue: '1' | '?'): string[]; | ||
explainSql(sql: string): Promise<Either<InvalidSqlError, boolean>>; | ||
createInvalidSqlError(err: any): Either<InvalidSqlError, never>; | ||
executeQuery(query: string): Promise<Either<InvalidSqlError, FieldDescriptor[]>>; | ||
executeExpression(expr: string, from?: string): Promise<FieldDescriptor[]>; | ||
fieldPacketToFieldDescriptor(field: FieldPacket): FieldDescriptor; | ||
functionParamType(functionName: string): "double" | "varchar"; | ||
explainSql(sql: string): Promise<Either<TypeSqlError, boolean>>; | ||
createInvalidSqlError(err: any): Either<TypeSqlError, never>; | ||
} | ||
//# sourceMappingURL=queryExectutor.d.ts.map |
@@ -18,7 +18,20 @@ "use strict"; | ||
const Either_1 = require("fp-ts/lib/Either"); | ||
const mysql_mapping_1 = require("./mysql-mapping"); | ||
const connectionNotOpenError = { | ||
name: 'Connection error', | ||
description: 'The database connection is not open.' | ||
}; | ||
class DbClient { | ||
connect(connectionUri) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.connection = yield promise_1.default.createConnection(connectionUri); | ||
try { | ||
this.connection = yield promise_1.default.createConnection(connectionUri); | ||
return Either_1.right(true); | ||
} | ||
catch (e) { | ||
const connError = { | ||
name: 'Connection error', | ||
description: e.message | ||
}; | ||
return Either_1.left(connError); | ||
} | ||
}); | ||
@@ -28,3 +41,5 @@ } | ||
return __awaiter(this, void 0, void 0, function* () { | ||
this.connection.end(); | ||
if (this.connection != null) { | ||
this.connection.end(); | ||
} | ||
}); | ||
@@ -40,4 +55,10 @@ } | ||
`; | ||
return this.connection.execute(sql) | ||
.then(res => res[0]); | ||
if (this.connection != null) { | ||
return this.connection.execute(sql) | ||
.then(res => { | ||
const columns = res[0]; | ||
return Either_1.right(columns); | ||
}); | ||
} | ||
return Either_1.left(connectionNotOpenError); | ||
}); | ||
@@ -60,4 +81,10 @@ } | ||
`; | ||
return this.connection.execute(sql, [tableName]) | ||
.then(res => res[0]); | ||
if (this.connection) { | ||
return this.connection.execute(sql, [tableName]) | ||
.then(res => { | ||
const columns = res[0]; | ||
return Either_1.right(columns); | ||
}); | ||
} | ||
return Either_1.left(connectionNotOpenError); | ||
}); | ||
@@ -75,7 +102,10 @@ } | ||
return __awaiter(this, void 0, void 0, function* () { | ||
//@ts-ignore | ||
return this.connection.prepare(sql) | ||
.then(() => { | ||
return Either_1.right(true); | ||
}).catch((err) => this.createInvalidSqlError(err)); | ||
if (this.connection) { | ||
//@ts-ignore | ||
return this.connection.prepare(sql) | ||
.then(() => { | ||
return Either_1.right(true); | ||
}).catch((err) => this.createInvalidSqlError(err)); | ||
} | ||
return Either_1.left(connectionNotOpenError); | ||
}); | ||
@@ -90,49 +120,4 @@ } | ||
} | ||
executeQuery(query) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const params = this.createParams(query, '?'); | ||
try { | ||
const [columns, fields] = yield this.connection | ||
.query(`${query} LIMIT 0`, params); | ||
const columnsSchema = fields.map(field => this.fieldPacketToFieldDescriptor(field)); | ||
return Either_1.right(columnsSchema); | ||
} | ||
catch (err) { | ||
return this.createInvalidSqlError(err); | ||
} | ||
; | ||
}); | ||
} | ||
executeExpression(expr, from) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const query = `select ${expr}` + (from ? ` ${from} LIMIT 0` : ''); | ||
let params = this.createParams(query, '?'); | ||
const [columns, fields] = yield this.connection.execute(`${query.toLowerCase()}`, params); | ||
return fields.map(field => this.fieldPacketToFieldDescriptor(field)); | ||
}); | ||
} | ||
fieldPacketToFieldDescriptor(field) { | ||
const fieldDescriptor = { | ||
name: field.name, | ||
column: field.orgName, | ||
columnType: mysql_mapping_1.convertTypeCodeToMysqlType(field.columnType, field.flags, field.columnLength), | ||
notNull: mysql_mapping_1.checkFlag(field.flags, mysql_mapping_1.FlagEnum.NOT_NULL) | ||
}; | ||
return fieldDescriptor; | ||
} | ||
functionParamType(functionName) { | ||
switch (functionName.toLowerCase()) { | ||
case 'abs': | ||
case 'acos': | ||
case 'asin': | ||
case 'atan': | ||
case 'atan2': | ||
case 'ceil': | ||
return 'double'; | ||
default: | ||
return 'varchar'; | ||
} | ||
} | ||
} | ||
exports.DbClient = DbClient; | ||
//# sourceMappingURL=queryExectutor.js.map |
@@ -1,5 +0,3 @@ | ||
Obs.: This is a WIP experimental project. | ||
Typesql: Generate type safe api for **mysql** databases. | ||
Typesql: Generate type safe code for **mysql** database. | ||
## Example | ||
@@ -15,4 +13,3 @@ | ||
WHERE discontinued = 0 | ||
AND list_price > :minPrice | ||
AND list_price < :maxPrice | ||
AND list_price BETWEEN :minPrice AND :maxPrice | ||
``` | ||
@@ -29,5 +26,17 @@ | ||
1. Write your queries in a determined folder, like this: | ||
1. *npm install -g typesql-cli* | ||
2. Add the `typesql.json` configuration file in project root folder. You can generate an template with cli command `typesql init`. | ||
```json | ||
{ | ||
"databaseUri": "mysql://root:password@localhost/mydb", | ||
"sqlDir": "./sqls", | ||
"target": "node" | ||
} | ||
``` | ||
3. Write your queries in the folder specified in the configuration file. You can also use the cli to scaffold the queries. | ||
``` | ||
sqls\ | ||
@@ -39,6 +48,4 @@ select-products.sql | ||
2. Then run `npx typesql-cli -w -t=deno -d mysql://root:password@localhost/mydb .\sqls` to start typesql in watch mode and generate code targeting the deno runtime. | ||
4. Then run `typesql compile --watch` to start typesql in watch mode. After that you will have one Typescript file for each query file. | ||
3. After that you will have one Typescript file for each query file. | ||
``` | ||
@@ -54,3 +61,3 @@ sqls\ | ||
4. Now you can import and use the generated code | ||
5. Now you can import and use the generated code. | ||
@@ -64,3 +71,10 @@ ``` | ||
# Examples | ||
[Query scaffolding](/docs/query_scaffolding.md) | ||
[Order by and limit clauses](/docs/orderBy_limit.md) | ||
[Order by and limit clauses](/docs/orderBy_limit.md) | ||
# Project status | ||
**WARNING:** This is an WIP experimental project. It is under active development and its API can change. | ||
Issues reports and feature requests are welcome. |
@@ -75,3 +75,3 @@ import { MySqlType } from "./mysql-mapping"; | ||
}; | ||
export declare type InvalidSqlError = { | ||
export declare type TypeSqlError = { | ||
name: string; | ||
@@ -78,0 +78,0 @@ description: string; |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
284494
3574
75