Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #100

Merged
merged 2 commits into from
Nov 16, 2023
Merged

Dev #100

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "hotstaq",
"version": "0.8.68",
"version": "0.8.69",
"description": "A friendly web framework that fits nicely into devops and CI/CD pipelines.",
"bin": {
"hotstaq": "./bin/hotstaq"
Expand Down
14 changes: 14 additions & 0 deletions src/Hot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,10 +256,24 @@ export class Hot
/**
* Make an api call. This must include the route version.
*
* Simple apiCall:
* @example
* ```ts
* await Hot.apiCall ('/v1/hello_world/echo', { message: "Hello!" });
* ```
*
* Make an API call and upload a file:
* @example
* ```ts
* let input = document.getElementById ("fileInput");
* let file = input.files[0];
*
* await Hot.apiCall ('/v1/hello_world/echo',
* { message: "Hello!" }, HotEventMethod.POST,
* {
* "indexFileKey": file
* });
* ```
*/
static async apiCall (route: string, data: any = null,
httpMethod: HotEventMethod = HotEventMethod.POST,
Expand Down
2 changes: 1 addition & 1 deletion src/HotCLI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1787,7 +1787,7 @@ export class HotCLI
createHotGenerator ();
generator.optimizeJS = true;
});
generateCmd.option ("--generate-type <type>", "The type of output to generate. Can be: javascript,openapi-3.0.0-json,openapi-3.0.0-yaml",
generateCmd.option ("--generate-type <type>", "The type of output to generate. Can be: javascript,openapi-3.0.0-json,openapi-3.0.0-yaml,asyncapi-2.6.0-json,asyncapi-2.6.0-yaml,",
(arg: string, previous: any) =>
{
createHotGenerator ();
Expand Down
104 changes: 84 additions & 20 deletions src/HotGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export class HotGenerator
* * javascript
* * openapi-3.0.0-json
* * openapi-3.0.0-yaml
* * asyncapi-2.6.0-json
* * asyncapi-2.6.0-yaml
*/
generateType: string;
Expand Down Expand Up @@ -55,6 +56,10 @@ export class HotGenerator
* The directory to copy all built files to.
*/
copyTo: string;
/**
* Exit on complete.
*/
exitOnComplete: boolean;

constructor (logger: HotLog)
{
Expand All @@ -66,6 +71,7 @@ export class HotGenerator
this.logger = logger;
this.outputDir = ppath.normalize (`${process.cwd ()}/build-web/`);
this.copyTo = "";
this.exitOnComplete = true;
}

/**
Expand Down Expand Up @@ -228,6 +234,7 @@ export class HotGenerator
{
if ((this.generateType === "openapi-3.0.0-json") ||
(this.generateType === "openapi-3.0.0-yaml") ||
(this.generateType === "asyncapi-2.6.0-json") ||
(this.generateType === "asyncapi-2.6.0-yaml"))
{
await this.generateAPIDocumentation (processor, apis);
Expand Down Expand Up @@ -357,7 +364,9 @@ export class HotGenerator
}

this.logger.info (`Finished generating Web API "${key}" from HotSite "${hotsite.name}"...`);
process.exit (0);

if (this.exitOnComplete === true)
process.exit (0);
});
}

Expand All @@ -370,6 +379,7 @@ export class HotGenerator
{
if (! ((this.generateType === "openapi-3.0.0-json") ||
(this.generateType === "openapi-3.0.0-yaml") ||
(this.generateType === "asyncapi-2.6.0-json") ||
(this.generateType === "asyncapi-2.6.0-yaml")))
{
throw new Error (`Unknown API documentation --generate-type ${JSON.stringify (this.generateType)}`);
Expand All @@ -384,16 +394,27 @@ export class HotGenerator
let jsonObj: any = {};
let components: any = {};
let hotsiteDescription: string = "";
let servers: any[] = [{ url: serverResult.baseAPIUrl }];
let servers: any = null;

if (hotsite.description != null)
hotsiteDescription = hotsite.description;

if (this.generateType.indexOf ("openapi-3.0.0") > -1)
{
jsonObj.openapi = "3.0.0";
servers = [{ url: serverResult.baseAPIUrl }];
}

if (this.generateType.indexOf ("asyncapi-2.6.0-yaml") > -1)
{
jsonObj.asyncapi = "2.6.0";
servers = {
server: {
url: serverResult.baseAPIUrl,
protocol: "WebSocket"
}
};
}

let filename: string = `${libraryName}_${apiName}_${this.generateType}`;
jsonObj.info = {};
Expand Down Expand Up @@ -437,6 +458,17 @@ export class HotGenerator
}
}

if (jsonObj.asyncapi != null)
{
if (! ((method.type === HotEventMethod.POST_AND_WEBSOCKET_CLIENT_PUB_EVENT) ||
(method.type === HotEventMethod.WEBSOCKET_CLIENT_PUB_EVENT)))
{
this.logger.verbose (`Skipping method ${method.name} because it is not a POST_AND_WEBSOCKET_CLIENT_PUB_EVENT or WEBSOCKET_CLIENT_PUB_EVENT method.`);

continue;
}
}

let methodName: string = method.name;
let path: string = `/${route.version}/${routeName}/${methodName}`;
let methodDescription: string = "";
Expand Down Expand Up @@ -527,13 +559,28 @@ export class HotGenerator
}
}

jsonObj.paths[path] = {};
jsonObj.paths[path][method.type.toLowerCase ()] = {
"summary": methodDescription,
responses: {
"200": returnsDescription
}
};
if (jsonObj.openapi != null)
{
jsonObj.paths[path] = {};
jsonObj.paths[path][method.type.toLowerCase ()] = {
"summary": methodDescription,
responses: {
"200": returnsDescription
}
};
}

if (jsonObj.asyncapi != null)
{
jsonObj.channels[path] = {
publish: {
summary: methodDescription,
message: {
"payload": returnsDescription
}
}
};
}

if (method.parameters != null)
{
Expand Down Expand Up @@ -573,16 +620,27 @@ export class HotGenerator

if (component != null)
{
jsonObj.paths[path][method.type.toLowerCase ()]["requestBody"] = {
required: true,
content: {
"application/json": {
schema: {
"$ref": `#/components/schemas/${componentName}`
if (jsonObj.openapi != null)
{
jsonObj.paths[path][method.type.toLowerCase ()]["requestBody"] = {
required: true,
content: {
"application/json": {
schema: {
"$ref": `#/components/schemas/${componentName}`
}
}
}
}
};
};
}

if (jsonObj.asyncapi != null)
{
jsonObj.channels[path].publish = { message: { payload: {} } };
jsonObj.channels[path].publish.message.payload = {
"$ref": `#/components/schemas/${componentName}`
};
}
}
}
}
Expand All @@ -595,10 +653,14 @@ export class HotGenerator
let outputFileExtension: string = ".json";
let fileContent: string = "";

if (this.generateType === "openapi-3.0.0-json")
if ((this.generateType === "openapi-3.0.0-json") ||
(this.generateType === "asyncapi-2.6.0-json"))
{
fileContent = JSON.stringify (jsonObj, null, 2);
}

if (this.generateType === "openapi-3.0.0-yaml")
if ((this.generateType === "openapi-3.0.0-yaml") ||
(this.generateType === "asyncapi-2.6.0-yaml"))
{
outputFileExtension = ".yaml";

Expand All @@ -612,7 +674,9 @@ export class HotGenerator
await HotIO.writeTextFile (`${outputFile}${outputFileExtension}`, fileContent);

this.logger.info (`Finished generating API Documentation "${key}" from HotSite "${hotsite.name}"...`);
process.exit (0);

if (this.exitOnComplete === true)
process.exit (0);
});
}

Expand Down
11 changes: 11 additions & 0 deletions src/HotIO.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,17 @@ export class HotIO
}));
}

/**
* Write a file stream.
*/
static writeFileStream (path: string, stream: fs.ReadStream): fs.WriteStream
{
let writeStream: fs.WriteStream = fs.createWriteStream (path);
stream.pipe (writeStream);

return (writeStream);
}

/**
* Read a file and create a stream from it.
*/
Expand Down
2 changes: 1 addition & 1 deletion src/HotStaq.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ export class HotStaq implements IHotStaq
/**
* The current version of HotStaq.
*/
static version: string = "0.8.68";
static version: string = "0.8.69";
/**
* Indicates if this is a web build.
*/
Expand Down
2 changes: 1 addition & 1 deletion tests/create/CreateApp.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ describe ("Create App Tests", function ()

creator = new HotCreator (processor.logger, "app");
creator.outputDir = baseDir;
creator.hotstaqVersion = `link`; // Be sure to set the previous version for testing
creator.hotstaqVersion = `0.8.68`; // Be sure to set the previous version for testing
await creator.create ();
});
it ("should check that the node_modules folder exists", async () =>
Expand Down
14 changes: 14 additions & 0 deletions tests/generator/GenerateAPI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ describe ("API Generator Tests", () =>
{
generator = new HotGenerator (processor.logger);
generator.hotsites = [processor.hotSite];
generator.exitOnComplete = false;
await generator.generateAPI (processor, apis);
});
it ("should check the generated API", async () =>
Expand All @@ -56,4 +57,17 @@ describe ("API Generator Tests", () =>
expect (hash).to.equal ("0685f7b411e61bc401c805d54f155779331195ecff646f70a1e290988688017f",
`The generated API documentation file has changed. Please update the hash in the test.`);
});
it ("should generate the Async API documentation", async () =>
{
generator.generateType = "asyncapi-2.6.0-yaml";

await generator.generateAPIDocumentation (processor, apis);
});
it ("should check the generated Async API documentation", async () =>
{
const hash: string = await HotIO.sha256File (`./build-web/HotStaqTests_HelloWorldAPI_asyncapi-2.6.0-yaml.yaml`);

expect (hash).to.equal ("d795de68ff49e48a807121ca059eb91ff7ad5cc00c2b126a2f574b9d6b4727ea",
`The generated API documentation file has changed. Please update the hash in the test.`);
});
});