1 /* 2 * Copyright (C) 2021-2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16 #ifndef INTERFACES_KITS_JS_MEDIALIBRARY_INCLUDE_MEDIALIBRARY_NAPI_UTILS_H_ 17 #define INTERFACES_KITS_JS_MEDIALIBRARY_INCLUDE_MEDIALIBRARY_NAPI_UTILS_H_ 18 19 #include <vector> 20 21 #include "datashare_predicates.h" 22 #include "datashare_result_set.h" 23 #include "media_column.h" 24 #include "medialibrary_db_const.h" 25 #include "medialibrary_napi_log.h" 26 #include "napi/native_api.h" 27 #include "napi/native_node_api.h" 28 #include "photo_album_column.h" 29 30 #define GET_JS_ARGS(env, info, argc, argv, thisVar) \ 31 do { \ 32 void *data; \ 33 napi_get_cb_info(env, info, &(argc), argv, &(thisVar), &(data)); \ 34 } while (0) 35 36 #define GET_JS_OBJ_WITH_ZERO_ARGS(env, info, status, thisVar) \ 37 do { \ 38 void *data; \ 39 status = napi_get_cb_info(env, info, nullptr, nullptr, &(thisVar), &(data)); \ 40 } while (0) 41 42 #define GET_JS_ASYNC_CB_REF(env, arg, count, cbRef) \ 43 do { \ 44 napi_valuetype valueType = napi_undefined; \ 45 if ((napi_typeof(env, arg, &valueType) == napi_ok) && (valueType == napi_function)) { \ 46 napi_create_reference(env, arg, count, &(cbRef)); \ 47 } else { \ 48 NAPI_ERR_LOG("invalid arguments"); \ 49 NAPI_ASSERT(env, false, "type mismatch"); \ 50 } \ 51 } while (0) 52 53 #define ASSERT_NULLPTR_CHECK(env, result) \ 54 do { \ 55 if ((result) == nullptr) { \ 56 napi_get_undefined(env, &(result)); \ 57 return result; \ 58 } \ 59 } while (0) 60 61 #define NAPI_CREATE_PROMISE(env, callbackRef, deferred, result) \ 62 do { \ 63 if ((callbackRef) == nullptr) { \ 64 napi_create_promise(env, &(deferred), &(result)); \ 65 } \ 66 } while (0) 67 68 #define NAPI_CREATE_RESOURCE_NAME(env, resource, resourceName, context) \ 69 do { \ 70 napi_create_string_utf8(env, resourceName, NAPI_AUTO_LENGTH, &(resource)); \ 71 (context)->SetApiName(resourceName); \ 72 } while (0) 73 74 #define CHECK_NULL_PTR_RETURN_UNDEFINED(env, ptr, ret, message) \ 75 do { \ 76 if ((ptr) == nullptr) { \ 77 NAPI_ERR_LOG(message); \ 78 napi_get_undefined(env, &(ret)); \ 79 return ret; \ 80 } \ 81 } while (0) 82 83 #define CHECK_NULL_PTR_RETURN_VOID(ptr, message) \ 84 do { \ 85 if ((ptr) == nullptr) { \ 86 NAPI_ERR_LOG(message); \ 87 return; \ 88 } \ 89 } while (0) 90 #define CHECK_IF_EQUAL(condition, errMsg) \ 91 do { \ 92 if (!(condition)) { \ 93 NAPI_ERR_LOG(errMsg); \ 94 return; \ 95 } \ 96 } while (0) 97 98 #define CHECK_COND_RET(cond, ret, message) \ 99 do { \ 100 if (!(cond)) { \ 101 NAPI_ERR_LOG(message); \ 102 return ret; \ 103 } \ 104 } while (0) 105 106 #define CHECK_STATUS_RET(cond, message) \ 107 do { \ 108 napi_status __ret = (cond); \ 109 if (__ret != napi_ok) { \ 110 NAPI_ERR_LOG(message); \ 111 return __ret; \ 112 } \ 113 } while (0) 114 115 #define CHECK_NULLPTR_RET(ret) \ 116 do { \ 117 if ((ret) == nullptr) { \ 118 return nullptr; \ 119 } \ 120 } while (0) 121 122 #define CHECK_ARGS_BASE(env, cond, err, retVal) \ 123 do { \ 124 if ((cond) != napi_ok) { \ 125 NapiError::ThrowError(env, err, __FUNCTION__, __LINE__); \ 126 return retVal; \ 127 } \ 128 } while (0) 129 130 #define CHECK_ARGS(env, cond, err) CHECK_ARGS_BASE(env, cond, err, nullptr) 131 132 #define CHECK_ARGS_RET_VOID(env, cond, err) CHECK_ARGS_BASE(env, cond, err, NAPI_RETVAL_NOTHING) 133 134 #define CHECK_COND(env, cond, err) \ 135 do { \ 136 if (!(cond)) { \ 137 NapiError::ThrowError(env, err, __FUNCTION__, __LINE__); \ 138 return nullptr; \ 139 } \ 140 } while (0) 141 142 namespace OHOS { 143 namespace Media { 144 145 /* Constants for array index */ 146 const int32_t PARAM0 = 0; 147 const int32_t PARAM1 = 1; 148 const int32_t PARAM2 = 2; 149 const int32_t PARAM3 = 3; 150 151 /* Constants for array size */ 152 const int32_t ARGS_ZERO = 0; 153 const int32_t ARGS_ONE = 1; 154 const int32_t ARGS_TWO = 2; 155 const int32_t ARGS_THREE = 3; 156 const int32_t ARGS_FOUR = 4; 157 const int32_t ARG_BUF_SIZE = 100; 158 constexpr uint32_t NAPI_INIT_REF_COUNT = 1; 159 160 constexpr size_t NAPI_ARGC_MAX = 4; 161 162 // Error codes 163 const int32_t ERR_DEFAULT = 0; 164 const int32_t ERR_MEM_ALLOCATION = 2; 165 const int32_t ERR_INVALID_OUTPUT = 3; 166 167 const int32_t TRASH_SMART_ALBUM_ID = 1; 168 const std::string TRASH_SMART_ALBUM_NAME = "TrashAlbum"; 169 const int32_t FAVORIT_SMART_ALBUM_ID = 2; 170 const std::string FAVORIT_SMART_ALBUM_NAME = "FavoritAlbum"; 171 172 const std::string API_VERSION = "api_version"; 173 174 enum NapiAssetType { 175 TYPE_DEFAULT = 0, 176 TYPE_AUDIO = 1, 177 TYPE_PHOTO = 2, 178 TYPE_ALBUM = 3, 179 }; 180 181 enum AlbumType { 182 TYPE_VIDEO_ALBUM = 0, 183 TYPE_IMAGE_ALBUM = 1, 184 TYPE_NONE = 2, 185 }; 186 187 enum FetchOptionType { 188 ASSET_FETCH_OPT = 0, 189 ALBUM_FETCH_OPT = 1 190 }; 191 192 const std::vector<std::string> privateAlbumTypeNameEnum { 193 "TYPE_FAVORITE", "TYPE_TRASH", "TYPE_HIDE", "TYPE_SMART", "TYPE_SEARCH" 194 }; 195 196 const std::vector<std::string> mediaTypesEnum { 197 "FILE", "IMAGE", "VIDEO", "AUDIO", "MEDIA", "ALBUM_LIST", "ALBUM_LIST_INFO" 198 }; 199 200 const std::vector<std::string> mediaTypesUserFileEnum { 201 "IMAGE", "VIDEO", "AUDIO" 202 }; 203 204 const std::vector<std::string> fileKeyEnum { 205 "ID", "RELATIVE_PATH", "DISPLAY_NAME", "PARENT", "MIME_TYPE", "MEDIA_TYPE", "SIZE", 206 "DATE_ADDED", "DATE_MODIFIED", "DATE_TAKEN", "TITLE", "ARTIST", "AUDIOALBUM", "DURATION", 207 "WIDTH", "HEIGHT", "ORIENTATION", "ALBUM_ID", "ALBUM_NAME" 208 }; 209 210 const std::vector<std::string> directoryEnum { 211 "DIR_CAMERA", "DIR_VIDEO", "DIR_IMAGE", "DIR_AUDIO", "DIR_DOCUMENTS", "DIR_DOWNLOAD" 212 }; 213 214 const std::vector<std::string> virtualAlbumTypeEnum { 215 "TYPE_FAVORITE", "TYPE_TRASH" 216 }; 217 218 const std::vector<std::string> directoryEnumValues { 219 "Camera/", 220 "Videos/", 221 "Pictures/", 222 "Audios/", 223 "Documents/", 224 "Download/" 225 }; 226 227 const std::vector<std::string> systemAlbumSubType { 228 "FAVORITE", "VIDEO", "HIDDEN", "TRASH", "SCREENSHOT", "CAMERA", "IMAGES" 229 }; 230 231 const std::vector<std::string> positionTypeEnum { 232 "LOCAL", "CLOUD", "BOTH" 233 }; 234 235 const std::vector<std::string> photoSubTypeEnum { 236 "DEFAULT", "SCREENSHOT", "CAMERA" 237 }; 238 239 const std::vector<std::string> notifyTypeEnum { 240 "NOTIFY_ADD", "NOTIFY_UPDATE", "NOTIFY_REMOVE", "NOTIFY_ALBUM_ADD_ASSET", "NOTIFY_ALBUM_REMOVE_ASSET" 241 }; 242 243 const std::vector<std::string> fileKeyEnumValues { 244 MEDIA_DATA_DB_ID, 245 MEDIA_DATA_DB_RELATIVE_PATH, 246 MEDIA_DATA_DB_NAME, 247 MEDIA_DATA_DB_PARENT_ID, 248 MEDIA_DATA_DB_MIME_TYPE, 249 MEDIA_DATA_DB_MEDIA_TYPE, 250 MEDIA_DATA_DB_SIZE, 251 MEDIA_DATA_DB_DATE_ADDED, 252 MEDIA_DATA_DB_DATE_MODIFIED, 253 MEDIA_DATA_DB_DATE_TAKEN, 254 MEDIA_DATA_DB_TITLE, 255 MEDIA_DATA_DB_ARTIST, 256 MEDIA_DATA_DB_AUDIO_ALBUM, 257 MEDIA_DATA_DB_DURATION, 258 MEDIA_DATA_DB_WIDTH, 259 MEDIA_DATA_DB_HEIGHT, 260 MEDIA_DATA_DB_ORIENTATION, 261 MEDIA_DATA_DB_BUCKET_ID, 262 MEDIA_DATA_DB_BUCKET_NAME 263 }; 264 265 const std::vector<std::pair<std::string, std::string>> FILE_KEY_ENUM_PROPERTIES = { 266 std::make_pair("ID", MEDIA_DATA_DB_ID), 267 std::make_pair("RELATIVE_PATH", MEDIA_DATA_DB_RELATIVE_PATH), 268 std::make_pair("DISPLAY_NAME", MEDIA_DATA_DB_NAME), 269 std::make_pair("PARENT", MEDIA_DATA_DB_PARENT_ID), 270 std::make_pair("MIME_TYPE", MEDIA_DATA_DB_MIME_TYPE), 271 std::make_pair("MEDIA_TYPE", MEDIA_DATA_DB_MEDIA_TYPE), 272 std::make_pair("SIZE", MEDIA_DATA_DB_SIZE), 273 std::make_pair("DATE_ADDED", MEDIA_DATA_DB_DATE_ADDED), 274 std::make_pair("DATE_MODIFIED", MEDIA_DATA_DB_DATE_MODIFIED), 275 std::make_pair("DATE_TAKEN", MEDIA_DATA_DB_DATE_TAKEN), 276 std::make_pair("TITLE", MEDIA_DATA_DB_TITLE), 277 std::make_pair("ARTIST", MEDIA_DATA_DB_ARTIST), 278 std::make_pair("AUDIOALBUM", MEDIA_DATA_DB_AUDIO_ALBUM), 279 std::make_pair("DURATION", MEDIA_DATA_DB_DURATION), 280 std::make_pair("WIDTH", MEDIA_DATA_DB_WIDTH), 281 std::make_pair("HEIGHT", MEDIA_DATA_DB_HEIGHT), 282 std::make_pair("ORIENTATION", MEDIA_DATA_DB_ORIENTATION), 283 std::make_pair("ALBUM_ID", MEDIA_DATA_DB_BUCKET_ID), 284 std::make_pair("ALBUM_NAME", MEDIA_DATA_DB_BUCKET_NAME) 285 }; 286 287 const std::vector<std::pair<std::string, std::string>> USERFILEMGR_FILEKEY_ENUM_PROPERTIES = { 288 std::make_pair("URI", MEDIA_DATA_DB_URI), 289 std::make_pair("RELATIVE_PATH", MEDIA_DATA_DB_RELATIVE_PATH), 290 std::make_pair("DISPLAY_NAME", MEDIA_DATA_DB_NAME), 291 std::make_pair("DATE_ADDED", MEDIA_DATA_DB_DATE_ADDED), 292 std::make_pair("DATE_MODIFIED", MEDIA_DATA_DB_DATE_MODIFIED), 293 std::make_pair("TITLE", MEDIA_DATA_DB_TITLE) 294 }; 295 296 const std::vector<std::pair<std::string, std::string>> AUDIOKEY_ENUM_PROPERTIES = { 297 std::make_pair("URI", MEDIA_DATA_DB_URI), 298 std::make_pair("DISPLAY_NAME", MEDIA_DATA_DB_NAME), 299 std::make_pair("DATE_ADDED", MEDIA_DATA_DB_DATE_ADDED), 300 std::make_pair("DATE_MODIFIED", MEDIA_DATA_DB_DATE_MODIFIED), 301 std::make_pair("TITLE", MEDIA_DATA_DB_TITLE), 302 std::make_pair("ARTIST", MEDIA_DATA_DB_ARTIST), 303 std::make_pair("AUDIOALBUM", MEDIA_DATA_DB_AUDIO_ALBUM), 304 std::make_pair("DURATION", MEDIA_DATA_DB_DURATION), 305 std::make_pair("FAVORITE", MEDIA_DATA_DB_IS_FAV), 306 std::make_pair("SIZE", MediaColumn::MEDIA_SIZE), 307 std::make_pair("PACKAGE_NAME", MediaColumn::MEDIA_PACKAGE_NAME) 308 }; 309 310 const std::vector<std::pair<std::string, std::string>> IMAGEVIDEOKEY_ENUM_PROPERTIES = { 311 std::make_pair("URI", MEDIA_DATA_DB_URI), 312 std::make_pair("DISPLAY_NAME", MediaColumn::MEDIA_NAME), 313 std::make_pair("DATE_ADDED", MediaColumn::MEDIA_DATE_ADDED), 314 std::make_pair("FILE_TYPE", MediaColumn::MEDIA_TYPE), 315 std::make_pair("PHOTO_TYPE", MediaColumn::MEDIA_TYPE), 316 std::make_pair("DATE_MODIFIED", MediaColumn::MEDIA_DATE_MODIFIED), 317 std::make_pair("TITLE", MediaColumn::MEDIA_TITLE), 318 std::make_pair("DURATION", MediaColumn::MEDIA_DURATION), 319 std::make_pair("WIDTH", PhotoColumn::PHOTO_WIDTH), 320 std::make_pair("HEIGHT", PhotoColumn::PHOTO_HEIGHT), 321 std::make_pair("DATE_TAKEN", MediaColumn::MEDIA_DATE_TAKEN), 322 std::make_pair("ORIENTATION", PhotoColumn::PHOTO_ORIENTATION), 323 std::make_pair("FAVORITE", MediaColumn::MEDIA_IS_FAV), 324 std::make_pair("MEDIA_TYPE", MediaColumn::MEDIA_TYPE), 325 std::make_pair("DATE_TRASHED", MediaColumn::MEDIA_DATE_TRASHED), 326 std::make_pair("POSITION", PhotoColumn::PHOTO_POSITION), 327 std::make_pair("HIDDEN", MediaColumn::MEDIA_HIDDEN), 328 std::make_pair("SIZE", MediaColumn::MEDIA_SIZE), 329 std::make_pair("PACKAGE_NAME", MediaColumn::MEDIA_PACKAGE_NAME), 330 std::make_pair("CAMERA_SHOT_KEY", PhotoColumn::CAMERA_SHOT_KEY), 331 std::make_pair("USER_COMMENT", PhotoColumn::PHOTO_USER_COMMENT), 332 }; 333 334 const std::vector<std::pair<std::string, std::string>> ALBUMKEY_ENUM_PROPERTIES = { 335 std::make_pair("URI", MEDIA_DATA_DB_URI), 336 std::make_pair("ALBUM_NAME", PhotoAlbumColumns::ALBUM_NAME), 337 std::make_pair("FILE_TYPE", MEDIA_DATA_DB_MEDIA_TYPE), 338 std::make_pair("DATE_ADDED", MEDIA_DATA_DB_DATE_ADDED), 339 std::make_pair("DATE_MODIFIED", MEDIA_DATA_DB_DATE_MODIFIED) 340 }; 341 342 const std::vector<std::pair<std::string, std::string>> DEFAULT_URI_ENUM_PROPERTIES = { 343 std::make_pair("DEFAULT_PHOTO_URI", PhotoColumn::DEFAULT_PHOTO_URI), 344 std::make_pair("DEFAULT_ALBUM_URI", PhotoAlbumColumns::DEFAULT_PHOTO_ALBUM_URI), 345 std::make_pair("DEFAULT_AUDIO_URI", AudioColumn::DEFAULT_AUDIO_URI) 346 }; 347 348 struct JSAsyncContextOutput { 349 napi_value error; 350 napi_value data; 351 bool status; 352 }; 353 354 struct NapiClassInfo { 355 std::string name; 356 napi_ref *ref; 357 napi_value (*constructor)(napi_env, napi_callback_info); 358 std::vector<napi_property_descriptor> props; 359 }; 360 361 /* Util class used by napi asynchronous methods for making call to js callback function */ 362 class MediaLibraryNapiUtils { 363 public: 364 static napi_value NapiDefineClass(napi_env env, napi_value exports, const NapiClassInfo &info); 365 static napi_value NapiAddStaticProps(napi_env env, napi_value exports, 366 const std::vector<napi_property_descriptor> &staticProps); 367 368 static napi_status GetUInt32(napi_env env, napi_value arg, uint32_t &value); 369 static napi_status GetInt32(napi_env env, napi_value arg, int32_t &value); 370 static napi_status GetParamBool(napi_env env, napi_value arg, bool &result); 371 static napi_status GetUInt32Array(napi_env env, napi_value arg, std::vector<uint32_t> ¶m); 372 static napi_status GetParamFunction(napi_env env, napi_value arg, napi_ref &callbackRef); 373 static napi_status GetParamString(napi_env env, napi_value arg, std::string &str); 374 static napi_status GetParamStringPathMax(napi_env env, napi_value arg, std::string &str); 375 static napi_status GetProperty(napi_env env, const napi_value arg, const std::string &propName, 376 std::string &propValue); 377 static napi_status GetArrayProperty(napi_env env, napi_value arg, const std::string &propName, 378 std::vector<std::string> &array); 379 static napi_status GetStringArray(napi_env env, napi_value arg, std::vector<std::string> &array); 380 static void UriAddTableName(std::string &uri, const std::string tableName); 381 static std::string GetFileIdFromUri(const std::string &uri); 382 static MediaType GetMediaTypeFromUri(const std::string &uri); 383 template <class AsyncContext> 384 static napi_status GetPredicate(napi_env env, const napi_value arg, const std::string &propName, 385 AsyncContext &context, const FetchOptionType &fetchOptType); 386 template <class AsyncContext> 387 static napi_status ParseAlbumFetchOptCallback(napi_env env, napi_callback_info info, AsyncContext &context); 388 template <class AsyncContext> 389 static bool HandleSpecialPredicate(AsyncContext &context, 390 std::shared_ptr<DataShare::DataShareAbsPredicates> &predicate, const FetchOptionType &fetchOptType); 391 template <class AsyncContext> 392 static void UpdateMediaTypeSelections(AsyncContext *context); 393 394 template <class AsyncContext> 395 static napi_status AsyncContextSetObjectInfo(napi_env env, napi_callback_info info, AsyncContext &asyncContext, 396 const size_t minArgs, const size_t maxArgs); 397 398 template <class AsyncContext> 399 static napi_status GetFetchOption(napi_env env, napi_value arg, const FetchOptionType &fetchOptType, 400 AsyncContext &context); 401 402 template <class AsyncContext> 403 static napi_status GetAlbumFetchOption(napi_env env, napi_value arg, const FetchOptionType &fetchOptType, 404 AsyncContext &context); 405 406 template <class AsyncContext> 407 static napi_status GetParamCallback(napi_env env, AsyncContext &context); 408 409 template <class AsyncContext> 410 static napi_status ParseAssetFetchOptCallback(napi_env env, napi_callback_info info, 411 AsyncContext &context); 412 413 template <class AsyncContext> 414 static napi_status ParseArgsBoolCallBack(napi_env env, napi_callback_info info, AsyncContext &context, bool ¶m); 415 416 template <class AsyncContext> 417 static napi_status ParseArgsStringCallback(napi_env env, napi_callback_info info, AsyncContext &context, 418 std::string ¶m); 419 template <class AsyncContext> 420 static napi_status ParseArgsStringArrayCallback(napi_env env, napi_callback_info info, 421 AsyncContext &context, std::vector<std::string> &array); 422 423 template <class AsyncContext> 424 static napi_status ParseArgsNumberCallback(napi_env env, napi_callback_info info, AsyncContext &context, 425 int32_t &value); 426 427 template <class AsyncContext> 428 static napi_status ParseArgsOnlyCallBack(napi_env env, napi_callback_info info, AsyncContext &context); 429 430 static AssetType GetAssetType(MediaType type); 431 432 static void AppendFetchOptionSelection(std::string &selection, const std::string &newCondition); 433 434 static int TransErrorCode(const std::string &Name, std::shared_ptr<DataShare::DataShareResultSet> resultSet); 435 436 static int TransErrorCode(const std::string &Name, int error); 437 438 static void HandleError(napi_env env, int error, napi_value &errorObj, const std::string &Name); 439 440 static void CreateNapiErrorObject(napi_env env, napi_value &errorObj, const int32_t errCode, 441 const std::string errMsg); 442 443 static void InvokeJSAsyncMethod(napi_env env, napi_deferred deferred, napi_ref callbackRef, napi_async_work work, 444 const JSAsyncContextOutput &asyncContext); 445 446 template <class AsyncContext> 447 static napi_value NapiCreateAsyncWork(napi_env env, std::unique_ptr<AsyncContext> &asyncContext, 448 const std::string &resourceName, void (*execute)(napi_env, void *), 449 void (*complete)(napi_env, napi_status, void *)); 450 451 static std::tuple<bool, std::unique_ptr<char[]>, size_t> ToUTF8String(napi_env env, napi_value value); 452 453 static bool IsExistsByPropertyName(napi_env env, napi_value jsObject, const char *propertyName); 454 455 static napi_value GetPropertyValueByName(napi_env env, napi_value jsObject, const char *propertyName); 456 457 static bool CheckJSArgsTypeAsFunc(napi_env env, napi_value arg); 458 459 static bool IsArrayForNapiValue(napi_env env, napi_value param, uint32_t &arraySize); 460 461 static napi_status HasCallback(napi_env env, const size_t argc, const napi_value argv[], 462 bool &isCallback); 463 464 static napi_value GetInt32Arg(napi_env env, napi_value arg, int32_t &value); 465 466 static void UriAppendKeyValue(std::string &uri, const std::string &key, const std::string &value); 467 468 static napi_value AddDefaultAssetColumns(napi_env env, std::vector<std::string> &fetchColumn, 469 std::function<bool(const std::string &columnName)> isValidColumn, 470 const PhotoAlbumSubType subType = PhotoAlbumSubType::USER_GENERIC); 471 472 static int32_t GetSystemAlbumPredicates(const PhotoAlbumSubType subType, 473 DataShare::DataSharePredicates &predicates); 474 static int32_t GetUserAlbumPredicates(const int32_t albumId, DataShare::DataSharePredicates &predicates); 475 static bool IsSystemApp(); 476 477 private: 478 static napi_status hasFetchOpt(napi_env env, const napi_value arg, bool &hasFetchOpt); 479 }; 480 } // namespace Media 481 } // namespace OHOS 482 483 #endif // INTERFACES_KITS_JS_MEDIALIBRARY_INCLUDE_MEDIALIBRARY_NAPI_UTILS_H_ 484