hotstaq 0.8.21 → 0.8.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -90,7 +90,7 @@ void 0,void 0,function*(){for(;!1===y.isReadyForTesting;)yield y.wait(10);null!=
90
90
  (h+='<script type = "text/javascript">\nfunction hotstaq_isDocumentReady ()\n{\nif (window["Hot"] != null)\n{\nif (Hot.Mode === HotStaqWeb.DeveloperMode.Development)\n{\nlet func = function ()\n\t{\n\t\tif (Hot.TesterAPI != null)\n\t\t{\n\t\t\tlet testPaths = {};\n\t\t\tlet testElements = JSON.stringify (Hot.CurrentPage.testElements);\n\t\t\tlet testMaps = JSON.stringify (Hot.CurrentPage.testMaps);\n\n\t\t\tfor (let key in Hot.CurrentPage.testPaths)\n\t\t\t{\n\t\t\t\tlet testPath = Hot.CurrentPage.testPaths[key];\n\n\t\t\t\ttestPaths[key] = testPath.toString ();\n\t\t\t}\n\n\t\t\tlet testPathsStr = JSON.stringify (testPaths);\n\n\t\t\tHot.TesterAPI.tester.pageLoaded ({\n\t\t\t\t\ttesterName: Hot.CurrentPage.testerName,\n\t\t\t\t\ttesterMap: Hot.CurrentPage.testerMap,\n\t\t\t\t\tpageName: Hot.CurrentPage.name,\n\t\t\t\t\ttestElements: testElements,\n\t\t\t\t\ttestPaths: testPathsStr\n\t\t\t\t}).then (function (resp)\n\t\t\t\t\t{\n\t\t\t\t\t\tif (resp.error != null)\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tif (resp.error !== "")\n\t\t\t\t\t\t\t\tthrow new Error (resp.error);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tHotStaqWeb.HotStaq.isReadyForTesting = true;\n\t\t\t\t\t});\n\t\t}\n\t};\n\nif ((document.readyState === "complete") || (document.readyState === "interactive"))\n\tfunc ();\nelse\n\tdocument.addEventListener ("DOMContentLoaded", func);\n}\n}\n}\n\nhotstaq_isDocumentReady ();\n\x3c/script>'),
91
91
  h}static displayUrl(b,h=null,t=null,x=null){return A(this,void 0,void 0,function*(){return new Promise((H,I)=>{y.onReady(()=>A(this,void 0,void 0,function*(){var C={url:""};C.name=null==h?"string"==typeof b?b:b.name:h;""===C.name&&(C.name="string"==typeof b?b:b.name);"string"==typeof b?C.url=b:(C.url=b.url,null==t&&null!=b.processor&&(t=b.processor),null==x&&null!=b.args&&(x=b.args),null!=b.testerMap&&(C.testerMap=b.testerMap),null!=b.testerName&&(C.testerName=b.testerName),null!=b.testerAPIBaseUrl&&
92
92
  (C.testerAPIBaseUrl=b.testerAPIBaseUrl));null==t&&(t=new y);y.setupTesters(t,C);C.processor=t;C.args=x;0>C.url.indexOf("hstqserve")&&(C.url+="?hstqserve=nahfam");C=yield y.processUrl(C);C+=y.setupClientTesters(t);yield y.useOutput(C);H(t)}))})})}static displayContent(b,h=null,t=null,x=null){return A(this,void 0,void 0,function*(){return new Promise((H,I)=>{y.onReady(()=>A(this,void 0,void 0,function*(){var C={content:""};C.name=null==h?"string"==typeof b?"":b.name:h;""===C.name&&(C.name="string"==
93
- typeof b?"":b.name);"string"==typeof b?C.content=b:(C.content=b.content,null==t&&null!=b.processor&&(t=b.processor),null==x&&null!=b.args&&(x=b.args),null!=b.testerMap&&(C.testerMap=b.testerMap),null!=b.testerName&&(C.testerName=b.testerName),null!=b.testerAPIBaseUrl&&(C.testerAPIBaseUrl=b.testerAPIBaseUrl));null==t&&(t=new y);y.setupTesters(t,C);C.processor=t;C.args=x;C=yield y.processContent(C);yield y.useOutput(C);H(t)}))})})}}u.HotStaq=y;y.version="0.8.21";y.isWeb=!1;y.isReadyForTesting=!1;y.onReadyForTesting=
93
+ typeof b?"":b.name);"string"==typeof b?C.content=b:(C.content=b.content,null==t&&null!=b.processor&&(t=b.processor),null==x&&null!=b.args&&(x=b.args),null!=b.testerMap&&(C.testerMap=b.testerMap),null!=b.testerName&&(C.testerName=b.testerName),null!=b.testerAPIBaseUrl&&(C.testerAPIBaseUrl=b.testerAPIBaseUrl));null==t&&(t=new y);y.setupTesters(t,C);C.processor=t;C.args=x;C=yield y.processContent(C);yield y.useOutput(C);H(t)}))})})}}u.HotStaq=y;y.version="0.8.23";y.isWeb=!1;y.isReadyForTesting=!1;y.onReadyForTesting=
94
94
  null;y.errors={};"undefined"!=typeof document&&window.addEventListener("load",p.hotStaqWebStart)},638:(G,u,p)=>{Object.defineProperty(u,"__esModule",{value:!0});u.registerComponent=void 0;const m=p(732),v=p(260),A=p(243),g=p(507);u.registerComponent=function(e,n){if(null==e||""===e)throw Error("All components must have a tag!");if(void 0===customElements.get(e)){var l=this.components;customElements.define(e,class extends HTMLElement{constructor(){super();var c=l[e];if(this.component=new c.componentType(c.processor,
95
95
  c.api),this.hotComponent=this.component,this.component.htmlElements=[this],this.component.inner=this.innerHTML,null!=this.component.handleAttributes)this.component.handleAttributes(this.attributes);else for(c=0;c<this.attributes.length;c++){var a=this.attributes[c],f=a.name.toLowerCase();a=a.value;if("id"===f&&(this.component.name=a),"name"===f&&(this.component.name=a),"value"===f&&(this.component.value=a),-1<f.indexOf("hot-"))f=f.substring(4),this.component[f]=a}if(null==this.component.onPreOutput||
96
96
  !1!==this.component.onPreOutput())for(f=this.component.output(),null!=this.component.onPostOutput&&(f=this.component.onPostOutput(f)),c=[],"string"==typeof f?c.push({html:f}):c=f instanceof Array?f:[f],f=0;f<c.length;f++){a=c[f];var d=a.html,k="";null!=a.addFunctionsTo&&(k=a.addFunctionsTo);d=m.HotFile.parseContent(d,!0,{outputCommands:!1});null!=this.component.onParsed&&(d=this.component.onParsed(d));var r={fixedStr:"",querySelector:""};r=null!=this.component.onFixHTML?this.component.onFixHTML(d):
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hotstaq",
3
- "version": "0.8.21",
3
+ "version": "0.8.23",
4
4
  "description": "A friendly web framework that fits nicely into devops and CI/CD pipelines.",
5
5
  "bin": {
6
6
  "hotstaq": "./bin/hotstaq"
package/src/HotCLI.ts CHANGED
@@ -1256,7 +1256,7 @@ export class HotCLI
1256
1256
  {
1257
1257
  testerSettings.remoteServer = remoteServer;
1258
1258
  }, "");
1259
- runCmd.option (`--accept-websocket-connections`,
1259
+ runCmd.option (`--ws, --accept-websocket-connections`,
1260
1260
  `This will allow the all servers to accept websocket connections.`,
1261
1261
  (remoteServer: string, previous: any) =>
1262
1262
  {
package/src/HotFile.ts CHANGED
@@ -4,7 +4,6 @@ import fetch from "node-fetch";
4
4
 
5
5
  import { DeveloperMode, Hot } from "./Hot";
6
6
  import { HotPage } from "./HotPage";
7
- import { HotTestElement } from "./HotTestElement";
8
7
 
9
8
  /**
10
9
  * A file to process.
@@ -130,6 +130,9 @@ export class HotGenerator
130
130
  res.json ({ "status": "ok" });
131
131
  });
132
132
 
133
+ if (server.api.onPreRegister != null)
134
+ await server.api.onPreRegister ();
135
+
133
136
  //server.serverType = "API Server";
134
137
  //await server.listen ();
135
138
 
@@ -368,6 +371,7 @@ export class HotGenerator
368
371
  if (this.generateType.indexOf ("openapi-3.0.0") > -1)
369
372
  jsonObj.openapi = "3.0.0";
370
373
 
374
+ let filename: string = `${libraryName}_${apiName}_${this.generateType}`;
371
375
  jsonObj.info = {};
372
376
  jsonObj.info.title = hotsite.name;
373
377
  jsonObj.info.version = hotsite.name;
@@ -387,6 +391,8 @@ export class HotGenerator
387
391
  if (route.description != null)
388
392
  routeDescription = route.description;
389
393
 
394
+ this.logger.verbose (`Generating Route ${routeName}...`);
395
+
390
396
  for (let iJdx = 0; iJdx < route.methods.length; iJdx++)
391
397
  {
392
398
  let method: HotRouteMethod = route.methods[iJdx];
@@ -398,10 +404,13 @@ export class HotGenerator
398
404
  };
399
405
  let component: any = null;
400
406
  let componentName: string = "";
407
+
408
+ this.logger.verbose (`Generating method ${methodName} at path ${path}`);
409
+
401
410
  let getChildParameters = (param: HotRouteMethodParameter): any =>
402
411
  {
403
412
  let createdObj: any = {
404
- type: param.type,
413
+ type: param.type || "string",
405
414
  description: param.description || "",
406
415
  properties: {}
407
416
  };
@@ -433,8 +442,8 @@ export class HotGenerator
433
442
  else
434
443
  {
435
444
  createdObj.properties[key3] = {
436
- type: tempParam.type,
437
- description: tempParam.description
445
+ type: tempParam.type || "string",
446
+ description: tempParam.description || ""
438
447
  };
439
448
  }
440
449
  }
@@ -451,7 +460,7 @@ export class HotGenerator
451
460
  if (method.returns.type === "object")
452
461
  {
453
462
  returnsDescription = {
454
- description: method.returns.description,
463
+ description: method.returns.description || "",
455
464
  content: {
456
465
  "application/json": {
457
466
  schema: getChildParameters (method.returns)
@@ -462,12 +471,12 @@ export class HotGenerator
462
471
  else
463
472
  {
464
473
  returnsDescription = {
465
- description: method.returns.description,
474
+ description: method.returns.description || "",
466
475
  content: {
467
476
  "application/json": {
468
477
  schema: {
469
478
  type: "string",
470
- description: method.returns.description
479
+ description: method.returns.description || ""
471
480
  }
472
481
  }
473
482
  }
@@ -489,7 +498,6 @@ export class HotGenerator
489
498
  {
490
499
  components[`${routeName}_${methodName}`] = {
491
500
  type: "object",
492
- required: [],
493
501
  properties: {}
494
502
  };
495
503
  component = components[`${routeName}_${methodName}`];
@@ -505,13 +513,18 @@ export class HotGenerator
505
513
  else
506
514
  {
507
515
  component.properties[key3] = {
508
- type: param.type,
509
- description: param.description
516
+ type: param.type || "string",
517
+ description: param.description || ""
510
518
  };
511
519
  }
512
520
 
513
521
  if (param.required === true)
522
+ {
523
+ if (component.required == null)
524
+ component.required = [];
525
+
514
526
  component.required.push (key3);
527
+ }
515
528
  }
516
529
  }
517
530
 
@@ -535,7 +548,7 @@ export class HotGenerator
535
548
  schemas: components
536
549
  };
537
550
 
538
- const outputFile: string = ppath.normalize (`${outputDir}/${jsonObj.info.title}`);
551
+ const outputFile: string = ppath.normalize (`${outputDir}/${filename}`);
539
552
  let outputFileExtension: string = ".json";
540
553
  let fileContent: string = "";
541
554
 
@@ -552,6 +565,7 @@ export class HotGenerator
552
565
  fileContent = yamldoc.toString ();
553
566
  }
554
567
 
568
+ this.logger.verbose (`Writing to file ${outputFile}${outputFileExtension}`);
555
569
  await HotIO.writeTextFile (`${outputFile}${outputFileExtension}`, fileContent);
556
570
 
557
571
  this.logger.info (`Finished generating API Documentation "${key}" from HotSite "${hotsite.name}"...`);
@@ -833,7 +847,7 @@ class ${data.routeName}
833
847
  else
834
848
  {
835
849
  outputParams += `
836
- * @property {${tempParam.type}} ${key3} ${tempParam.description}`;
850
+ * @property {${tempParam.type || "string"}} ${key3} ${tempParam.description || ""}`;
837
851
  }
838
852
  }
839
853
  }
@@ -859,7 +873,7 @@ class ${data.routeName}
859
873
  else
860
874
  {
861
875
  paramsToOutput += `
862
- * @property {${param.type}} ${key} ${param.description}`;
876
+ * @property {${param.type || "string"}} ${key} ${param.description || ""}`;
863
877
  }
864
878
  }
865
879
 
@@ -891,13 +905,13 @@ class ${data.routeName}
891
905
  `;
892
906
  jsonReturnOutput = `
893
907
  *
894
- * @returns {${returnObjType}} ${method.returns.description}`;
908
+ * @returns {${returnObjType}} ${method.returns.description || ""}`;
895
909
  }
896
910
  else
897
911
  {
898
912
  jsonReturnOutput = `
899
913
  *
900
- * @returns {${method.returns.type}} ${method.returns.description}`;
914
+ * @returns {${method.returns.type}} ${method.returns.description || ""}`;
901
915
  }
902
916
  }
903
917
 
@@ -172,6 +172,43 @@ export class HotHTTPServer extends HotServer
172
172
  * If set to true, worker threads will be used. NOT WORKING YET. DO NOT USE.
173
173
  */
174
174
  useWorkerThreads: boolean;
175
+ /**
176
+ * The options to use when a new client has made a request.
177
+ */
178
+ options: {
179
+ /**
180
+ * Executes when the new client has requested the headers.
181
+ */
182
+ onCall: (req: express.Request, res: express.Response, next: express.NextFunction) => Promise<void>;
183
+ /**
184
+ * The headers to send with the response. Default:
185
+ * [
186
+ * { type: "Access-Control-Allow-Origin", value: "*" },
187
+ * { type: "Access-Control-Allow-Methods", value: "GET,HEAD,PUT,PATCH,POST,DELETE" },
188
+ * { type: "Access-Control-Allow-Headers", value: "Origin, X-Requested-With, Content-Type, Accept" }
189
+ * ]
190
+ */
191
+ headers: HTTPHeader[];
192
+ };
193
+ /**
194
+ * The CORS settings. By default the origin will be open to all.
195
+ * The CORS settings that are set here will also be used for the
196
+ * websocket server as well.
197
+ */
198
+ cors: {
199
+ /**
200
+ * Executed when a CORS call has been made.
201
+ */
202
+ onCORSCall: (req: express.Request, res: express.Response, next: express.NextFunction) => Promise<void>;
203
+ /**
204
+ * The allowed CORS origins. Default: *
205
+ */
206
+ origin: string;
207
+ /**
208
+ * The allowed headers. Default: ["Origin", "X-Requested-With", "Content-Type", "Accept"]
209
+ */
210
+ allowedHeaders: string[];
211
+ };
175
212
  /**
176
213
  * The function to execute when handling 404 errors.
177
214
  */
@@ -207,6 +244,19 @@ export class HotHTTPServer extends HotServer
207
244
  afterUploadIdUse: true
208
245
  };
209
246
  this.useWorkerThreads = false;
247
+ this.options = {
248
+ onCall: null,
249
+ headers: [
250
+ { type: "Access-Control-Allow-Origin", value: "*" },
251
+ { type: "Access-Control-Allow-Methods", value: "GET,HEAD,PUT,PATCH,POST,DELETE" },
252
+ { type: "Access-Control-Allow-Headers", value: "Origin, X-Requested-With, Content-Type, Accept" }
253
+ ]
254
+ };
255
+ this.cors = {
256
+ onCORSCall: null,
257
+ origin: "*",
258
+ allowedHeaders: ["Origin", "X-Requested-With", "Content-Type", "Accept"]
259
+ };
210
260
  this.handle404 = null;
211
261
  this.handleOther = null;
212
262
 
@@ -263,20 +313,37 @@ export class HotHTTPServer extends HotServer
263
313
  JSONLimit = process.env.JSON_LIMIT;
264
314
  }
265
315
 
266
- this.expressApp.options ("*", (req: express.Request, res: express.Response, next: express.NextFunction) =>
316
+ this.expressApp.options ("*", async (req: express.Request, res: express.Response, next: express.NextFunction) =>
267
317
  {
268
- res.header ("Access-Control-Allow-Origin", "*");
269
- res.header ("Access-Control-Allow-Methods", "GET,HEAD,PUT,PATCH,POST,DELETE");
270
- res.header ("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
318
+ if (this.options.onCall != null)
319
+ {
320
+ await this.options.onCall (req, res, next);
321
+
322
+ return;
323
+ }
324
+
325
+ for (let iIdx = 0; iIdx < this.options.headers.length; iIdx++)
326
+ {
327
+ let header: HTTPHeader = this.options.headers[iIdx];
328
+
329
+ res.header (header.type, header.value);
330
+ }
271
331
 
272
332
  res.statusCode = 204;
273
333
  res.setHeader ("Content-Length", "0");
274
334
  res.end ();
275
335
  });
276
- this.expressApp.use ((req: express.Request, res: express.Response, next: express.NextFunction) =>
336
+ this.expressApp.use (async (req: express.Request, res: express.Response, next: express.NextFunction) =>
277
337
  {
278
- res.header ("Access-Control-Allow-Origin", "*");
279
- res.header ("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
338
+ if (this.cors.onCORSCall != null)
339
+ {
340
+ await this.cors.onCORSCall (req, res, next);
341
+
342
+ return;
343
+ }
344
+
345
+ res.header ("Access-Control-Allow-Origin", this.cors.origin);
346
+ res.header ("Access-Control-Allow-Headers", this.cors.allowedHeaders);
280
347
 
281
348
  next ();
282
349
  });
@@ -182,7 +182,7 @@ export async function processRequest (server: HotHTTPServer,
182
182
  }
183
183
  catch (ex)
184
184
  {
185
- logger.verbose (`Execution error: ${ex.message}`);
185
+ logger.error (`Execution error: ${ex.message}`);
186
186
  return ({ error: ex.message });
187
187
  }
188
188
 
package/src/HotStaq.ts CHANGED
@@ -131,7 +131,7 @@ export class HotStaq implements IHotStaq
131
131
  /**
132
132
  * The current version of HotStaq.
133
133
  */
134
- static version: string = "0.8.21";
134
+ static version: string = "0.8.23";
135
135
  /**
136
136
  * Indicates if this is a web build.
137
137
  */
@@ -15,11 +15,16 @@ export class HotWebSocketClient
15
15
  * The connected socket.
16
16
  */
17
17
  socket: Socket;
18
+ /**
19
+ * Any data that this client socket should contain.
20
+ */
21
+ persistentData: any;
18
22
 
19
23
  constructor (webSocketServer: HotWebSocketServer, socket: Socket)
20
24
  {
21
25
  this.webSocketServer = webSocketServer;
22
26
  this.socket = socket;
27
+ this.persistentData = {};
23
28
  }
24
29
 
25
30
  /**
@@ -77,12 +77,22 @@ export class HotWebSocketServer
77
77
  {
78
78
  if (this.connection.httpsListener != null)
79
79
  {
80
- this.io = new Server (this.connection.httpsListener);
80
+ this.io = new Server (this.connection.httpsListener, {
81
+ "cors": {
82
+ "origin": this.connection.cors.origin,
83
+ "allowedHeaders": this.connection.cors.allowedHeaders
84
+ }
85
+ });
81
86
  this.logger.info (`Secure WebSocket server listening...`);
82
87
  }
83
88
  else
84
89
  {
85
- this.io = new Server (this.connection.httpListener);
90
+ this.io = new Server (this.connection.httpListener, {
91
+ "cors": {
92
+ "origin": this.connection.cors.origin,
93
+ "allowedHeaders": this.connection.cors.allowedHeaders
94
+ }
95
+ });
86
96
  this.logger.info (`WebSocket server listening...`);
87
97
  }
88
98
 
@@ -183,6 +193,8 @@ export class HotWebSocketServer
183
193
  "jsonObj": jsonObj,
184
194
  "wsSocket": wsSocket
185
195
  });
196
+
197
+ socket.data.wsSocket = wsSocket;
186
198
 
187
199
  let result: any = await method.onServerExecute.call (this, request);
188
200
 
@@ -193,7 +205,7 @@ export class HotWebSocketServer
193
205
  }
194
206
  catch (ex)
195
207
  {
196
- this.logger.verbose (`Execution error: ${ex.message}`);
208
+ this.logger.error (`Execution error: ${ex.message}`);
197
209
  socket.emit (`sub/${routeName}/${method.name}`, { error: ex.message });
198
210
  }
199
211
  });