Skip to content

Commit cb56c19

Browse files
[OV JS][DOCS] Edits in JS API docs (#27064)
Porting: #26875 --------- Co-authored-by: Roman Kazantsev <roman.kazantsev@intel.com>
1 parent e16e4d4 commit cb56c19

File tree

8 files changed

+342
-12
lines changed

8 files changed

+342
-12
lines changed

CONTRIBUTING.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ Choose the component your Good First Issue is related to. You can run tests to m
115115
- [C API](https://github.com/openvinotoolkit/openvino/tree/master/src/bindings/c)
116116
- [Core](https://github.com/openvinotoolkit/openvino/tree/master/src/core)
117117
- [Python API](https://github.com/openvinotoolkit/openvino/tree/master/src/bindings/python)
118+
- [Node.js API](https://github.com/openvinotoolkit/openvino/tree/master/src/bindings/js/node)
118119

119120
##### Frontends
120121
- [IR Frontend](https://github.com/openvinotoolkit/openvino/tree/master/src/frontends/ir)

src/bindings/js/docs/CODESTYLE.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
# Code Style Guide
22

3+
Node.js bindings contain two parts: C++ and Typescript/JavaScript.
4+
35
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.
46

7+
For C++ codestyle rules, refer to [OpenVINO Coding Guidelines](https://github.com/openvinotoolkit/openvino/blob/master/docs/dev/coding_style.md).
8+
59
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.
610

11+
712
## General Rules
813

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

97+
9298
## Additional Resources
9399

94100
For further details on each rule, refer to the [ESLint documentation](https://eslint.org/docs/rules/).

src/bindings/js/docs/README.md

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22

33
## Folders
44

5-
- `./docs` - documentation
6-
- `./node` - openvino-node npm package
5+
- [./docs](../docs/) - documentation
6+
- [./node](../node/) - openvino-node npm package
77

8-
## openvino-node Package Developer Documentation
8+
## `openvino-node` Package Developer Documentation
99

1010
### Components
1111

@@ -28,7 +28,6 @@
2828
```bash
2929
cmake \
3030
-DCMAKE_BUILD_TYPE=Release \
31-
-DENABLE_FASTER_BUILD=ON \
3231
-DCPACK_GENERATOR=NPM \
3332
-DENABLE_SYSTEM_TBB=OFF -UTBB* \
3433
-DENABLE_TESTS=OFF \
@@ -75,9 +74,9 @@
7574

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

78-
## Contribution
77+
## Contributing
7978

80-
If you want to contribute to the project, refer to the [code style rules](./CODESTYLE.md) and [contribution guide](../../../../CONTRIBUTING.md) first.
79+
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.
8180

8281
## See Also
8382

src/bindings/js/docs/code_examples.md

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# How to extend the OpenVINO™ JavaScript API code
2+
3+
## Build the OpenVINO™ JavaScript API
4+
5+
For detailed build instructions, refer to the [OpenVINO™ JavaScript API documentation](./README.md).
6+
7+
8+
## Project's naming conventions
9+
10+
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.
11+
12+
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()`.
13+
14+
15+
## node-addon-api module
16+
17+
[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).
18+
19+
20+
## Adding a new class and method
21+
22+
To introduce a new `MyTensor` class that interacts with the `ov::Tensor` class, follow these steps:
23+
- The class should facilitate construction from an ov::Tensor instance and allow initialization from a JavaScript element type and shape.
24+
- It should also provide a getElementType method that retrieves the ov::Tensor element type.
25+
26+
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:
27+
```cpp
28+
class MyTensor : public Napi::ObjectWrap<MyTensor> {
29+
public:
30+
// Constructor for the wrapper class
31+
MyTensor(const Napi::CallbackInfo& info);
32+
33+
// It returns a JavaScript class definition
34+
static Napi::Function get_class(Napi::Env env);
35+
36+
// It returns the element type of ov::Tensor
37+
Napi::Value get_element_type(const Napi::CallbackInfo& info);
38+
39+
private:
40+
ov::Tensor _tensor;
41+
};
42+
```
43+
The implementation of the class methods should be placed in a source file at `<openvino_repo>/src/bindings/js/node/src/my_tensor.cpp`
44+
```cpp
45+
MyTensor::MyTensor(const Napi::CallbackInfo& info) : Napi::ObjectWrap<MyTensor>(info) {
46+
std::vector<std::string> allowed_signatures;
47+
48+
try {
49+
if (ov::js::validate<Napi::String, Napi::Array>(info, allowed_signatures)) {
50+
const auto type = js_to_cpp<ov::element::Type_t>(info, 0);
51+
const auto& shape = js_to_cpp<ov::Shape>(info, 1);
52+
this->_tensor = ov::Tensor(type, shape);
53+
} else {
54+
OPENVINO_THROW("'MyTensor' constructor", ov::js::get_parameters_error_msg(info, allowed_signatures));
55+
}
56+
} catch (std::exception& err) {
57+
reportError(info.Env(), err.what());
58+
}
59+
}
60+
61+
Napi::Function MyTensor::get_class(Napi::Env env) {
62+
return DefineClass(env,
63+
"MyTensor",
64+
{
65+
InstanceMethod("getElementType", &MyTensor::get_element_type),
66+
});
67+
}
68+
69+
Napi::Value MyTensor::get_element_type(const Napi::CallbackInfo& info) {
70+
return Napi::String::New(info.Env(), _tensor.get_element_type().to_string());
71+
}
72+
```
73+
Finally, update the `CMakeLists.txt` file at `<openvino_repo>/src/bindings/js/node/` to include the new source file in the build process:
74+
```cmake
75+
add_library(${PROJECT_NAME} SHARED
76+
${CMAKE_CURRENT_SOURCE_DIR}/src/my_tensor.cpp
77+
)
78+
```
79+
80+
81+
### Argument validation and conversion
82+
83+
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.
84+
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.
85+
86+
87+
### New class initialization
88+
89+
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.
90+
```cpp
91+
Napi::Object init_module(Napi::Env env, Napi::Object exports) {
92+
auto addon_data = new AddonData();
93+
env.SetInstanceData<AddonData>(addon_data);
94+
init_class(env, exports, "MyTensor", &MyTensor::get_class, addon_data->my_tensor);
95+
96+
return exports;
97+
}
98+
```
99+
To keep track of the JavaScript class definitions, they are kept in `<openvino_repo>/src/bindings/js/node/include/addon.hpp`.
100+
```cpp
101+
struct AddonData {
102+
Napi::FunctionReference my_tensor;
103+
// and other class references
104+
};
105+
```
106+
107+
### Document the new functionality
108+
109+
The last step is to add the TypeScript type definitions and describe the new functionality.
110+
```typescript
111+
/**
112+
* The {@link MyTensor} class and its documentation.
113+
*/
114+
interface MyTensor {
115+
/**
116+
* It gets the tensor element type.
117+
*/
118+
getElementType(): element;
119+
120+
}
121+
interface MyTensorConstructor {
122+
/**
123+
* It constructs a tensor using the element type and shape. The new tensor
124+
* data will be allocated by default.
125+
* @param type The element type of the new tensor.
126+
* @param shape The shape of the new tensor.
127+
*/
128+
new(type: element | elementTypeString, shape: number[]): MyTensor;
129+
}
130+
131+
export interface NodeAddon {
132+
MyTensor: MyTensorConstructor,
133+
}
134+
```
135+
136+
137+
## Testing the new code
138+
139+
Now that coding is finished, remember to rebuild the project and test it out.
140+
141+
To learn how to test your code, refer to the guide on [how to test OpenVINO™ JavaScript API.](./test_examples.md)
142+
143+
## See also
144+
* [OpenVINO™ README](../../../../README.md)
145+
* [OpenVINO™ bindings README](../../README.md)
146+
* [Developer documentation](../../../../docs/dev/index.md)

src/bindings/js/docs/test_examples.md

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
# How to test the OpenVINO™ JavaScript API
2+
3+
## Build the OpenVINO™ JavaScript API
4+
For detailed build instructions, refer to the [OpenVINO™ JavaScript API documentation](./README.md).
5+
6+
7+
## Run OpenVINO™ JavaScript API tests
8+
*For simplicity, begin by navigating to the [main JavaScript API folder](./../node):*
9+
```shell
10+
cd <openvino_repo>/src/bindings/js/node
11+
```
12+
13+
Use this command to run OpenVINO JavaScript API tests:
14+
```shell
15+
npm run test
16+
```
17+
18+
To run specific test files, you can pass one or more glob patterns:
19+
```shell
20+
node --test "tests/unit/core.test.js" "tests/unit/*model.test.js"
21+
```
22+
23+
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:
24+
25+
```shell
26+
npm run test_setup
27+
```
28+
29+
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).
30+
31+
32+
## Check the code style of the JavaScript API
33+
*ESLint* is a tool to enforce a consistent coding style and to identify and fix potential issues in JavaScript code.
34+
35+
To check the code style of the JavaScript API, run the following commands:
36+
```shell
37+
npm run lint
38+
```
39+
*ESLint* can automatically fix many of the issues it detects. Use following command to run *ESLint* with the fix option on a single file:
40+
```shell
41+
npx eslint --fix "tests/unit/core.test.js"
42+
```
43+
44+
It is recommended to run the code style check each time new tests are added.
45+
46+
47+
## Writing OpenVINO™ JavaScript API tests
48+
49+
### Before start
50+
Follow and complete [Examples of OpenVINO™ JavaScript API code](./code_examples.md).
51+
52+
53+
### Adding new test-case in the correct place
54+
Each new test should verify the correct behavior of the new functionality (e.g. class, method).
55+
56+
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.
57+
58+
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*.
59+
60+
61+
### Test writing guidelines
62+
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*.
63+
64+
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.
65+
66+
```js
67+
const { describe, it, beforeEach } = require('node:test');
68+
describe('ov.Tensor tests', () => {
69+
test('MyTensor.getElementType()', () => {
70+
const tensor = new ov.MyTensor(ov.element.f32, [1, 3]);
71+
assert.strictEqual(tensor.getElementType(), ov.element.f32);
72+
});
73+
74+
});
75+
```
76+
When writing tests, keep the following best practices in mind:
77+
78+
* Focus on testing general usage and edge cases, but avoid excessive testing that leads to redundant test cases and can slow down validation pipelines.
79+
* Avoid initializing shared variables outside of `test` or `beforeEach` blocks to prevent tests from affecting each other.
80+
* Do not test built-in language features; instead, focus on the functionality provided by your code.
81+
* Use hardcoded expected results to verify the correctness of your code. Alternatively, generate reference values at runtime using reliable libraries or methods.
82+
* Extract and reuse common code snippets, such as helper functions or setup code, to improve test readability and maintainability.
83+
84+
85+
## See also
86+
* [OpenVINO™ README](../../../../README.md)
87+
* [OpenVINO™ bindings README](../../README.md)
88+
* [Developer documentation](../../../../docs/dev/index.md)

src/bindings/js/node/CONTRIBUTING.md

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Contributing to OpenVINO™ Node.js API
2+
3+
Your commitment to this project is greatly appreciated and the following guide is intended to help you contribute.
4+
5+
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.
6+
7+
8+
## TLDR
9+
10+
1. Decide what you want to change.
11+
2. Create your fork of the OpenVINO repository.
12+
3. Create a branch with a meaningful name for your changes.
13+
4. Align the code style, commit the changes, and run tests.
14+
5. Create a Pull Request, which clearly describes what has been changed and why.
15+
6. Go through the Code Review.
16+
7. Get your awesome code merged!
17+
18+
Read the section below for more details.
19+
20+
21+
## How to Decide What to Change
22+
23+
In case of minor fixes, like changing variable names, additional parameter checks, etc., go to the next step.
24+
25+
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
26+
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
27+
codeowners. It will prevent you from doing extra work.
28+
29+
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!
30+
31+
32+
## Let's code
33+
34+
Get familiar with Node.js API architecture and code samples.
35+
Refer to the [guide](../docs/code_examples.md), which will help you understand the component structure and the code style.
36+
37+
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).
38+
39+
Run tests! If you add a new functionality, make sure that it is covered by tests first.
40+
Read [the guide](../docs/test_examples.md) for more details about the tests and their runs.
41+
Many CI checks will run after getting a Code Review. Make sure that
42+
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.
43+
44+
Remember to follow [our codestyle](../docs/CODESTYLE.md).
45+
By following the provided guide and using an automotive code style checking tool, like
46+
**eslint** and **clang-format-9**, you will save some time and help with the code review of proposed changes.
47+
48+
49+
## Description of the Pull Request
50+
51+
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.
52+
53+
Use the following template:
54+
```
55+
*Describe what is the purpose of this PR*
56+
57+
### Details:
58+
- *Describe your changes.*
59+
- ...
60+
61+
```
62+
63+
64+
## License
65+
66+
By contributing to the OpenVINO project, you agree that your contributions will be
67+
licensed under the terms of the [LICENSE](https://github.com/openvinotoolkit/openvino/blob/master/LICENSE).

0 commit comments

Comments
 (0)