Skip to content

Commit

Permalink
[OV JS][DOCS] Edits in JS API docs (#27064)
Browse files Browse the repository at this point in the history
Porting: #26875

---------

Co-authored-by: Roman Kazantsev <roman.kazantsev@intel.com>
  • Loading branch information
sgolebiewski-intel and rkazants authored Oct 21, 2024
1 parent e16e4d4 commit cb56c19
Show file tree
Hide file tree
Showing 8 changed files with 342 additions and 12 deletions.
1 change: 1 addition & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ Choose the component your Good First Issue is related to. You can run tests to m
- [C API](https://github.com/openvinotoolkit/openvino/tree/master/src/bindings/c)
- [Core](https://github.com/openvinotoolkit/openvino/tree/master/src/core)
- [Python API](https://github.com/openvinotoolkit/openvino/tree/master/src/bindings/python)
- [Node.js API](https://github.com/openvinotoolkit/openvino/tree/master/src/bindings/js/node)

##### Frontends
- [IR Frontend](https://github.com/openvinotoolkit/openvino/tree/master/src/frontends/ir)
Expand Down
6 changes: 6 additions & 0 deletions src/bindings/js/docs/CODESTYLE.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
# Code Style Guide

Node.js bindings contain two parts: C++ and Typescript/JavaScript.

This article presents the coding standards for JavaScript and TypeScript parts of **openvino-node** package. The following rules will help maintain code quality and consistency throughout the codebase.

For C++ codestyle rules, refer to [OpenVINO Coding Guidelines](https://github.com/openvinotoolkit/openvino/blob/master/docs/dev/coding_style.md).

Make sure your IDE has ESLint plugin installed. Its rules are specified in the [.eslint-global.js file](../.eslintrc-global.js). Keep in mind that your PR will not be approved if it does not meet the following requirements.


## General Rules

### 1. Semicolons
Expand Down Expand Up @@ -89,6 +94,7 @@ Make sure your IDE has ESLint plugin installed. Its rules are specified in the [
- Special case for the `catch` keyword: No space after `catch`
- **Enforced By**: `keyword-spacing: ['error', { overrides: { catch: { after: false } } }]`


## Additional Resources

For further details on each rule, refer to the [ESLint documentation](https://eslint.org/docs/rules/).
11 changes: 5 additions & 6 deletions src/bindings/js/docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

## Folders

- `./docs` - documentation
- `./node` - openvino-node npm package
- [./docs](../docs/) - documentation
- [./node](../node/) - openvino-node npm package

## openvino-node Package Developer Documentation
## `openvino-node` Package Developer Documentation

### Components

Expand All @@ -28,7 +28,6 @@
```bash
cmake \
-DCMAKE_BUILD_TYPE=Release \
-DENABLE_FASTER_BUILD=ON \
-DCPACK_GENERATOR=NPM \
-DENABLE_SYSTEM_TBB=OFF -UTBB* \
-DENABLE_TESTS=OFF \
Expand Down Expand Up @@ -75,9 +74,9 @@

[OpenVINO™ Node.js Bindings Examples of Usage](../../../../samples/js/node/README.md)

## Contribution
## Contributing

If you want to contribute to the project, refer to the [code style rules](./CODESTYLE.md) and [contribution guide](../../../../CONTRIBUTING.md) first.
Your contributions are welcome! Make sure to read the [Contribution Guide](https://github.com/openvinotoolkit/openvino/blob/master/src/bindings/js/node/CONTRIBUTING.md) to learn how you can get involved.

## See Also

Expand Down
146 changes: 146 additions & 0 deletions src/bindings/js/docs/code_examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
# How to extend the OpenVINO™ JavaScript API code

## Build the OpenVINO™ JavaScript API

For detailed build instructions, refer to the [OpenVINO™ JavaScript API documentation](./README.md).


## Project's naming conventions

When implementing the C++ sources for the JavaScript API, it is essential to adhere to the OpenVINO naming conventions described in the [OpenVINO Coding Style Guide](../../../../docs/dev/coding_style.md). In summary, the naming style employs `Snake Case` for methods, functions, and variables, while `Camel Case` is used for class names. Additionally, the naming of entities in the C++ sources should closely mirror their equivalents in the C++ API to maintain consistency.

For methods that are exposed to JavaScript, the naming convention transitions to `Camel Case`, aligning with common JavaScript practices. As an example, a method in the C++ API named `get_element_type` would be represented in the JavaScript API as `getElementType()`.


## node-addon-api module

[node addon api](https://github.com/nodejs/node-addon-api) is used to create OpenVINO JavaScript API for Node.js. The quickest way to learn is to follow the official [examples](https://github.com/nodejs/node-addon-examples). It is recommended to check out the tutorial on [how to create a JavaScript object from a C++ object](https://github.com/nodejs/node-addon-examples/tree/main/src/2-js-to-native-conversion/object-wrap-demo/node-addon-api).


## Adding a new class and method

To introduce a new `MyTensor` class that interacts with the `ov::Tensor` class, follow these steps:
- The class should facilitate construction from an ov::Tensor instance and allow initialization from a JavaScript element type and shape.
- It should also provide a getElementType method that retrieves the ov::Tensor element type.

Begin by creating a header file for the `MyTensor` class in the OpenVINO repository at `<openvino_repo>/src/bindings/js/node/include/my_tensor.hpp`. This file should contain the necessary includes and class definitions:
```cpp
class MyTensor : public Napi::ObjectWrap<MyTensor> {
public:
// Constructor for the wrapper class
MyTensor(const Napi::CallbackInfo& info);

// It returns a JavaScript class definition
static Napi::Function get_class(Napi::Env env);

// It returns the element type of ov::Tensor
Napi::Value get_element_type(const Napi::CallbackInfo& info);

private:
ov::Tensor _tensor;
};
```
The implementation of the class methods should be placed in a source file at `<openvino_repo>/src/bindings/js/node/src/my_tensor.cpp`
```cpp
MyTensor::MyTensor(const Napi::CallbackInfo& info) : Napi::ObjectWrap<MyTensor>(info) {
std::vector<std::string> allowed_signatures;
try {
if (ov::js::validate<Napi::String, Napi::Array>(info, allowed_signatures)) {
const auto type = js_to_cpp<ov::element::Type_t>(info, 0);
const auto& shape = js_to_cpp<ov::Shape>(info, 1);
this->_tensor = ov::Tensor(type, shape);
} else {
OPENVINO_THROW("'MyTensor' constructor", ov::js::get_parameters_error_msg(info, allowed_signatures));
}
} catch (std::exception& err) {
reportError(info.Env(), err.what());
}
}
Napi::Function MyTensor::get_class(Napi::Env env) {
return DefineClass(env,
"MyTensor",
{
InstanceMethod("getElementType", &MyTensor::get_element_type),
});
}
Napi::Value MyTensor::get_element_type(const Napi::CallbackInfo& info) {
return Napi::String::New(info.Env(), _tensor.get_element_type().to_string());
}
```
Finally, update the `CMakeLists.txt` file at `<openvino_repo>/src/bindings/js/node/` to include the new source file in the build process:
```cmake
add_library(${PROJECT_NAME} SHARED
${CMAKE_CURRENT_SOURCE_DIR}/src/my_tensor.cpp
)
```


### Argument validation and conversion

When binding JavaScript arguments with C++ functions, it is crucial to validate and convert the arguments appropriately. The template `ov::js::validate` function is a utility that facilitates this process. It is particularly useful for handling different overloads of functions and ensuring standardized error messages when arguments do not match expected signatures.
Before implementing a new conversion function, such as `js_to_cpp<ov::Shape>`, review the existing [helper methods](../../node/include/helper.hpp) to see if one already meets your requirements.


### New class initialization

When a new class is introduced to the `openvino-node` module, it must be initialized upon module loading. This is done in the [addon.cpp](../../src/addon.cpp) file. The initialization process registers the class with the Node.js environment so that it can be used within JavaScript code.
```cpp
Napi::Object init_module(Napi::Env env, Napi::Object exports) {
auto addon_data = new AddonData();
env.SetInstanceData<AddonData>(addon_data);
init_class(env, exports, "MyTensor", &MyTensor::get_class, addon_data->my_tensor);

return exports;
}
```
To keep track of the JavaScript class definitions, they are kept in `<openvino_repo>/src/bindings/js/node/include/addon.hpp`.
```cpp
struct AddonData {
Napi::FunctionReference my_tensor;
// and other class references
};
```

### Document the new functionality

The last step is to add the TypeScript type definitions and describe the new functionality.
```typescript
/**
* The {@link MyTensor} class and its documentation.
*/
interface MyTensor {
/**
* It gets the tensor element type.
*/
getElementType(): element;

}
interface MyTensorConstructor {
/**
* It constructs a tensor using the element type and shape. The new tensor
* data will be allocated by default.
* @param type The element type of the new tensor.
* @param shape The shape of the new tensor.
*/
new(type: element | elementTypeString, shape: number[]): MyTensor;
}

export interface NodeAddon {
MyTensor: MyTensorConstructor,
}
```


## Testing the new code

Now that coding is finished, remember to rebuild the project and test it out.

To learn how to test your code, refer to the guide on [how to test OpenVINO™ JavaScript API.](./test_examples.md)

## See also
* [OpenVINO™ README](../../../../README.md)
* [OpenVINO™ bindings README](../../README.md)
* [Developer documentation](../../../../docs/dev/index.md)
88 changes: 88 additions & 0 deletions src/bindings/js/docs/test_examples.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
# How to test the OpenVINO™ JavaScript API

## Build the OpenVINO™ JavaScript API
For detailed build instructions, refer to the [OpenVINO™ JavaScript API documentation](./README.md).


## Run OpenVINO™ JavaScript API tests
*For simplicity, begin by navigating to the [main JavaScript API folder](./../node):*
```shell
cd <openvino_repo>/src/bindings/js/node
```

Use this command to run OpenVINO JavaScript API tests:
```shell
npm run test
```

To run specific test files, you can pass one or more glob patterns:
```shell
node --test "tests/unit/core.test.js" "tests/unit/*model.test.js"
```

Before executing individual test files, a one-time setup is required. If you have not previously executed `npm run test`, initiate the setup by running the following command:

```shell
npm run test_setup
```

More information on running tests from the command line can be found in the [Node.js documentation]( https://nodejs.org/docs/latest/api/test.html#running-tests-from-the-command-line).


## Check the code style of the JavaScript API
*ESLint* is a tool to enforce a consistent coding style and to identify and fix potential issues in JavaScript code.

To check the code style of the JavaScript API, run the following commands:
```shell
npm run lint
```
*ESLint* can automatically fix many of the issues it detects. Use following command to run *ESLint* with the fix option on a single file:
```shell
npx eslint --fix "tests/unit/core.test.js"
```

It is recommended to run the code style check each time new tests are added.


## Writing OpenVINO™ JavaScript API tests

### Before start
Follow and complete [Examples of OpenVINO™ JavaScript API code](./code_examples.md).


### Adding new test-case in the correct place
Each new test should verify the correct behavior of the new functionality (e.g. class, method).

Unit test files are located in the `<openvino_repo>/src/bindings/js/node/tests/unit/` directory and their names correspond to the class/module to be tested.

Always add tests to the correct locations and create new files only when necessary. *Remember to include the license on top of each new file*.


### Test writing guidelines
Each test file starts with a `describe` block to group all tests related to a specific class or module. The name of the `describe` block should match the name of the class or module being tested, for example *ov.Core tests*.

Within the `describe` block, individual tests are defined using `test` or `it` blocks, with the name of the test reflecting what is being tested. If multiple tests relate to the same method, they can be grouped within a nested `describe` block.

```js
const { describe, it, beforeEach } = require('node:test');
describe('ov.Tensor tests', () => {
test('MyTensor.getElementType()', () => {
const tensor = new ov.MyTensor(ov.element.f32, [1, 3]);
assert.strictEqual(tensor.getElementType(), ov.element.f32);
});

});
```
When writing tests, keep the following best practices in mind:

* Focus on testing general usage and edge cases, but avoid excessive testing that leads to redundant test cases and can slow down validation pipelines.
* Avoid initializing shared variables outside of `test` or `beforeEach` blocks to prevent tests from affecting each other.
* Do not test built-in language features; instead, focus on the functionality provided by your code.
* Use hardcoded expected results to verify the correctness of your code. Alternatively, generate reference values at runtime using reliable libraries or methods.
* Extract and reuse common code snippets, such as helper functions or setup code, to improve test readability and maintainability.


## See also
* [OpenVINO™ README](../../../../README.md)
* [OpenVINO™ bindings README](../../README.md)
* [Developer documentation](../../../../docs/dev/index.md)
67 changes: 67 additions & 0 deletions src/bindings/js/node/CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
# Contributing to OpenVINO™ Node.js API

Your commitment to this project is greatly appreciated and the following guide is intended to help you contribute.

Make sure to read [main contribution guide](https://github.com/openvinotoolkit/openvino/blob/master/CONTRIBUTING.md) first. It covers most topics related to contributing to OpenVINO.


## TLDR

1. Decide what you want to change.
2. Create your fork of the OpenVINO repository.
3. Create a branch with a meaningful name for your changes.
4. Align the code style, commit the changes, and run tests.
5. Create a Pull Request, which clearly describes what has been changed and why.
6. Go through the Code Review.
7. Get your awesome code merged!

Read the section below for more details.


## How to Decide What to Change

In case of minor fixes, like changing variable names, additional parameter checks, etc., go to the next step.

However, if you want to bring significant changes, for example, the extension of architecture or a big part of functionality, that involves a large amount
of source code, open [an issue](https://github.com/openvinotoolkit/openvino/issues/new?assignees=octocat&labels=enhancement%2Cfeature&projects=&template=feature_request.yml&title=%5BFeature+Request%5D%3A+) first and discuss your idea with
codeowners. It will prevent you from doing extra work.

You can also take one of the well-described tasks from the [Good First Issue](https://github.com/orgs/openvinotoolkit/projects/3/views/14) section. It can be a great start to contributing with codeowners' support!


## Let's code

Get familiar with Node.js API architecture and code samples.
Refer to the [guide](../docs/code_examples.md), which will help you understand the component structure and the code style.

The environment setup and build instructions can be found in [Building the Node.js API](https://github.com/openvinotoolkit/openvino/blob/master/src/bindings/js/docs/README.md#openvino-node-package-developer-documentation).

Run tests! If you add a new functionality, make sure that it is covered by tests first.
Read [the guide](../docs/test_examples.md) for more details about the tests and their runs.
Many CI checks will run after getting a Code Review. Make sure that
all checks have passed. CI checks are composed of both functional tests and code-style checks and may fail because of warnings/errors in both stages.

Remember to follow [our codestyle](../docs/CODESTYLE.md).
By following the provided guide and using an automotive code style checking tool, like
**eslint** and **clang-format-9**, you will save some time and help with the code review of proposed changes.


## Description of the Pull Request

Append all PR titles with the `[OV JS]` tag. Provide any relevant details in the description, as it will definitely help with the review. The minimum requirement is a compact, bulleted list of proposed changes.

Use the following template:
```
*Describe what is the purpose of this PR*
### Details:
- *Describe your changes.*
- ...
```


## License

By contributing to the OpenVINO project, you agree that your contributions will be
licensed under the terms of the [LICENSE](https://github.com/openvinotoolkit/openvino/blob/master/LICENSE).
Loading

0 comments on commit cb56c19

Please sign in to comment.