@@ -2,6 +2,7 @@ const axios = require("axios");
2
2
const https = require ( 'node:https' ) ;
3
3
const http2 = require ( "http2" ) ;
4
4
const { ksqlDBError } = require ( "./customErrors.js" ) ;
5
+ const validateInputs = require ( './validateInputs.js' ) ;
5
6
const queryBuilder = require ( './queryBuilder.js' ) ;
6
7
const builder = new queryBuilder ( ) ;
7
8
@@ -34,10 +35,14 @@ class ksqljs {
34
35
* Example: [{object that contains the metadata}, [data], [data], ...}]
35
36
*/
36
37
pull = ( query ) => {
38
+ validateInputs ( [ query , 'string' , 'query' ] ) ;
39
+
40
+ const validatedQuery = builder . build ( query ) ;
41
+
37
42
return axios
38
43
. post ( this . ksqldbURL + "/query-stream" ,
39
44
{
40
- sql : query ,
45
+ sql : validatedQuery ,
41
46
} ,
42
47
{
43
48
headers :
@@ -70,6 +75,9 @@ class ksqljs {
70
75
* result if successful.
71
76
*/
72
77
push ( query , cb ) {
78
+ validateInputs ( [ query , 'string' , 'query' , true ] , [ cb , 'function' , 'cb' , true ] ) ;
79
+ const validatedQuery = builder . build ( query ) ;
80
+
73
81
return new Promise ( ( resolve , reject ) => {
74
82
let sentQueryId = false ;
75
83
const session = http2 . connect (
@@ -94,7 +102,7 @@ class ksqljs {
94
102
) ;
95
103
96
104
const reqBody = {
97
- sql : query ,
105
+ sql : validatedQuery ,
98
106
Accept : "application/json, application/vnd.ksqlapi.delimited.v1" ,
99
107
} ;
100
108
@@ -133,6 +141,8 @@ class ksqljs {
133
141
* if the termination was successful.
134
142
*/
135
143
terminate ( queryId ) {
144
+ validateInputs ( [ queryId , 'string' , 'queryId' ] ) ;
145
+
136
146
return axios . post ( this . ksqldbURL + '/ksql' ,
137
147
{
138
148
ksql : `TERMINATE ${ queryId } ;`
@@ -164,9 +174,13 @@ class ksqljs {
164
174
* @return {Promise } a promise that completes once the server response is received, and returns the requested data.
165
175
*/
166
176
ksql ( query ) {
177
+ validateInputs ( [ query , 'string' , 'query' ] ) ;
178
+
179
+ const validatedQuery = builder . build ( query ) ;
180
+
167
181
return axios . post ( this . ksqldbURL + '/ksql' ,
168
182
{
169
- ksql : query
183
+ ksql : validatedQuery
170
184
} ,
171
185
{
172
186
headers :
@@ -200,9 +214,8 @@ class ksqljs {
200
214
* @return {Promise } a promise that completes once the server response is received, and returns a response object.
201
215
*/
202
216
createStream ( name , columnsType , topic , value_format = 'json' , partitions = 1 , key ) {
203
- if ( typeof name !== 'string' || typeof columnsType !== 'object' || typeof topic !== 'string' || typeof partitions !== 'number' ) {
204
- return console . log ( "invalid input(s)" )
205
- }
217
+ validateInputs ( [ name , 'string' , 'name' , true ] , [ columnsType , 'object' , 'columnsType' , true ] , [ topic , 'string' , 'topic' ] , [ partitions , 'number' , 'partitions' ] ) ;
218
+
206
219
const columnsTypeString = columnsType . reduce ( ( result , currentType ) => result + ', ' + currentType ) ;
207
220
const query = `CREATE STREAM ${ name } (${ columnsTypeString } ) WITH (kafka_topic='${ topic } ', value_format='${ value_format } ', partitions=${ partitions } );` ;
208
221
@@ -216,7 +229,6 @@ class ksqljs {
216
229
{ } ,
217
230
httpsAgent : this . httpsAgentAxios ? this . httpsAgentAxios : null ,
218
231
} )
219
- . then ( res => res )
220
232
. catch ( error => {
221
233
throw error . response ?. data [ '@type' ] ? new ksqlDBError ( error . response . data ) : error ;
222
234
} ) ;
@@ -233,6 +245,8 @@ class ksqljs {
233
245
* @returns {Promise } - a promise that completes once the server response is received, and returns a query ID
234
246
*/
235
247
createStreamAs = ( streamName , selectColumns , sourceStream , propertiesObj , conditions , partitionBy ) => {
248
+ validateInputs ( [ streamName , 'string' , 'streamName' , true ] , [ selectColumns , 'array' , 'selectColumns' , true ] , [ sourceStream , 'string' , 'sourceStream' , true ] , [ propertiesObj , 'object' , 'propertiesObj' ] , [ conditions , 'string' , 'conditions' ] , [ partitionBy , 'string' , 'partitionBy' ] ) ;
249
+
236
250
const propertiesArgs = [ ] ;
237
251
const selectColStr = selectColumns . reduce ( ( result , current ) => result + ', ' + current ) ;
238
252
// begin with first consistent portion of query
@@ -283,6 +297,8 @@ class ksqljs {
283
297
* @return {Promise } a promise that completes once the server response is received, and returns a response object.
284
298
*/
285
299
createTable = ( name , columnsType , topic , value_format = 'json' , partitions ) => {
300
+ validateInputs ( [ name , 'string' , 'name' , true ] , [ columnsType , 'array' , 'columnsType' , true ] , [ topic , 'string' , 'topic' , true ] , [ value_format , 'string' , 'value_format' , true ] , [ partitions , 'number' , 'partitions' ] ) ;
301
+
286
302
const columnsTypeString = columnsType . reduce ( ( result , currentType ) => result + ', ' + currentType ) ;
287
303
const query = `CREATE TABLE ${ name } (${ columnsTypeString } ) WITH (kafka_topic='${ topic } ', value_format='${ value_format } ', partitions=${ partitions } );`
288
304
@@ -321,6 +337,8 @@ class ksqljs {
321
337
* @returns {Promise } a promise that completes once the server response is received, returning a response object
322
338
*/
323
339
createTableAs = ( tableName , source , selectArray , propertiesObj , conditionsObj ) => {
340
+ validateInputs ( [ tableName , 'string' , 'tableName' , true ] , [ source , 'string' , 'source' , true ] , [ selectArray , 'array' , 'selectArray' , true ] , [ propertiesObj , 'object' , 'propertiesObj' ] , [ conditionsObj , 'object' , 'conditionsObj' ] ) ;
341
+
324
342
let selectColStr = selectArray . reduce ( ( result , current ) => result + ', ' + current ) ;
325
343
326
344
// expect user to input properties object of format {topic: ... , value_format: ..., partitions: ...}
@@ -387,6 +405,8 @@ class ksqljs {
387
405
*/
388
406
//---------------------Insert Rows Into Existing Streams-----------------
389
407
insertStream = ( stream , rows ) => {
408
+ validateInputs ( [ stream , 'string' , 'stream' , true ] , [ rows , 'array' , 'rows' , true ] ) ;
409
+
390
410
return new Promise ( ( resolve , reject ) => {
391
411
const msgOutput = [ ] ;
392
412
@@ -453,13 +473,8 @@ class ksqljs {
453
473
* the end of the array that includes the time that the data was inserted into the ksqldb.
454
474
*/
455
475
pullFromTo = async ( streamName , timezone = 'Greenwich' , from = [ undefined , '00' , '00' , '00' ] , to = [ '2200-03-14' , '00' , '00' , '00' ] ) => {
456
- if ( ! streamName || typeof timezone !== 'string' || ! from
457
- || typeof from [ 0 ] !== 'string' || typeof from [ 1 ] !== 'string' || typeof from [ 2 ] !== 'string' || typeof from [ 3 ] !== 'string'
458
- || typeof to [ 0 ] !== 'string' || typeof to [ 1 ] !== 'string' || typeof to [ 2 ] !== 'string' || typeof to [ 3 ] !== 'string'
459
- || from [ 0 ] . length !== 10 || to [ 0 ] . length !== 10 || from [ 1 ] . length !== 2 || to [ 1 ] . length !== 2 || from [ 2 ] . length !== 2 || to [ 2 ] . length !== 2 || from [ 3 ] . length !== 2 || to [ 3 ] . length !== 2
460
- ) {
461
- return new Error ( 'invalid inputs' ) ;
462
- }
476
+ validateInputs ( [ streamName , 'string' , 'streamName' , true ] , [ timezone , 'string' , 'timezone' , true ] , [ from , 'array' , 'from' , true ] , [ to , 'array' , 'to' , true ] ) ;
477
+
463
478
const userFrom = `${ from [ 0 ] } T${ from [ 1 ] } :${ from [ 2 ] } :${ from [ 3 ] } ` ;
464
479
const userTo = `${ to [ 0 ] } T${ to [ 1 ] } :${ to [ 2 ] } :${ to [ 3 ] } ` ;
465
480
const userFromUnix = new Date ( userFrom ) . getTime ( ) ;
@@ -491,6 +506,8 @@ class ksqljs {
491
506
* message (string): Detailed message regarding the status of the execution statement.
492
507
*/
493
508
inspectQueryStatus ( commandId ) {
509
+ validateInputs ( [ commandId , 'string' , 'commandId' , true ] ) ;
510
+
494
511
return axios . get ( this . ksqldbURL + `/status/${ commandId } ` )
495
512
. then ( response => response )
496
513
. catch ( error => {
@@ -561,6 +578,8 @@ class ksqljs {
561
578
* @return {Promise } this method returns a promise that returns a response object.
562
579
*/
563
580
terminateCluster ( topicsToDelete = [ ] ) {
581
+ validateInputs ( [ topicsToDelete , 'array' , 'topicsToDelete' , true ] ) ;
582
+
564
583
return axios . post ( this . ksqldbURL + `/ksql/terminate` , {
565
584
"deleteTopicList" : topicsToDelete
566
585
} , {
@@ -591,9 +610,12 @@ class ksqljs {
591
610
* "message": "One or more properties overrides set locally are prohibited by the KSQL server (use UNSET to reset their default value): [ksql.service.id]"
592
611
* }
593
612
*
613
+ * @param {string } propertyName - the name of the property to validate
594
614
* @return {Promise } this method returns a promise that resolves to a boolean true if the property is allowed to be changed.
595
615
*/
596
616
isValidProperty ( propertyName ) {
617
+ validateInputs ( [ propertyName , 'string' , 'propertyName' , true ] ) ;
618
+
597
619
return axios . get ( this . ksqldbURL + `/is_valid_property/${ propertyName } ` )
598
620
. then ( response => response )
599
621
. catch ( error => {
0 commit comments