Skip to content

Commit

Permalink
Add new process method
Browse files Browse the repository at this point in the history
  • Loading branch information
krisztianb committed Sep 17, 2023
1 parent 183bd34 commit 365aadd
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 15 deletions.
1 change: 0 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,6 @@
"@typescript-eslint/prefer-for-of": ["error"],
"@typescript-eslint/prefer-literal-enum-member": ["error"],
"@typescript-eslint/prefer-readonly": ["error"],
"@typescript-eslint/prefer-readonly-parameter-types": ["error"],
"@typescript-eslint/promise-function-async": ["error"],

// plugin: @typescript-eslint - extension rules
Expand Down
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.6.0] - 2023-09-17
### Added
- New method 'process' that returns a promise for the PlantUML diagram image that is generated
### Changed
- New plantuml.jar version: V1.2023.11 (13 Sep, 2023)

## [1.5.0] - 2023-04-10
### Changed
- Updated dependencies (split2)
Expand Down Expand Up @@ -64,7 +70,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- First version

[Unreleased]: https://github.com/krisztianb/plantuml-pipe/compare/v1.5.0...HEAD
[Unreleased]: https://github.com/krisztianb/plantuml-pipe/compare/v1.6.0...HEAD
[1.6.0]: https://github.com/krisztianb/plantuml-pipe/releases/tag/v1.6.0
[1.5.0]: https://github.com/krisztianb/plantuml-pipe/releases/tag/v1.5.0
[1.4.0]: https://github.com/krisztianb/plantuml-pipe/releases/tag/v1.4.0
[1.3.6]: https://github.com/krisztianb/plantuml-pipe/releases/tag/v1.3.6
Expand Down
35 changes: 31 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@
</p>

A PlantUmlPipe instance is a wrapper to a PlantUML JAVA process running in pipe mode.
The object has an input stream (`in`) into which the PlantUML code for one or multiple diagrams can be written and

The object has an input stream (`in`) into which the PlantUML code of multiple diagrams can be written and
an output streams (`out`) from which the generated diagrams can be read.

Instead of the streams you can also use the `process` method of the object which returns a promise with the generated diagram.

## Installation

