Skip to content

Commit 0a25c0d

Browse files
committed
Fix all
1 parent ee624f6 commit 0a25c0d

7 files changed

Lines changed: 142 additions & 82 deletions

File tree

__tests__/ddl.spec.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { getDBConfig, getSpace, getTable } from './utils';
2-
import { QueryResult, SQParam } from '../src/skytable';
32

43
const testSpace = 'ddltestspace';
54

__tests__/dml.spec.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Rows } from '../src/skytable';
1+
import type { Rows } from '../src';
22
import { getDBConfig, getTable } from './utils';
33

44
describe('DML', () => {

examples/test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Row } from './../src/skytable';
1+
import type { Row } from '../src';
22
import { Config } from '../src';
33

44
async function test() {

src/config.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
33
createConnection,
44
createConnectionTls,
55
} from './connection';
6-
import { createSkytable } from './skytable';
6+
import { createDB } from './skytable';
77
import { bufferToHandshakeResult, getClientHandshake } from './protocol';
88
import type {
99
ConnectionOptions as ConnectionTLSOptions,
@@ -81,6 +81,9 @@ export class Config {
8181
return this.connection;
8282
}
8383

84+
/**
85+
* connect to Skytable
86+
*/
8487
async connect() {
8588
const connect = await createConnection({
8689
port: this.port,
@@ -93,10 +96,13 @@ export class Config {
9396

9497
this.connection = connect;
9598

96-
return createSkytable(connect);
99+
return createDB(connect);
97100
}
98101

99-
async connectTSL(options: ConnectionTLSOptions) {
102+
/**
103+
* connect to Skytable
104+
*/
105+
async connectTLS(options: ConnectionTLSOptions) {
100106
const connect = await createConnectionTls({
101107
port: this.port,
102108
host: this.host,
@@ -109,9 +115,12 @@ export class Config {
109115

110116
this.connection = connect;
111117

112-
return createSkytable(connect);
118+
return createDB(connect);
113119
}
114120

121+
/**
122+
* disconnect from Skytable
123+
*/
115124
async disconnect() {
116125
if (this.connection) {
117126
this.connection.destroySoon();

src/protocol.ts

Lines changed: 54 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Config } from './config';
22
import type { Column, QueryResult, Row, Rows, SQParam } from './skytable';
3+
import { Query } from './query';
34

45
const PARAMS_TYPE = {
56
NULL: '\x00',
@@ -38,67 +39,60 @@ const HANDSHAKE_RESULT = {
3839
ERROR: 'H01',
3940
};
4041

41-
function isResponsesResult(type: number): boolean {
42-
return Object.values(RESPONSES_RESULT).includes(type);
43-
}
44-
4542
function isFloat(number: number | string): boolean {
4643
return Number.isFinite(number) && !Number.isInteger(number);
4744
}
4845

49-
export function encodeParams(parameters: SQParam[]): string {
50-
if (!parameters.length) {
51-
return '';
46+
export function encodeParam(param: SQParam): string {
47+
// 5 A binary blob [5<size>\n<payload>]
48+
if (Buffer.isBuffer(param)) {
49+
return [PARAMS_TYPE.BINARY, param.length, '\n', param.toString()].join('');
5250
}
5351

54-
return parameters
55-
.map((param) => {
56-
switch (typeof param) {
57-
case 'string':
58-
return [PARAMS_TYPE.STRING, param.length, '\n', param].join('');
59-
case 'number':
60-
// 2 Unsigned integer 64
61-
// 3 Signed integer 64
62-
// 4 Float A 64-bit
63-
return [
64-
isFloat(param)
65-
? PARAMS_TYPE.FLOAT
66-
: param < 0
67-
? PARAMS_TYPE.SINT
68-
: PARAMS_TYPE.UINT,
69-
String(param),
70-
'\n',
71-
].join('');
72-
case 'bigint':
73-
return [
74-
param < 0 ? PARAMS_TYPE.SINT : PARAMS_TYPE.UINT,
75-
String(param),
76-
'\n',
77-
].join('');
78-
case 'boolean':
79-
return [PARAMS_TYPE.BOOLEAN, Number(param) === 1 ? '\x01' : 0].join(
80-
'',
81-
);
82-
default:
83-
// 5 A binary blob [5<size>\n<payload>]
84-
if (Buffer.isBuffer(param)) {
85-
return [
86-
PARAMS_TYPE.BINARY,
87-
param.length,
88-
'\n',
89-
param.toString(),
90-
].join('');
91-
}
92-
// null undefined
93-
if (param == null) {
94-
return '\x00';
95-
}
96-
throw new TypeError(
97-
`un support type: ${typeof param}, val: ${param}`,
98-
);
99-
}
100-
})
101-
.join('');
52+
// null undefined
53+
if (param == null) {
54+
return '\x00';
55+
}
56+
57+
switch (typeof param) {
58+
case 'string':
59+
return [PARAMS_TYPE.STRING, param.length, '\n', param].join('');
60+
case 'number':
61+
// 2 Unsigned integer 64
62+
// 3 Signed integer 64
63+
// 4 Float A 64-bit
64+
return [
65+
isFloat(param)
66+
? PARAMS_TYPE.FLOAT
67+
: param < 0
68+
? PARAMS_TYPE.SINT
69+
: PARAMS_TYPE.UINT,
70+
String(param),
71+
'\n',
72+
].join('');
73+
case 'bigint':
74+
return [
75+
param < 0 ? PARAMS_TYPE.SINT : PARAMS_TYPE.UINT,
76+
String(param),
77+
'\n',
78+
].join('');
79+
case 'boolean':
80+
return [PARAMS_TYPE.BOOLEAN, Number(param) === 1 ? '\x01' : 0].join('');
81+
default:
82+
throw new TypeError(`un support type: ${typeof param}, val: ${param}`);
83+
}
84+
}
85+
86+
export function encodeParams(parameters: SQParam[]): string {
87+
return parameters.map(encodeParam).join('');
88+
}
89+
90+
export function encodeQuery(query: Query): Buffer {
91+
const dataframe = `${query.getQuery()}${query.getParams().join('')}`;
92+
const data = [query.getQueryLength(), '\n', dataframe];
93+
const requestData = ['S', data.join('').length, '\n', ...data];
94+
95+
return Buffer.from(requestData.join(''), 'utf-8');
10296
}
10397

10498
function getFirstSplitOffset(buffer: Buffer, split = '\n'): number {
@@ -251,13 +245,12 @@ export function formatResponse(buffer: Buffer): QueryResult {
251245
`response error code: ${buffer.subarray(1, 2).readInt8()}`,
252246
);
253247
default:
254-
if (isResponsesResult(type)) {
255-
const [val] = parseSingleVal(buffer);
256-
257-
return val;
258-
}
259-
throw new TypeError('unknown response type');
248+
break;
260249
}
250+
251+
const [val] = parseSingleVal(buffer);
252+
253+
return val;
261254
}
262255

263256
export function getClientHandshake(config: Config): string {

src/query.ts

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
import { encodeParam } from './protocol';
2+
import { SQParam } from './skytable';
3+
4+
export class Query {
5+
private query: string;
6+
private params: string[];
7+
8+
/**
9+
* Create a new query with the base query set. You can now add (any) additional parameters.
10+
*
11+
* @param query The base query
12+
*/
13+
constructor(query: string) {
14+
this.query = query;
15+
this.params = [];
16+
}
17+
/**
18+
* Get the query string
19+
* @returns query string
20+
*/
21+
getQuery(): string {
22+
return this.query;
23+
}
24+
25+
/**
26+
* Get the Params
27+
* @returns params encoded string
28+
*/
29+
getParams(): string[] {
30+
return this.params;
31+
}
32+
/**
33+
* Get the number of parameters
34+
*
35+
* @returns Returns a count of the number of parameters
36+
*/
37+
public getParamCount(): number {
38+
return this.params.length;
39+
}
40+
41+
/**
42+
* Get the query length
43+
*
44+
* @returns Returns the length of the query
45+
*/
46+
public getQueryLength(): number {
47+
return this.query.length;
48+
}
49+
/**
50+
*
51+
* Add a new parameter to your query
52+
*
53+
* @param param Query input parameter
54+
*/
55+
public pushParam(param: SQParam): void {
56+
this.params.push(encodeParam(param));
57+
}
58+
}

src/skytable.ts

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
import { Socket } from 'node:net';
22
import { TLSSocket } from 'node:tls';
33
import { connectionWrite } from './connection';
4-
import { encodeParams, formatResponse } from './protocol';
5-
6-
export type ConnectionOptions = {
7-
port: number;
8-
hostname: string;
9-
};
10-
11-
export type ConnectionTlsOptions = ConnectionOptions & { certFile: string };
4+
import { encodeQuery, formatResponse } from './protocol';
5+
import { Query } from './query';
126

137
export type ColumnBase = string | number | boolean | null | bigint;
148

@@ -30,15 +24,22 @@ export type Rows = Row[];
3024

3125
export type QueryResult = Column | Row | Rows;
3226

33-
export function createSkytable(connection: Socket | TLSSocket) {
27+
/**
28+
* create a db instance
29+
* @param connection The connection to Skytable
30+
* @returns { query: (query: string | Query, ...params: SQParam[]) => Promise<QueryResult> }
31+
*/
32+
export function createDB(connection: Socket | TLSSocket) {
3433
const query = async (
35-
query: string,
34+
query: string | Query,
3635
...params: SQParam[]
3736
): Promise<QueryResult> => {
38-
const dataframe = `${query}${encodeParams(params)}`;
39-
const data = [query.length, '\n', dataframe];
40-
const requestData = ['S', data.join('').length, '\n', ...data];
41-
const buffer = Buffer.from(requestData.join(''), 'utf-8');
37+
const queryInstance = typeof query === 'string' ? new Query(query) : query;
38+
params.forEach((param) => {
39+
queryInstance.pushParam(param);
40+
});
41+
42+
const buffer = encodeQuery(queryInstance);
4243

4344
const res = await connectionWrite(connection, buffer);
4445

0 commit comments

Comments
 (0)