From cb56c190eca9537ef331e96a8f45891ed13c443c Mon Sep 17 00:00:00 2001 From: Sebastian Golebiewski Date: Mon, 21 Oct 2024 10:36:54 +0200 Subject: [PATCH] [OV JS][DOCS] Edits in JS API docs (#27064) Porting: https://github.com/openvinotoolkit/openvino/pull/26875 --------- Co-authored-by: Roman Kazantsev --- CONTRIBUTING.md | 1 + src/bindings/js/docs/CODESTYLE.md | 6 ++ src/bindings/js/docs/README.md | 11 +- src/bindings/js/docs/code_examples.md | 146 ++++++++++++++++++++++++++ src/bindings/js/docs/test_examples.md | 88 ++++++++++++++++ src/bindings/js/node/CONTRIBUTING.md | 67 ++++++++++++ src/bindings/js/node/README.md | 30 +++++- src/bindings/js/node/package.json | 5 +- 8 files changed, 342 insertions(+), 12 deletions(-) create mode 100644 src/bindings/js/docs/code_examples.md create mode 100644 src/bindings/js/docs/test_examples.md create mode 100644 src/bindings/js/node/CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7169ebc2ba2c9b..c30ce12665ab33 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -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) diff --git a/src/bindings/js/docs/CODESTYLE.md b/src/bindings/js/docs/CODESTYLE.md index 0ebfd322767b57..9b9bc58b7dea48 100644 --- a/src/bindings/js/docs/CODESTYLE.md +++ b/src/bindings/js/docs/CODESTYLE.md @@ -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 @@ -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/). diff --git a/src/bindings/js/docs/README.md b/src/bindings/js/docs/README.md index bada676878847f..f0c70cf4dd9aed 100644 --- a/src/bindings/js/docs/README.md +++ b/src/bindings/js/docs/README.md @@ -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 @@ -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 \ @@ -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 diff --git a/src/bindings/js/docs/code_examples.md b/src/bindings/js/docs/code_examples.md new file mode 100644 index 00000000000000..08d92e7307dbfe --- /dev/null +++ b/src/bindings/js/docs/code_examples.md @@ -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 `/src/bindings/js/node/include/my_tensor.hpp`. This file should contain the necessary includes and class definitions: +```cpp +class MyTensor : public Napi::ObjectWrap { +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 `/src/bindings/js/node/src/my_tensor.cpp` +```cpp +MyTensor::MyTensor(const Napi::CallbackInfo& info) : Napi::ObjectWrap(info) { + std::vector allowed_signatures; + + try { + if (ov::js::validate(info, allowed_signatures)) { + const auto type = js_to_cpp(info, 0); + const auto& shape = js_to_cpp(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 `/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`, 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(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 `/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) diff --git a/src/bindings/js/docs/test_examples.md b/src/bindings/js/docs/test_examples.md new file mode 100644 index 00000000000000..0e75cb56f3a700 --- /dev/null +++ b/src/bindings/js/docs/test_examples.md @@ -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 /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 `/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) diff --git a/src/bindings/js/node/CONTRIBUTING.md b/src/bindings/js/node/CONTRIBUTING.md new file mode 100644 index 00000000000000..aacef418aeed2d --- /dev/null +++ b/src/bindings/js/node/CONTRIBUTING.md @@ -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). diff --git a/src/bindings/js/node/README.md b/src/bindings/js/node/README.md index e2c38f2a18e516..c927bd0b360ed4 100644 --- a/src/bindings/js/node/README.md +++ b/src/bindings/js/node/README.md @@ -1,8 +1,14 @@ # OpenVINO™ Node.js Bindings -Use OpenVINO JavaScript API for your Node.js application. +Use OpenVINO to deploy deep learning models easily in Node.js applications. -## Usage +## Introduction + +OpenVINO™ is an open-source toolkit designed for high-performance deep learning inference. +Node.js API provides bindings to subset APIs from OpenVINO Runtime. +The Node.js bindings enable JavaScript developers to use the capabilities of OpenVINO in their applications. + +## Quick Start Install the **openvino-node** package: ```bash @@ -14,15 +20,21 @@ Use the **openvino-node** package: const { addon: ov } = require('openvino-node'); ``` +Refer to the complete description of the `addon` API in the [documentation](https://docs.openvino.ai/2024/api/nodejs_api/addon.html). + +See the [samples](https://github.com/openvinotoolkit/openvino/blob/master/samples/js/node/README.md) for more details on how to use it. + ## Usage in Electron applications To use the package in development of Electron applications on Windows, make sure that **Desktop development with C++** component from [Build Tools for Visual Studio](https://aka.ms/vs/17/release/vs_BuildTools.exe) is installed. -## Build From Sources +## Supported Platforms -For more details, refer to the [OpenVINO™ JavaScript API Developer Documentation](https://github.com/openvinotoolkit/openvino/blob/master/src/bindings/js/docs/README.md#openvino-node-package-developer-documentation) +- Windows x86 +- Linux x86/ARM +- MacOS x86/ARM ## Documentation & Samples @@ -31,11 +43,19 @@ For more details, refer to the [OpenVINO™ JavaScript API Developer Documentati ## Live Sample -You can run this sample in the browser; no installation is required. +You can run the following sample in the browser, no installation is required. [Codesandbox](https://codesandbox.io/) is a free online service with limited resources. For optimal performance and more control, it is recommended to run the sample locally. - [hello-classification-sample](https://codesandbox.io/p/devbox/openvino-node-hello-classification-sample-djl893) +## Build From Sources + +For more details, refer to the [OpenVINO™ JavaScript API Developer Documentation](https://github.com/openvinotoolkit/openvino/blob/master/src/bindings/js/docs/README.md#openvino-node-package-developer-documentation) + +## Contributing + +Contributions are always welcome! 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 * [OpenVINO™ README](https://github.com/openvinotoolkit/openvino/blob/master/README.md) diff --git a/src/bindings/js/node/package.json b/src/bindings/js/node/package.json index d00633c93b062a..8bc6bbd4bb1d46 100644 --- a/src/bindings/js/node/package.json +++ b/src/bindings/js/node/package.json @@ -48,5 +48,8 @@ "remote_path": "./repositories/openvino/nodejs_bindings/{version}/{platform}/", "package_name": "openvino_nodejs_bindings_{platform}_{version}_{arch}.tar.gz", "host": "https://storage.openvinotoolkit.org" - } + }, + "keywords": [ + "OpenVINO" + ] }