This module can be installed using [npm](https://www.npmjs.com/package/plantuml-pipe):
Expand All @@ -23,9 +26,9 @@ order to use this module. A corresponding test is run after installing this modu

This module includes type definitions for TypeScript.

## Usage
## Usage (with streams)

The following TypeScript code creates two SVG image files:
The following TypeScript code creates two SVG image files using streams:

```typescript
import * as fs from "fs";
Expand Down Expand Up @@ -54,6 +57,30 @@ Output:
| :---------------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------------------------------------------------------------: |
| ![First image](http://www.plantuml.com/plantuml/svg/SoWkIImgAStDuN8ghQfIqBLJ2C_FJwbKi588oLV8p4lBpCiigTJJqrD8p4jHI4gjpCzBKUHoICrB0Me10000) | ![Second image](http://www.plantuml.com/plantuml/svg/SoWkIImgAStDuGhFpq-fLD2rKt0ghQfIi5Bmo2y7yWk0idcfHOfS3gbvAK1b0000) |

## Usage (with promises)

The following TypeScript code creates the same two SVG image files using promises:

```typescript
import * as fs from "fs";
import { PlantUmlPipe } from "plantuml_pipe";

const puml = new PlantUmlPipe();

const buzzPlantUml = "@startuml\nBuzz -> Woody : To infinity... and beyond!\n@enduml";
const woodyPlantUml = "@startuml\nWoody -> Buzz : Howdy partner!\n@enduml";

puml.process(buzzPlantUml).then((imageData) => {
fs.writeFileSync("./1.svg", imageData);
});

puml.process(woodyPlantUml).then((imageData) => {
fs.writeFileSync("./2.svg", imageData);
});

puml.close();
```

## Options

The `PlantUmlPipe` constructor can receive an options object as a parameter. It has the following members:
Expand All @@ -68,7 +95,7 @@ The `PlantUmlPipe` constructor can receive an options object as a parameter. It
| `pixelCutOffValue` | To prevent memory problems PlantUML limits the width and height of pixel (PNG) graphics to 4096. Use this option to set the `PLANTUML_LIMIT_SIZE` variable which overrides this value. | |
| `noErrorImages` | By default when the PlantUML process encounters an error (eg: because of an error in your PlantUML code), it still generates an image which contains an error message. You can set this option to `true` to disable error image generation. You can then implement an error handling yourself using the normal data event of PlantUMLPipe's output stream. For every error the data chunk of the event is going to start with the line `ERROR`. | `false` |
| `javaOptions` | A string array of options that are passed to the JAVA process. If you are generating many big diagrams it might be necessary to increase the maximum heap size of the JAVA process. You can use this property to do so - look [here](https://plantuml.com/de/faq#e689668a91b8d065) for more information on this issue. | |
| `plantUmlArgs` | A string array of arguments that are passed to the PlantUML process as options. The PlantUML process has many options that you can set through the command line. Some of these options can be set directly using a property of the options argument you pass to the constructor of PlantUmlPipe - for example the `delimiter` property sets the `-pipedelimitor "xyz"` option. If there is no property for the option that you want to pass to the PlantUML process, you can use this property to do so. You can find the list of possible PlantUML options [here](https://plantuml.com/de/command-line#6a26f548831e6a8c). | |
| `plantUmlArgs` | A string array of arguments that are passed to the PlantUML process as options. The PlantUML process has many options that you can set through the command line. Some of these options can be set directly using a property of the options argument you pass to the constructor of PlantUmlPipe - for example the `delimiter` property sets the `-pipedelimitor "xyz"` option. If there is no property for the option that you want to pass to the PlantUML process, you can use this property to do so. You can find the list of available PlantUML options [here](https://plantuml.com/de/command-line#6a26f548831e6a8c). | |

## Bugs

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "plantuml-pipe",
"version": "1.5.0",
"version": "1.6.0",
"description": "Generate multiple PlantUML diagrams with one JAVA process",
"author": {
"name": "Krisztián Balla",
Expand Down
50 changes: 50 additions & 0 deletions src/plantuml_pipe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ export class PlantUmlPipe {
*/
private readonly outputStream: Readable;

/**
* Collection of promise resolver functions used for the "process" method that returns a promise.
*/
private readonly resolvers = new Array<(imageData: string | Readonly<Buffer>) => void>();

/**
* Creates a new PlantUML pipe.
* @param userOptions Possible user defined options for the PlantUML generating pipe.
Expand Down Expand Up @@ -67,4 +72,49 @@ export class PlantUmlPipe {
public get out(): Readable {
return this.outputStream;
}

/**
* Closes the input stream of the PlantUML diagram generator.
*/
public close(): void {
this.inputStream.end();
}

/**
* Resolves the currently first promise in the queue by calling its corresponding resolve function.
* @param imageData The gnerated image data that is passed to the resolve function of the promise.
*/
private readonly resolvePromise = (imageData: string | Readonly<Buffer>): void => {
const resolver = this.resolvers.shift();

if (resolver) {
resolver(imageData);
}
};

/**
* Generates a PlantUML diagram image from the given PlantUML code.
* @param plantUml The PlantUML code.
* @returns A promise with the data of the generated PlantUML diagram image.
*/
public async process<T extends string | Readonly<Buffer>>(plantUml: string): Promise<T>;
public async process(plantUml: string): Promise<string | Readonly<Buffer>> {
let resolver: ((imageData: string | Readonly<Buffer>) => void) | undefined;

const promise = new Promise<string | Readonly<Buffer>>((resolve) => {
resolver = resolve;
});

if (resolver) {
this.resolvers.push(resolver);
}

if (!this.outputStream.listeners("data").includes(this.resolvePromise)) {
this.outputStream.on("data", this.resolvePromise);
}

this.inputStream.write(plantUml.endsWith("\n") ? plantUml : plantUml + "\n");

return promise;
}
}
33 changes: 32 additions & 1 deletion test/plantuml_pipe.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,38 @@ describe("PlantUmlPipe", function () {
// eslint-disable-next-line @typescript-eslint/no-invalid-this -- See https://mochajs.org/#timeouts
this.timeout(0);

it("should create two SVG images", (done) => {
it("should create two SVG images using promises", (done) => {
const puml = new PlantUmlPipe();

puml.process<string>(toyStorySinglePlantUml)
.then((imageData) => {
fs.writeFileSync(__dirname + `/promise-1.svg`, imageData);
})
.catch((err) => {
console.error("Unexpected error " + String(err));
});

puml.process<string>(toyStorySinglePlantUml)
.then((imageData) => {
fs.writeFileSync(__dirname + `/promise-2.svg`, imageData);
})
.catch((err) => {
console.error("Unexpected error " + String(err));
});

puml.out.on("close", () => {
assert.strictEqual(fs.existsSync(__dirname + "/promise-1.svg"), true);
assert.strictEqual(fs.existsSync(__dirname + "/promise-2.svg"), true);

fs.unlinkSync(__dirname + "/promise-1.svg");
fs.unlinkSync(__dirname + "/promise-2.svg");
done();
});

puml.close();
});

it("should create two SVG images using stream events", (done) => {
const puml = new PlantUmlPipe();
let fileNum = 1;

Expand Down
12 changes: 6 additions & 6 deletions tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
{
"include": ["src"],
"compilerOptions": {
"target": "es5",
"lib": ["ES2015"],
"module": "commonjs",
"outDir": "dist",
"esModuleInterop": true,
"declaration": true,
"strict": true,
"noImplicitOverride": true,
"exactOptionalPropertyTypes": true,
"target": "es5",
"declaration": true,
"esModuleInterop": true
},
"include": ["src"]
"exactOptionalPropertyTypes": true
}
}
2 changes: 1 addition & 1 deletion vendor/plantuml-version.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
The plantuml.jar in this folder is: V1.2023.5 (24 Mar, 2023)
The plantuml.jar in this folder is: V1.2023.11 (13 Sep, 2023)
You can find the CHANGELOG here: https://plantuml.com/changes
Binary file modified vendor/plantuml.jar
Binary file not shown.

0 comments on commit 365aadd

Please sign in to comment.