1 /*
2 * Copyright (c) 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 #define LOG_TAG "JsSingleKVStore"
16 #include "js_single_kv_store.h"
17 #include "js_util.h"
18 #include "js_kv_store_resultset.h"
19 #include "datashare_predicates.h"
20 #include "js_query.h"
21 #include "log_print.h"
22 #include "napi_queue.h"
23 #include "uv_queue.h"
24 #include "kv_utils.h"
25
26 using namespace OHOS::DistributedKv;
27 using namespace OHOS::DataShare;
28 namespace OHOS::DistributedKVStore {
29 inline static uint8_t UNVALID_SUBSCRIBE_TYPE = 255;
30 std::map<std::string, JsSingleKVStore::Exec> JsSingleKVStore::onEventHandlers_ = {
31 { "dataChange", JsSingleKVStore::OnDataChange },
32 { "syncComplete", JsSingleKVStore::OnSyncComplete }
33 };
34
35 std::map<std::string, JsSingleKVStore::Exec> JsSingleKVStore::offEventHandlers_ = {
36 { "dataChange", JsSingleKVStore::OffDataChange },
37 { "syncComplete", JsSingleKVStore::OffSyncComplete }
38 };
39
40 std::map<napi_valuetype, std::string> JsSingleKVStore::valueTypeToString_ = {
41 { napi_string, std::string("string") },
42 { napi_number, std::string("integer") },
43 { napi_object, std::string("bytearray") },
44 { napi_boolean, std::string("bollean") },
45 };
46
ValidSubscribeType(uint8_t type)47 static bool ValidSubscribeType(uint8_t type)
48 {
49 return (SUBSCRIBE_LOCAL <= type) && (type <= SUBSCRIBE_LOCAL_REMOTE);
50 }
51
ToSubscribeType(uint8_t type)52 static SubscribeType ToSubscribeType(uint8_t type)
53 {
54 switch (type) {
55 case 0: // 0 means SUBSCRIBE_TYPE_LOCAL
56 return SubscribeType::SUBSCRIBE_TYPE_LOCAL;
57 case 1: // 1 means SUBSCRIBE_TYPE_REMOTE
58 return SubscribeType::SUBSCRIBE_TYPE_REMOTE;
59 case 2: // 2 means SUBSCRIBE_TYPE_ALL
60 return SubscribeType::SUBSCRIBE_TYPE_ALL;
61 default:
62 return static_cast<SubscribeType>(UNVALID_SUBSCRIBE_TYPE);
63 }
64 }
65
JsSingleKVStore(const std::string & storeId)66 JsSingleKVStore::JsSingleKVStore(const std::string& storeId)
67 : storeId_(storeId)
68 {
69 }
70
SetKvStorePtr(std::shared_ptr<SingleKvStore> kvStore)71 void JsSingleKVStore::SetKvStorePtr(std::shared_ptr<SingleKvStore> kvStore)
72 {
73 kvStore_ = kvStore;
74 }
75
GetKvStorePtr()76 std::shared_ptr<SingleKvStore> JsSingleKVStore::GetKvStorePtr()
77 {
78 return kvStore_;
79 }
80
SetContextParam(std::shared_ptr<ContextParam> param)81 void JsSingleKVStore::SetContextParam(std::shared_ptr<ContextParam> param)
82 {
83 param_ = param;
84 }
85
SetUvQueue(std::shared_ptr<UvQueue> uvQueue)86 void JsSingleKVStore::SetUvQueue(std::shared_ptr<UvQueue> uvQueue)
87 {
88 uvQueue_ = uvQueue;
89 }
90
IsSchemaStore() const91 bool JsSingleKVStore::IsSchemaStore() const
92 {
93 return isSchemaStore_;
94 }
95
SetSchemaInfo(bool isSchemaStore)96 void JsSingleKVStore::SetSchemaInfo(bool isSchemaStore)
97 {
98 isSchemaStore_ = isSchemaStore;
99 }
100
IsSystemApp() const101 bool JsSingleKVStore::IsSystemApp() const
102 {
103 return param_->isSystemApp;
104 }
105
~JsSingleKVStore()106 JsSingleKVStore::~JsSingleKVStore()
107 {
108 ZLOGD("no memory leak for JsSingleKVStore");
109 if (kvStore_ == nullptr) {
110 return;
111 }
112
113 std::lock_guard<std::mutex> lck(listMutex_);
114 for (uint8_t type = SUBSCRIBE_LOCAL; type < SUBSCRIBE_COUNT; type++) {
115 for (auto& observer : dataObserver_[type]) {
116 auto subscribeType = ToSubscribeType(type);
117 kvStore_->UnSubscribeKvStore(subscribeType, observer);
118 observer->Clear();
119 }
120 dataObserver_[type].clear();
121 }
122
123 kvStore_->UnRegisterSyncCallback();
124 for (auto &syncObserver : syncObservers_) {
125 syncObserver->Clear();
126 }
127 syncObservers_.clear();
128 }
129
Constructor(napi_env env)130 napi_value JsSingleKVStore::Constructor(napi_env env)
131 {
132 auto lambda = []() -> std::vector<napi_property_descriptor> {
133 std::vector<napi_property_descriptor> properties = {
134 DECLARE_NAPI_FUNCTION("put", JsSingleKVStore::Put),
135 DECLARE_NAPI_FUNCTION("delete", JsSingleKVStore::Delete),
136 DECLARE_NAPI_FUNCTION("putBatch", JsSingleKVStore::PutBatch),
137 DECLARE_NAPI_FUNCTION("deleteBatch", JsSingleKVStore::DeleteBatch),
138 DECLARE_NAPI_FUNCTION("startTransaction", JsSingleKVStore::StartTransaction),
139 DECLARE_NAPI_FUNCTION("commit", JsSingleKVStore::Commit),
140 DECLARE_NAPI_FUNCTION("rollback", JsSingleKVStore::Rollback),
141 DECLARE_NAPI_FUNCTION("enableSync", JsSingleKVStore::EnableSync),
142 DECLARE_NAPI_FUNCTION("setSyncRange", JsSingleKVStore::SetSyncRange),
143 DECLARE_NAPI_FUNCTION("backup", JsSingleKVStore::Backup),
144 DECLARE_NAPI_FUNCTION("restore", JsSingleKVStore::Restore),
145 DECLARE_NAPI_FUNCTION("deleteBackup", JsSingleKVStore::DeleteBackup),
146
147 DECLARE_NAPI_FUNCTION("get", JsSingleKVStore::Get),
148 DECLARE_NAPI_FUNCTION("getEntries", JsSingleKVStore::GetEntries),
149 DECLARE_NAPI_FUNCTION("getResultSet", JsSingleKVStore::GetResultSet),
150 DECLARE_NAPI_FUNCTION("closeResultSet", JsSingleKVStore::CloseResultSet),
151 DECLARE_NAPI_FUNCTION("getResultSize", JsSingleKVStore::GetResultSize),
152 DECLARE_NAPI_FUNCTION("removeDeviceData", JsSingleKVStore::RemoveDeviceData),
153 DECLARE_NAPI_FUNCTION("sync", JsSingleKVStore::Sync),
154 DECLARE_NAPI_FUNCTION("setSyncParam", JsSingleKVStore::SetSyncParam),
155 DECLARE_NAPI_FUNCTION("getSecurityLevel", JsSingleKVStore::GetSecurityLevel),
156 DECLARE_NAPI_FUNCTION("on", JsSingleKVStore::OnEvent), /* same to JsDeviceKVStore */
157 DECLARE_NAPI_FUNCTION("off", JsSingleKVStore::OffEvent) /* same to JsDeviceKVStore */
158 };
159 return properties;
160 };
161 return JSUtil::DefineClass(env, "ohos.data.distributedKVStore", "SingleKVStore", lambda, JsSingleKVStore::New);
162 }
163
164 /*
165 * [JS API Prototype]
166 * [AsyncCallback]
167 * put(key:string, value:Uint8Array | string | boolean | number, callback: AsyncCallback<void>):void;
168 * [Promise]
169 * put(key:string, value:Uint8Array | string | boolean | number):Promise<void>;
170 */
Put(napi_env env,napi_callback_info info)171 napi_value JsSingleKVStore::Put(napi_env env, napi_callback_info info)
172 {
173 struct PutContext : public ContextBase {
174 std::string key;
175 JSUtil::KvStoreVariant value;
176 };
177 auto ctxt = std::make_shared<PutContext>();
178 ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value* argv) {
179 // required 2 arguments :: <key> <value>
180 ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT,
181 "Parameter error:Mandatory parameters are left unspecified");
182 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->key);
183 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
184 "Parameter error:parameters key must be string");
185 ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->value);
186 if (ctxt->status != napi_ok) {
187 ctxt->isThrowError = true;
188 napi_valuetype ntype = napi_undefined;
189 napi_typeof(env, argv[0], &ntype);
190 auto type = valueTypeToString_.find(ntype);
191 ThrowNapiError(env, Status::INVALID_ARGUMENT, "Parameter error:the type of value must be:" + type->second);
192 return;
193 }
194 });
195 ASSERT_NULL(!ctxt->isThrowError, "Put exit");
196
197 auto execute = [ctxt]() {
198 DistributedKv::Key key(ctxt->key);
199 bool isSchemaStore = reinterpret_cast<JsSingleKVStore *>(ctxt->native)->IsSchemaStore();
200 auto &kvStore = reinterpret_cast<JsSingleKVStore *>(ctxt->native)->kvStore_;
201 DistributedKv::Value value = isSchemaStore ? DistributedKv::Blob(std::get<std::string>(ctxt->value))
202 : JSUtil::VariantValue2Blob(ctxt->value);
203 Status status = kvStore->Put(key, value);
204 ZLOGD("kvStore->Put return %{public}d", status);
205 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
206 napi_ok : napi_generic_failure;
207 };
208 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
209 }
210
211 /*
212 * [JS API Prototype]
213 * [AsyncCallback]
214 * delete(key: string, callback: AsyncCallback<void>): void;
215 * [Promise]
216 * delete(key: string): Promise<void>;
217 */
Delete(napi_env env,napi_callback_info info)218 napi_value JsSingleKVStore::Delete(napi_env env, napi_callback_info info)
219 {
220 struct DeleteContext : public ContextBase {
221 std::string key;
222 std::vector<DistributedKv::Blob> keys;
223 napi_valuetype type;
224 };
225 auto ctxt = std::make_shared<DeleteContext>();
226 ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value* argv) {
227 // required 1 arguments :: <key> || <predicates>
228 ASSERT_BUSINESS_ERR(ctxt, argc == 1, Status::INVALID_ARGUMENT,
229 "Parameter error:Mandatory parameters are left unspecified");
230 ctxt->type = napi_undefined;
231 ctxt->status = napi_typeof(env, argv[0], &(ctxt->type));
232 if (ctxt->type == napi_string) {
233 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->key);
234 ZLOGD("kvStore->Delete %{public}.6s status:%{public}d", ctxt->key.c_str(), ctxt->status);
235 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
236 "Parameter error:parameters key must be string");
237 } else if (ctxt->type == napi_object) {
238 JSUtil::StatusMsg statusMsg = JSUtil::GetValue(env, argv[0], ctxt->keys);
239 ctxt->status = statusMsg.status;
240 ZLOGD("kvStore->Delete status:%{public}d", ctxt->status);
241 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
242 "Parameter error:please check predicates type");
243 ASSERT_PERMISSION_ERR(ctxt,
244 !JSUtil::IsSystemApi(statusMsg.jsApiType) ||
245 reinterpret_cast<JsSingleKVStore *>(ctxt->native)->IsSystemApp(), Status::PERMISSION_DENIED, "");
246 }
247 });
248 ASSERT_NULL(!ctxt->isThrowError, "Delete exit");
249
250 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), [ctxt]() {
251 Status status = Status::INVALID_ARGUMENT;
252 if (ctxt->type == napi_string) {
253 OHOS::DistributedKv::Key key(ctxt->key);
254 auto& kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->kvStore_;
255 status = kvStore->Delete(key);
256 ZLOGD("kvStore->Delete %{public}.6s status:%{public}d", ctxt->key.c_str(), status);
257 } else if (ctxt->type == napi_object) {
258 auto& kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->kvStore_;
259 status = kvStore->DeleteBatch(ctxt->keys);
260 ZLOGD("kvStore->DeleteBatch status:%{public}d", status);
261 }
262 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
263 napi_ok : napi_generic_failure;
264 });
265 }
266
267 /*
268 * [JS API Prototype]
269 * [Callback]
270 * on(event:'syncComplete',syncCallback: Callback<Array<[string, number]>>):void;
271 * on(event:'dataChange', subType: SubscribeType, observer: Callback<ChangeNotification>): void;
272 */
OnEvent(napi_env env,napi_callback_info info)273 napi_value JsSingleKVStore::OnEvent(napi_env env, napi_callback_info info)
274 {
275 auto ctxt = std::make_shared<ContextBase>();
276 auto input = [env, ctxt](size_t argc, napi_value* argv) {
277 // required 2 arguments :: <event> [...] <callback>
278 ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT,
279 "Parameter error:Mandatory parameters are left unspecified");
280 std::string event;
281 ctxt->status = JSUtil::GetValue(env, argv[0], event);
282 ZLOGI("subscribe to event:%{public}s", event.c_str());
283 auto handle = onEventHandlers_.find(event);
284 ASSERT_BUSINESS_ERR(ctxt, handle != onEventHandlers_.end(), Status::INVALID_ARGUMENT,
285 "Parameter error:onevent type must belong dataChange or syncComplete");
286 // shift 1 argument, for JsSingleKVStore::Exec.
287 handle->second(env, argc - 1, &argv[1], ctxt);
288 };
289 ctxt->GetCbInfoSync(env, info, input);
290 ASSERT_NULL(!ctxt->isThrowError, "OnEvent exit");
291 if (ctxt->status != napi_ok) {
292 ThrowNapiError(env, Status::INVALID_ARGUMENT, "");
293 }
294 return nullptr;
295 }
296
297 /*
298 * [JS API Prototype]
299 * [Callback]
300 * off(event:'syncComplete',syncCallback: Callback<Array<[string, number]>>):void;
301 * off(event:'dataChange', subType: SubscribeType, observer: Callback<ChangeNotification>): void;
302 */
OffEvent(napi_env env,napi_callback_info info)303 napi_value JsSingleKVStore::OffEvent(napi_env env, napi_callback_info info)
304 {
305 auto ctxt = std::make_shared<ContextBase>();
306 auto input = [env, ctxt](size_t argc, napi_value* argv) {
307 // required 1 arguments :: <event> [callback]
308 ASSERT_BUSINESS_ERR(ctxt, argc != 0, Status::INVALID_ARGUMENT,
309 "Parameter error:Mandatory parameters are left unspecified");
310 std::string event;
311 ctxt->status = JSUtil::GetValue(env, argv[0], event);
312 ZLOGI("unsubscribe to event:%{public}s", event.c_str());
313 auto handle = offEventHandlers_.find(event);
314 ASSERT_BUSINESS_ERR(ctxt, handle != offEventHandlers_.end(), Status::INVALID_ARGUMENT,
315 "Parameter error:offevent type must belong dataChange or syncComplete");
316 // shift 1 argument, for JsSingleKVStore::Exec.
317 handle->second(env, argc - 1, &argv[1], ctxt);
318 };
319 ctxt->GetCbInfoSync(env, info, input);
320 ASSERT_NULL(!ctxt->isThrowError, "OffEvent exit");
321 if (ctxt->status != napi_ok) {
322 ThrowNapiError(env, Status::INVALID_ARGUMENT, "");
323 }
324 return nullptr;
325 }
326
327 /*
328 * [JS API Prototype]
329 * [AsyncCallback]
330 * putBatch(entries: Entry[], callback: AsyncCallback<void>):void;
331 * putBatch(valuesBucket: ValuesBucket[], callback: AsyncCallback<void>): void;
332 * [Promise]
333 * putBatch(entries: Entry[]):Promise<void>;
334 * putBatch(valuesBuckets: ValuesBucket[]): Promise<void>;
335 */
PutBatch(napi_env env,napi_callback_info info)336 napi_value JsSingleKVStore::PutBatch(napi_env env, napi_callback_info info)
337 {
338 struct PutBatchContext : public ContextBase {
339 std::vector<Entry> entries;
340 };
341 auto ctxt = std::make_shared<PutBatchContext>();
342 ctxt->GetCbInfo(env, info, [env, ctxt](size_t argc, napi_value *argv) {
343 // required 1 arguments :: <entries>
344 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
345 "Parameter error:Mandatory parameters are left unspecified");
346 auto isSchemaStore = reinterpret_cast<JsSingleKVStore *>(ctxt->native)->IsSchemaStore();
347 JSUtil::StatusMsg statusMsg = JSUtil::GetValue(env, argv[0], ctxt->entries, isSchemaStore);
348 ctxt->status = statusMsg.status;
349 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
350 "Parameter error:params entries type must be one of string,number,boolean,array");
351 ASSERT_PERMISSION_ERR(ctxt,
352 !JSUtil::IsSystemApi(statusMsg.jsApiType) ||
353 reinterpret_cast<JsSingleKVStore *>(ctxt->native)->IsSystemApp(), Status::PERMISSION_DENIED, "");
354 });
355 ASSERT_NULL(!ctxt->isThrowError, "PutBatch exit");
356
357 auto execute = [ctxt]() {
358 auto& kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->kvStore_;
359 Status status = kvStore->PutBatch(ctxt->entries);
360 ZLOGD("kvStore->DeleteBatch return %{public}d", status);
361 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
362 napi_ok : napi_generic_failure;
363 };
364 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
365 }
366
367 /*
368 * [JS API Prototype]
369 * [AsyncCallback]
370 * deleteBatch(keys: string[], callback: AsyncCallback<void>):void;
371 * [Promise]
372 * deleteBatch(keys: string[]):Promise<void>;
373 */
DeleteBatch(napi_env env,napi_callback_info info)374 napi_value JsSingleKVStore::DeleteBatch(napi_env env, napi_callback_info info)
375 {
376 struct DeleteBatchContext : public ContextBase {
377 std::vector<std::string> keys;
378 };
379 auto ctxt = std::make_shared<DeleteBatchContext>();
380 auto input = [env, ctxt](size_t argc, napi_value* argv) {
381 // required 1 arguments :: <keys>
382 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
383 "Parameter error:Mandatory parameters are left unspecified");
384 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->keys);
385 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
386 "Parameter error:keys verification must be array");
387 };
388 ctxt->GetCbInfo(env, info, input);
389 ASSERT_NULL(!ctxt->isThrowError, "DeleteBatch exit");
390
391 auto execute = [ctxt]() {
392 std::vector<DistributedKv::Key> keys;
393 for (auto it : ctxt->keys) {
394 DistributedKv::Key key(it);
395 keys.push_back(key);
396 }
397 auto& kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->kvStore_;
398 Status status = kvStore->DeleteBatch(keys);
399 ZLOGD("kvStore->DeleteBatch return %{public}d", status);
400 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
401 napi_ok : napi_generic_failure;
402 };
403 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
404 }
405
406 /*
407 * [JS API Prototype]
408 * [AsyncCallback]
409 * startTransaction(callback: AsyncCallback<void>):void;
410 * [Promise]
411 * startTransaction() : Promise<void>;
412 */
StartTransaction(napi_env env,napi_callback_info info)413 napi_value JsSingleKVStore::StartTransaction(napi_env env, napi_callback_info info)
414 {
415 auto ctxt = std::make_shared<ContextBase>();
416 ctxt->GetCbInfo(env, info);
417 auto execute = [ctxt]() {
418 auto& kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->kvStore_;
419 Status status = kvStore->StartTransaction();
420 ZLOGD("kvStore->StartTransaction return %{public}d", status);
421 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
422 napi_ok : napi_generic_failure;
423 };
424 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
425 }
426
427 /*
428 * [JS API Prototype]
429 * [AsyncCallback]
430 * commit(callback: AsyncCallback<void>):void;
431 * [Promise]
432 * commit() : Promise<void>;
433 */
Commit(napi_env env,napi_callback_info info)434 napi_value JsSingleKVStore::Commit(napi_env env, napi_callback_info info)
435 {
436 auto ctxt = std::make_shared<ContextBase>();
437 ctxt->GetCbInfo(env, info);
438
439 auto execute = [ctxt]() {
440 auto& kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->kvStore_;
441 Status status = kvStore->Commit();
442 ZLOGD("kvStore->Commit return %{public}d", status);
443 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
444 napi_ok : napi_generic_failure;
445 };
446 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
447 }
448
449 /*
450 * [JS API Prototype]
451 * [AsyncCallback]
452 * rollback(callback: AsyncCallback<void>):void;
453 * [Promise]
454 * rollback() : Promise<void>;
455 */
Rollback(napi_env env,napi_callback_info info)456 napi_value JsSingleKVStore::Rollback(napi_env env, napi_callback_info info)
457 {
458 auto ctxt = std::make_shared<ContextBase>();
459 ctxt->GetCbInfo(env, info);
460
461 auto execute = [ctxt]() {
462 auto& kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->kvStore_;
463 Status status = kvStore->Rollback();
464 ZLOGD("kvStore->Commit return %{public}d", status);
465 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
466 napi_ok : napi_generic_failure;
467 };
468 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
469 }
470
471 /*
472 * [JS API Prototype]
473 * [AsyncCallback]
474 * enableSync(enabled:boolean, callback: AsyncCallback<void>):void;
475 * [Promise]
476 * enableSync(enabled:boolean) : Promise<void>;
477 */
EnableSync(napi_env env,napi_callback_info info)478 napi_value JsSingleKVStore::EnableSync(napi_env env, napi_callback_info info)
479 {
480 struct EnableSyncContext : public ContextBase {
481 bool enable = false;
482 };
483 auto ctxt = std::make_shared<EnableSyncContext>();
484 auto input = [env, ctxt](size_t argc, napi_value* argv) {
485 // required 1 arguments :: <enable>
486 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
487 "Parameter error:Mandatory parameters are left unspecified");
488 ctxt->status = napi_get_value_bool(env, argv[0], &ctxt->enable);
489 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
490 "Parameter error:enable must be boolean");
491 };
492 ctxt->GetCbInfo(env, info, input);
493 ASSERT_NULL(!ctxt->isThrowError, "EnableSync exit");
494
495 auto execute = [ctxt]() {
496 auto& kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->kvStore_;
497 Status status = kvStore->SetCapabilityEnabled(ctxt->enable);
498 ZLOGD("kvStore->SetCapabilityEnabled return %{public}d", status);
499 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
500 napi_ok : napi_generic_failure;
501 };
502 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
503 }
504
505 /*
506 * [JS API Prototype]
507 * [AsyncCallback]
508 * setSyncRange(localLabels:string[], remoteSupportLabels:string[], callback: AsyncCallback<void>):void;
509 * [Promise]
510 * setSyncRange(localLabels:string[], remoteSupportLabels:string[]) : Promise<void>;
511 */
SetSyncRange(napi_env env,napi_callback_info info)512 napi_value JsSingleKVStore::SetSyncRange(napi_env env, napi_callback_info info)
513 {
514 struct SyncRangeContext : public ContextBase {
515 std::vector<std::string> localLabels;
516 std::vector<std::string> remoteSupportLabels;
517 };
518 auto ctxt = std::make_shared<SyncRangeContext>();
519 auto input = [env, ctxt](size_t argc, napi_value* argv) {
520 // required 2 arguments :: <localLabels> <remoteSupportLabels>
521 ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT,
522 "Parameter error:Mandatory parameters are left unspecified");
523 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->localLabels);
524 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
525 "Parameter error:parameters localLabels must be array");
526 ctxt->status = JSUtil::GetValue(env, argv[1], ctxt->remoteSupportLabels);
527 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
528 "Parameter error:parameters remoteSupportLabels must be array");
529 };
530 ctxt->GetCbInfo(env, info, input);
531 ASSERT_NULL(!ctxt->isThrowError, "SetSyncRange exit");
532
533 auto execute = [ctxt]() {
534 auto& kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->kvStore_;
535 Status status = kvStore->SetCapabilityRange(ctxt->localLabels, ctxt->remoteSupportLabels);
536 ZLOGD("kvStore->SetCapabilityRange return %{public}d", status);
537 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
538 napi_ok : napi_generic_failure;
539 };
540 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
541 }
542
543 /*
544 * [JS API Prototype]
545 * [AsyncCallback]
546 * backup(file:string, callback: AsyncCallback<void>):void;
547 * [Promise]
548 * backup(file:string): Promise<void>;
549 */
Backup(napi_env env,napi_callback_info info)550 napi_value JsSingleKVStore::Backup(napi_env env, napi_callback_info info)
551 {
552 struct BackupContext : public ContextBase {
553 std::string file;
554 };
555 auto ctxt = std::make_shared<BackupContext>();
556 auto input = [env, ctxt](size_t argc, napi_value* argv) {
557 // required 1 arguments :: <file>
558 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
559 "Parameter error:Mandatory parameters are left unspecified");
560 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->file);
561 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
562 "Parameter error:param file type must be string");
563 ASSERT_BUSINESS_ERR(ctxt, (ctxt->file.size() != 0 && ctxt->file != AUTO_BACKUP_NAME), Status::INVALID_ARGUMENT,
564 "Parameter error:empty file and filename not allow autoBackup");
565 };
566 ctxt->GetCbInfo(env, info, input);
567 ASSERT_NULL(!ctxt->isThrowError, "Backup exit");
568
569 auto execute = [ctxt]() {
570 auto jsKvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native);
571 Status status = jsKvStore->kvStore_->Backup(ctxt->file, jsKvStore->param_->baseDir);
572 ZLOGD("kvStore->Backup return %{public}d", status);
573 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
574 napi_ok : napi_generic_failure;
575 };
576 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
577 }
578
579 /*
580 * [JS API Prototype]
581 * [AsyncCallback]
582 * restore(file:string, callback: AsyncCallback<void>):void;
583 * [Promise]
584 * restore(file:string): Promise<void>;
585 */
Restore(napi_env env,napi_callback_info info)586 napi_value JsSingleKVStore::Restore(napi_env env, napi_callback_info info)
587 {
588 struct RestoreContext : public ContextBase {
589 std::string file;
590 };
591 auto ctxt = std::make_shared<RestoreContext>();
592 auto input = [env, ctxt](size_t argc, napi_value* argv) {
593 // required 1 arguments :: <file>
594 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
595 "Parameter error:Mandatory parameters are left unspecified");
596 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->file);
597 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
598 "Parameter error:get file failed. params type must be string");
599 };
600 ctxt->GetCbInfo(env, info, input);
601 ASSERT_NULL(!ctxt->isThrowError, "Restore exit");
602
603 auto execute = [ctxt]() {
604 auto jsKvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native);
605 Status status = jsKvStore->kvStore_->Restore(ctxt->file, jsKvStore->param_->baseDir);
606 ZLOGD("kvStore->Restore return %{public}d", status);
607 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
608 napi_ok : napi_generic_failure;
609 };
610 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
611 }
612
613 /*
614 * [JS API Prototype]
615 * [AsyncCallback]
616 * deleteBackup(files:Array<string>, callback: AsyncCallback<Array<[string, number]>>):void;
617 * [Promise]
618 * deleteBackup(files:Array<string>): Promise<Array<[string, number]>>;
619 */
DeleteBackup(napi_env env,napi_callback_info info)620 napi_value JsSingleKVStore::DeleteBackup(napi_env env, napi_callback_info info)
621 {
622 struct DeleteBackupContext : public ContextBase {
623 std::vector<std::string> files;
624 std::map<std::string, DistributedKv::Status> results;
625 };
626 auto ctxt = std::make_shared<DeleteBackupContext>();
627 auto input = [env, ctxt](size_t argc, napi_value* argv) {
628 // required 1 arguments :: <files>
629 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
630 "Parameter error:Mandatory parameters are left unspecified");
631 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->files);
632 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
633 "Parameter error:get file failed, params files must be stringArray");
634 };
635 ctxt->GetCbInfo(env, info, input);
636 ASSERT_NULL(!ctxt->isThrowError, "DeleteBackup exit");
637
638 auto execute = [ctxt]() {
639 auto jsKvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native);
640 Status status = jsKvStore->kvStore_->DeleteBackup(ctxt->files,
641 jsKvStore->param_->baseDir, ctxt->results);
642 ZLOGD("kvStore->DeleteBackup return %{public}d", status);
643 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
644 napi_ok : napi_generic_failure;
645 };
646 auto output = [env, ctxt](napi_value& result) {
647 ctxt->status = JSUtil::SetValue(env, ctxt->results, result);
648 ASSERT_STATUS(ctxt, "output failed!");
649 };
650 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
651 }
652
653 /*
654 * [JS API Prototype] JsSingleKVStore::OnDataChange is private non-static.
655 * [Callback]
656 * on(event:'dataChange', subType: SubscribeType, observer: Callback<ChangeNotification>): void;
657 */
OnDataChange(napi_env env,size_t argc,napi_value * argv,std::shared_ptr<ContextBase> ctxt)658 void JsSingleKVStore::OnDataChange(napi_env env, size_t argc, napi_value* argv, std::shared_ptr<ContextBase> ctxt)
659 {
660 // required 2 arguments :: <SubscribeType> <observer>
661 ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT,
662 "Parameter error:Mandatory parameters are left unspecified");
663
664 int32_t type = SUBSCRIBE_COUNT;
665 ctxt->status = napi_get_value_int32(env, argv[0], &type);
666 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, "");
667 ASSERT_BUSINESS_ERR(ctxt, ValidSubscribeType(type), Status::INVALID_ARGUMENT,
668 "Parameter error:parameter event type not exist");
669
670 napi_valuetype valueType = napi_undefined;
671 ctxt->status = napi_typeof(env, argv[1], &valueType);
672 ASSERT_BUSINESS_ERR(ctxt, (ctxt->status == napi_ok) && (valueType == napi_function), Status::INVALID_ARGUMENT,
673 "Parameter error:parameter Callback must be function");
674
675 ZLOGI("subscribe data change type %{public}d", type);
676 auto proxy = reinterpret_cast<JsSingleKVStore*>(ctxt->native);
677 std::lock_guard<std::mutex> lck(proxy->listMutex_);
678 for (auto& it : proxy->dataObserver_[type]) {
679 if (JSUtil::Equals(env, argv[1], it->GetCallback())) {
680 ZLOGI("function is already subscribe type");
681 return;
682 }
683 }
684
685 Status status = proxy->Subscribe(type,
686 std::make_shared<DataObserver>(proxy->uvQueue_, argv[1], proxy->IsSchemaStore()));
687 ThrowNapiError(env, status, "", false);
688 }
689
690 /*
691 * [JS API Prototype] JsSingleKVStore::OffDataChange is private non-static.
692 * [Callback]
693 * on(event:'dataChange', subType: SubscribeType, observer: Callback<ChangeNotification>): void;
694 * [NOTES!!!] no SubscribeType while off...
695 * off(event:'dataChange', observer: Callback<ChangeNotification>): void;
696 */
OffDataChange(napi_env env,size_t argc,napi_value * argv,std::shared_ptr<ContextBase> ctxt)697 void JsSingleKVStore::OffDataChange(napi_env env, size_t argc, napi_value* argv, std::shared_ptr<ContextBase> ctxt)
698 {
699 // required 1 arguments :: [callback]
700 ASSERT_BUSINESS_ERR(ctxt, argc <= 1, Status::INVALID_ARGUMENT,
701 "Parameter error:Mandatory parameters are left unspecified");
702 // have 1 arguments :: have the callback
703 if (argc == 1) {
704 napi_valuetype valueType = napi_undefined;
705 ctxt->status = napi_typeof(env, argv[0], &valueType);
706 ASSERT_BUSINESS_ERR(ctxt, (ctxt->status == napi_ok) && (valueType == napi_function), Status::INVALID_ARGUMENT,
707 "Parameter error:parameter Callback must be function");
708 }
709
710 ZLOGI("unsubscribe dataChange, %{public}s specified observer.", (argc == 0) ? "without": "with");
711
712 auto proxy = reinterpret_cast<JsSingleKVStore*>(ctxt->native);
713 bool found = false;
714 Status status = Status::SUCCESS;
715 auto traverseType = [argc, argv, proxy, env, &found, &status](uint8_t type, auto& observers) {
716 auto it = observers.begin();
717 while (it != observers.end()) {
718 if ((argc == 1) && !JSUtil::Equals(env, argv[0], (*it)->GetCallback())) {
719 ++it;
720 continue; // specified observer and not current iterator
721 }
722 found = true;
723 status = proxy->UnSubscribe(type, *it);
724 if (status != Status::SUCCESS) {
725 break; // stop on fail.
726 }
727 it = observers.erase(it);
728 }
729 };
730
731 std::lock_guard<std::mutex> lck(proxy->listMutex_);
732 for (uint8_t type = SUBSCRIBE_LOCAL; type < SUBSCRIBE_COUNT; type++) {
733 traverseType(type, proxy->dataObserver_[type]);
734 if (status != Status::SUCCESS) {
735 break; // stop on fail.
736 }
737 }
738 ASSERT_BUSINESS_ERR(ctxt, found || (argc == 0), Status::INVALID_ARGUMENT, "not Subscribed!");
739 ThrowNapiError(env, status, "", false);
740 }
741
742 /*
743 * [JS API Prototype] JsSingleKVStore::OnSyncComplete is private non-static.
744 * [Callback]
745 * on(event:'syncComplete',syncCallback: Callback<Array<[string, number]>>):void;
746 */
OnSyncComplete(napi_env env,size_t argc,napi_value * argv,std::shared_ptr<ContextBase> ctxt)747 void JsSingleKVStore::OnSyncComplete(napi_env env, size_t argc, napi_value* argv, std::shared_ptr<ContextBase> ctxt)
748 {
749 // required 1 arguments :: <callback>
750 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
751 "Parameter error:Mandatory parameters are left unspecified");
752 napi_valuetype valueType = napi_undefined;
753 ctxt->status = napi_typeof(env, argv[0], &valueType);
754 ASSERT_BUSINESS_ERR(ctxt, (ctxt->status == napi_ok) && (valueType == napi_function), Status::INVALID_ARGUMENT,
755 "Parameter error:params valueType must be function");
756
757 auto proxy = reinterpret_cast<JsSingleKVStore*>(ctxt->native);
758 ctxt->status = proxy->RegisterSyncCallback(std::make_shared<SyncObserver>(proxy->uvQueue_, argv[0]));
759 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
760 "Parameter error:RegisterSyncCallback params must be function");
761 }
762
763 /*
764 * [JS API Prototype] JsSingleKVStore::OffSyncComplete is private non-static.
765 * [Callback]
766 * off(event:'syncComplete',syncCallback: Callback<Array<[string, number]>>):void;
767 */
OffSyncComplete(napi_env env,size_t argc,napi_value * argv,std::shared_ptr<ContextBase> ctxt)768 void JsSingleKVStore::OffSyncComplete(napi_env env, size_t argc, napi_value* argv, std::shared_ptr<ContextBase> ctxt)
769 {
770 // required 1 arguments :: [callback]
771 auto proxy = reinterpret_cast<JsSingleKVStore*>(ctxt->native);
772 // have 1 arguments :: have the callback
773 if (argc == 1) {
774 napi_valuetype valueType = napi_undefined;
775 ctxt->status = napi_typeof(env, argv[0], &valueType);
776 ASSERT_BUSINESS_ERR(ctxt, (ctxt->status == napi_ok) && (valueType == napi_function), Status::INVALID_ARGUMENT,
777 "Parameter error:parameter types must be function");
778 std::lock_guard<std::mutex> lck(proxy->listMutex_);
779 auto it = proxy->syncObservers_.begin();
780 while (it != proxy->syncObservers_.end()) {
781 if (JSUtil::Equals(env, argv[0], (*it)->GetCallback())) {
782 (*it)->Clear();
783 proxy->syncObservers_.erase(it);
784 break;
785 }
786 }
787 ctxt->status = napi_ok;
788 }
789 ZLOGI("unsubscribe syncComplete, %{public}s specified observer.", (argc == 0) ? "without": "with");
790 if (argc == 0 || proxy->syncObservers_.empty()) {
791 ctxt->status = proxy->UnRegisterSyncCallback();
792 }
793 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
794 "Parameter error:params type must be function");
795 }
796
797 /*
798 * [Internal private non-static]
799 */
RegisterSyncCallback(std::shared_ptr<SyncObserver> callback)800 napi_status JsSingleKVStore::RegisterSyncCallback(std::shared_ptr<SyncObserver> callback)
801 {
802 Status status = kvStore_->RegisterSyncCallback(callback);
803 if (status != Status::SUCCESS) {
804 callback->Clear();
805 return napi_generic_failure;
806 }
807 std::lock_guard<std::mutex> lck(listMutex_);
808 syncObservers_.push_back(callback);
809 return napi_ok;
810 }
811
UnRegisterSyncCallback()812 napi_status JsSingleKVStore::UnRegisterSyncCallback()
813 {
814 Status status = kvStore_->UnRegisterSyncCallback();
815 if (status != Status::SUCCESS) {
816 return napi_generic_failure;
817 }
818 std::lock_guard<std::mutex> lck(listMutex_);
819 for (auto &syncObserver : syncObservers_) {
820 syncObserver->Clear();
821 }
822 syncObservers_.clear();
823 return napi_ok;
824 }
825
Subscribe(uint8_t type,std::shared_ptr<DataObserver> observer)826 Status JsSingleKVStore::Subscribe(uint8_t type, std::shared_ptr<DataObserver> observer)
827 {
828 auto subscribeType = ToSubscribeType(type);
829 Status status = kvStore_->SubscribeKvStore(subscribeType, observer);
830 ZLOGD("kvStore_->SubscribeKvStore(%{public}d) return %{public}d", type, status);
831 if (status != Status::SUCCESS) {
832 observer->Clear();
833 return status;
834 }
835 dataObserver_[type].push_back(observer);
836 return status;
837 }
838
UnSubscribe(uint8_t type,std::shared_ptr<DataObserver> observer)839 Status JsSingleKVStore::UnSubscribe(uint8_t type, std::shared_ptr<DataObserver> observer)
840 {
841 auto subscribeType = ToSubscribeType(type);
842 Status status = kvStore_->UnSubscribeKvStore(subscribeType, observer);
843 ZLOGD("kvStore_->UnSubscribeKvStore(%{public}d) return %{public}d", type, status);
844 if (status == Status::SUCCESS) {
845 observer->Clear();
846 return status;
847 }
848 return status;
849 }
850
OnChange(const ChangeNotification & notification)851 void JsSingleKVStore::DataObserver::OnChange(const ChangeNotification& notification)
852 {
853 ZLOGD("data change insert:%{public}zu, update:%{public}zu, delete:%{public}zu",
854 notification.GetInsertEntries().size(), notification.GetUpdateEntries().size(),
855 notification.GetDeleteEntries().size());
856 KvStoreObserver::OnChange(notification);
857
858 auto args = [notification, isSchema = isSchema_](napi_env env, int& argc, napi_value* argv) {
859 // generate 1 arguments for callback function.
860 argc = 1;
861 JSUtil::SetValue(env, notification, argv[0], isSchema);
862 };
863 AsyncCall(args);
864 }
865
SyncCompleted(const std::map<std::string,DistributedKv::Status> & results)866 void JsSingleKVStore::SyncObserver::SyncCompleted(const std::map<std::string, DistributedKv::Status>& results)
867 {
868 auto args = [results](napi_env env, int& argc, napi_value* argv) {
869 // generate 1 arguments for callback function.
870 argc = 1;
871 JSUtil::SetValue(env, results, argv[0]);
872 };
873 AsyncCall(args);
874 }
875
876 /*
877 * [JS API Prototype]
878 * [AsyncCallback]
879 * get(key:string, callback:AsyncCallback<boolean|string|number|Uint8Array>):void;
880 * [Promise]
881 * get(key:string):Promise<boolean|string|number|Uint8Array>;
882 */
Get(napi_env env,napi_callback_info info)883 napi_value JsSingleKVStore::Get(napi_env env, napi_callback_info info)
884 {
885 struct GetContext : public ContextBase {
886 std::string key;
887 JSUtil::KvStoreVariant value;
888 };
889 auto ctxt = std::make_shared<GetContext>();
890 auto input = [env, ctxt](size_t argc, napi_value* argv) {
891 // required 1 arguments :: <key>
892 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
893 "Parameter error:Mandatory parameters are left unspecified");
894 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->key);
895 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
896 "Parameter error:params key must be string and not allow empty");
897 };
898 ctxt->GetCbInfo(env, info, input);
899 ASSERT_NULL(!ctxt->isThrowError, "Get exit");
900
901 ZLOGD("key=%{public}.8s", ctxt->key.c_str());
902 auto execute = [env, ctxt]() {
903 OHOS::DistributedKv::Key key(ctxt->key);
904 OHOS::DistributedKv::Value value;
905 auto kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->GetKvStorePtr();
906 bool isSchemaStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->IsSchemaStore();
907 Status status = kvStore->Get(key, value);
908 ZLOGD("kvStore->Get return %{public}d", status);
909 ctxt->value = isSchemaStore ? value.ToString() : JSUtil::Blob2VariantValue(value);
910 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
911 napi_ok : napi_generic_failure;
912 };
913 auto output = [env, ctxt](napi_value& result) {
914 ctxt->status = JSUtil::SetValue(env, ctxt->value, result);
915 ASSERT_STATUS(ctxt, "output failed");
916 };
917 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
918 }
919
920 struct VariantArgs {
921 DataQuery dataQuery;
922 std::string errMsg = "";
923 };
924
GetVariantArgs(napi_env env,size_t argc,napi_value * argv,VariantArgs & va)925 static JSUtil::StatusMsg GetVariantArgs(napi_env env, size_t argc, napi_value* argv, VariantArgs& va)
926 {
927 // required 1 arguments :: <keyPrefix/query>
928 napi_valuetype type = napi_undefined;
929 JSUtil::StatusMsg statusMsg = napi_typeof(env, argv[0], &type);
930 if (statusMsg != napi_ok || (type != napi_string && type != napi_object)) {
931 va.errMsg = "Parameter error:parameters keyPrefix/query must be string or object";
932 return statusMsg.status != napi_ok ? statusMsg.status : napi_invalid_arg;
933 }
934 if (type == napi_string) {
935 std::string keyPrefix;
936 JSUtil::GetValue(env, argv[0], keyPrefix);
937 if (keyPrefix.empty()) {
938 va.errMsg = "Parameter error:parameters keyPrefix must be string";
939 return napi_invalid_arg;
940 }
941 va.dataQuery.KeyPrefix(keyPrefix);
942 } else if (type == napi_object) {
943 bool result = false;
944 statusMsg = napi_instanceof(env, argv[0], JsQuery::Constructor(env), &result);
945 if ((statusMsg == napi_ok) && (result != false)) {
946 JsQuery *jsQuery = nullptr;
947 statusMsg = JSUtil::Unwrap(env, argv[0], reinterpret_cast<void **>(&jsQuery), JsQuery::Constructor(env));
948 if (jsQuery == nullptr) {
949 va.errMsg = "Parameter error:parameters query is must be object";
950 return napi_invalid_arg;
951 }
952 va.dataQuery = jsQuery->GetDataQuery();
953 } else {
954 statusMsg = JSUtil::GetValue(env, argv[0], va.dataQuery);
955 ZLOGD("kvStoreDataShare->GetResultSet return %{public}d", statusMsg.status);
956 statusMsg.jsApiType = JSUtil::DATASHARE;
957 }
958 }
959 return statusMsg;
960 };
961
962 /*
963 * [JS API Prototype]
964 * getEntries(keyPrefix:string, callback:AsyncCallback<Entry[]>):void
965 * getEntries(keyPrefix:string):Promise<Entry[]>
966 *
967 * getEntries(query:Query, callback:AsyncCallback<Entry[]>):void
968 * getEntries(query:Query) : Promise<Entry[]>
969 */
GetEntries(napi_env env,napi_callback_info info)970 napi_value JsSingleKVStore::GetEntries(napi_env env, napi_callback_info info)
971 {
972 struct GetEntriesContext : public ContextBase {
973 VariantArgs va;
974 std::vector<Entry> entries;
975 };
976 auto ctxt = std::make_shared<GetEntriesContext>();
977 auto input = [env, ctxt](size_t argc, napi_value* argv) {
978 // required 1 arguments :: <keyPrefix/query>
979 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
980 "Parameter error:Mandatory parameters are left unspecified");
981 ctxt->status = GetVariantArgs(env, argc, argv, ctxt->va);
982 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, ctxt->va.errMsg);
983 };
984 ctxt->GetCbInfo(env, info, input);
985 ASSERT_NULL(!ctxt->isThrowError, "GetEntries exit");
986
987 auto execute = [ctxt]() {
988 auto kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->GetKvStorePtr();
989 Status status = kvStore->GetEntries(ctxt->va.dataQuery, ctxt->entries);
990 ZLOGD("kvStore->GetEntries() return %{public}d", status);
991 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
992 napi_ok : napi_generic_failure;
993 };
994 auto output = [env, ctxt](napi_value& result) {
995 auto isSchemaStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->IsSchemaStore();
996 ctxt->status = JSUtil::SetValue(env, ctxt->entries, result, isSchemaStore);
997 ASSERT_STATUS(ctxt, "output failed!");
998 };
999 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
1000 }
1001
1002 /*
1003 * [JS API Prototype]
1004 * getResultSet(keyPrefix:string, callback:AsyncCallback<KvStoreResultSet>):void
1005 * getResultSet(keyPrefix:string):Promise<KvStoreResultSet>
1006 *
1007 * getResultSet(query:Query, callback:AsyncCallback<KvStoreResultSet>):void
1008 * getResultSet(query:Query):Promise<KvStoreResultSet>
1009 */
GetResultSet(napi_env env,napi_callback_info info)1010 napi_value JsSingleKVStore::GetResultSet(napi_env env, napi_callback_info info)
1011 {
1012 struct GetResultSetContext : public ContextBase {
1013 VariantArgs va;
1014 JsKVStoreResultSet* resultSet = nullptr;
1015 napi_ref ref = nullptr;
1016 };
1017 auto ctxt = std::make_shared<GetResultSetContext>();
1018 auto input = [env, ctxt](size_t argc, napi_value* argv) {
1019 // required 1 arguments :: <keyPrefix/query>
1020 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
1021 "Parameter error:Mandatory parameters are left unspecified");
1022 JSUtil::StatusMsg statusMsg = GetVariantArgs(env, argc, argv, ctxt->va);
1023 ctxt->status = statusMsg.status;
1024 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT, ctxt->va.errMsg);
1025 ASSERT_PERMISSION_ERR(ctxt,
1026 !JSUtil::IsSystemApi(statusMsg.jsApiType) ||
1027 reinterpret_cast<JsSingleKVStore *>(ctxt->native)->IsSystemApp(), Status::PERMISSION_DENIED, "");
1028 ctxt->ref = JSUtil::NewWithRef(env, 0, nullptr, reinterpret_cast<void**>(&ctxt->resultSet),
1029 JsKVStoreResultSet::Constructor(env));
1030 ASSERT_BUSINESS_ERR(ctxt, ctxt->resultSet != nullptr, Status::INVALID_ARGUMENT,
1031 "Parameter error:resultSet nullptr");
1032 };
1033 ctxt->GetCbInfo(env, info, input);
1034 ASSERT_NULL(!ctxt->isThrowError, "GetResultSet exit");
1035
1036 auto execute = [ctxt]() {
1037 std::shared_ptr<KvStoreResultSet> kvResultSet;
1038 auto kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->GetKvStorePtr();
1039 Status status = kvStore->GetResultSet(ctxt->va.dataQuery, kvResultSet);
1040 ZLOGD("kvStore->GetResultSet() return %{public}d", status);
1041
1042 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
1043 napi_ok : napi_generic_failure;
1044 ctxt->resultSet->SetInstance(kvResultSet);
1045 bool isSchema = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->IsSchemaStore();
1046 ctxt->resultSet->SetSchema(isSchema);
1047 };
1048 auto output = [env, ctxt](napi_value& result) {
1049 ctxt->status = napi_get_reference_value(env, ctxt->ref, &result);
1050 napi_delete_reference(env, ctxt->ref);
1051 ASSERT_STATUS(ctxt, "output kvResultSet failed");
1052 };
1053 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
1054 }
1055
1056 /*
1057 * [JS API Prototype]
1058 * closeResultSet(resultSet:KVStoreResultSet, callback: AsyncCallback<void>):void
1059 * closeResultSet(resultSet:KVStoreResultSet):Promise<void>
1060 */
CloseResultSet(napi_env env,napi_callback_info info)1061 napi_value JsSingleKVStore::CloseResultSet(napi_env env, napi_callback_info info)
1062 {
1063 struct CloseResultSetContext : public ContextBase {
1064 JsKVStoreResultSet* resultSet = nullptr;
1065 };
1066 auto ctxt = std::make_shared<CloseResultSetContext>();
1067 auto input = [env, ctxt](size_t argc, napi_value* argv) {
1068 // required 1 arguments :: <resultSet>
1069 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
1070 "Parameter error:Mandatory parameters are left unspecified");
1071 napi_valuetype type = napi_undefined;
1072 ctxt->status = napi_typeof(env, argv[0], &type);
1073 ASSERT_BUSINESS_ERR(ctxt, type == napi_object, Status::INVALID_ARGUMENT,
1074 "Parameter error:Parameters type must be object");
1075 ctxt->status = JSUtil::Unwrap(env, argv[0], reinterpret_cast<void**>(&ctxt->resultSet),
1076 JsKVStoreResultSet::Constructor(env));
1077 ASSERT_BUSINESS_ERR(ctxt, ctxt->resultSet != nullptr, Status::INVALID_ARGUMENT,
1078 "Parameter error:resultSet nullptr");
1079 };
1080 ctxt->GetCbInfo(env, info, input);
1081 ASSERT_NULL(!ctxt->isThrowError, "CloseResultSet exit");
1082
1083 auto execute = [ctxt]() {
1084 auto kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->GetKvStorePtr();
1085 auto resultSet = ctxt->resultSet->GetInstance();
1086 ctxt->resultSet->SetInstance(nullptr);
1087 Status status = kvStore->CloseResultSet(resultSet);
1088 ZLOGD("kvStore->CloseResultSet return %{public}d", status);
1089 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
1090 napi_ok : napi_generic_failure;
1091 };
1092 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
1093 }
1094
1095 /*
1096 * [JS API Prototype]
1097 * getResultSize(query:Query, callback: AsyncCallback<number>):void
1098 * getResultSize(query:Query):Promise<number>
1099 */
GetResultSize(napi_env env,napi_callback_info info)1100 napi_value JsSingleKVStore::GetResultSize(napi_env env, napi_callback_info info)
1101 {
1102 struct ResultSizeContext : public ContextBase {
1103 JsQuery* query = nullptr;
1104 int resultSize = 0;
1105 };
1106 auto ctxt = std::make_shared<ResultSizeContext>();
1107 auto input = [env, ctxt](size_t argc, napi_value* argv) {
1108 // required 1 arguments :: <query>
1109 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
1110 "Parameter error:Mandatory parameters are left unspecified");
1111 napi_valuetype type = napi_undefined;
1112 ctxt->status = napi_typeof(env, argv[0], &type);
1113 ASSERT_BUSINESS_ERR(ctxt, type == napi_object, Status::INVALID_ARGUMENT,
1114 "Parameter error:Parameters type must be object");
1115 ctxt->status = JSUtil::Unwrap(env, argv[0], reinterpret_cast<void**>(&ctxt->query), JsQuery::Constructor(env));
1116 ASSERT_BUSINESS_ERR(ctxt, ctxt->query != nullptr, Status::INVALID_ARGUMENT,
1117 "Parameter error:query nullptr");
1118 };
1119 ctxt->GetCbInfo(env, info, input);
1120 ASSERT_NULL(!ctxt->isThrowError, "GetResultSize exit");
1121
1122 auto execute = [ctxt]() {
1123 auto kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->GetKvStorePtr();
1124 auto query = ctxt->query->GetDataQuery();
1125 Status status = kvStore->GetCount(query, ctxt->resultSize);
1126 ZLOGD("kvStore->GetCount() return %{public}d", status);
1127 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
1128 napi_ok : napi_generic_failure;
1129 };
1130 auto output = [env, ctxt](napi_value& result) {
1131 ctxt->status = JSUtil::SetValue(env, static_cast<int32_t>(ctxt->resultSize), result);
1132 ASSERT_STATUS(ctxt, "output resultSize failed!");
1133 };
1134 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
1135 }
1136
1137 /*
1138 * [JS API Prototype]
1139 * removeDeviceData(deviceId:string, callback: AsyncCallback<void>):void
1140 * removeDeviceData(deviceId:string):Promise<void>
1141 */
RemoveDeviceData(napi_env env,napi_callback_info info)1142 napi_value JsSingleKVStore::RemoveDeviceData(napi_env env, napi_callback_info info)
1143 {
1144 struct RemoveDeviceContext : public ContextBase {
1145 std::string deviceId;
1146 };
1147 auto ctxt = std::make_shared<RemoveDeviceContext>();
1148 auto input = [env, ctxt](size_t argc, napi_value* argv) {
1149 // required 1 arguments :: <deviceId>
1150 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
1151 "Parameter error:Mandatory parameters are left unspecified");
1152 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->deviceId);
1153 ASSERT_BUSINESS_ERR(ctxt, (!ctxt->deviceId.empty()) && (ctxt->status == napi_ok), Status::INVALID_ARGUMENT,
1154 "Parameter error:deviceId empty");
1155 };
1156 ctxt->GetCbInfo(env, info, input);
1157 ASSERT_NULL(!ctxt->isThrowError, "RemoveDeviceData exit");
1158
1159 auto execute = [ctxt]() {
1160 auto kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->GetKvStorePtr();
1161 Status status = kvStore->RemoveDeviceData(ctxt->deviceId);
1162 ZLOGD("kvStore->RemoveDeviceData return %{public}d", status);
1163 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
1164 napi_ok : napi_generic_failure;
1165 };
1166 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
1167 }
1168
1169 struct SyncContext : public ContextBase {
1170 std::vector<std::string> deviceIdList;
1171 uint32_t mode = 0;
1172 uint32_t allowedDelayMs = 0;
1173 JsQuery* query = nullptr;
1174 napi_valuetype type = napi_undefined;
1175
GetInputOHOS::DistributedKVStore::SyncContext1176 void GetInput(napi_env env, napi_callback_info info)
1177 {
1178 auto input = [env, this](size_t argc, napi_value* argv) {
1179 // required 3 arguments :: <deviceIdList> <mode> [allowedDelayMs]
1180 ASSERT_BUSINESS_ERR(this, argc >= 2, Status::INVALID_ARGUMENT,
1181 "Parameter error:Mandatory parameters are left unspecified");
1182 this->status = JSUtil::GetValue(env, argv[0], this->deviceIdList);
1183 ASSERT_BUSINESS_ERR(this, this->status == napi_ok, Status::INVALID_ARGUMENT,
1184 "Parameter error:params deviceIdList must be array");
1185 napi_typeof(env, argv[1], &this->type);
1186 if (this->type == napi_object) {
1187 this->status = JSUtil::Unwrap(env,
1188 argv[1], reinterpret_cast<void**>(&this->query), JsQuery::Constructor(env));
1189 ASSERT_BUSINESS_ERR(this, this->status == napi_ok, Status::INVALID_ARGUMENT,
1190 "Parameter error:params type must be query");
1191 this->status = JSUtil::GetValue(env, argv[2], this->mode);
1192 ASSERT_BUSINESS_ERR(this, this->status == napi_ok, Status::INVALID_ARGUMENT,
1193 "Parameter error:params mode must be int");
1194 if (argc == 4) {
1195 this->status = JSUtil::GetValue(env, argv[3], this->allowedDelayMs);
1196 ASSERT_BUSINESS_ERR(this, (this->status == napi_ok || JSUtil::IsNull(env, argv[3])),
1197 Status::INVALID_ARGUMENT, "Parameter error:params delay must be int");
1198 this->status = napi_ok;
1199 }
1200 }
1201 if (this->type == napi_number) {
1202 this->status = JSUtil::GetValue(env, argv[1], this->mode);
1203 ASSERT_BUSINESS_ERR(this, this->status == napi_ok, Status::INVALID_ARGUMENT,
1204 "Parameter error:params mode must be int");
1205 if (argc == 3) {
1206 this->status = JSUtil::GetValue(env, argv[2], this->allowedDelayMs);
1207 ASSERT_BUSINESS_ERR(this, (this->status == napi_ok || JSUtil::IsNull(env, argv[2])),
1208 Status::INVALID_ARGUMENT, "Parameter error:params delay must be int");
1209 this->status = napi_ok;
1210 }
1211 }
1212 ASSERT_BUSINESS_ERR(this, (this->mode <= uint32_t(SyncMode::PUSH_PULL)) && (this->status == napi_ok),
1213 Status::INVALID_ARGUMENT, "Parameter error:Parameters mode must be int");
1214 };
1215 ContextBase::GetCbInfoSync(env, info, input);
1216 }
1217 };
1218 /*
1219 * [JS API Prototype]
1220 * sync(deviceIdList:string[], mode:SyncMode, allowedDelayMs?:number):void
1221 */
Sync(napi_env env,napi_callback_info info)1222 napi_value JsSingleKVStore::Sync(napi_env env, napi_callback_info info)
1223 {
1224 auto ctxt = std::make_shared<SyncContext>();
1225 ctxt->GetInput(env, info);
1226 ASSERT_NULL(!ctxt->isThrowError, "Sync exit");
1227
1228 ZLOGD("sync deviceIdList.size=%{public}d, mode:%{public}u, allowedDelayMs:%{public}u",
1229 (int)ctxt->deviceIdList.size(), ctxt->mode, ctxt->allowedDelayMs);
1230
1231 auto kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->GetKvStorePtr();
1232 Status status = Status::INVALID_ARGUMENT;
1233 if (ctxt->type == napi_object) {
1234 auto query = ctxt->query->GetDataQuery();
1235 status = kvStore->Sync(ctxt->deviceIdList, static_cast<SyncMode>(ctxt->mode), query,
1236 nullptr, ctxt->allowedDelayMs);
1237 }
1238 if (ctxt->type == napi_number) {
1239 status = kvStore->Sync(ctxt->deviceIdList, static_cast<SyncMode>(ctxt->mode), ctxt->allowedDelayMs);
1240 }
1241 ZLOGD("kvStore->Sync return %{public}d!", status);
1242 ThrowNapiError(env, status, "", false);
1243 return nullptr;
1244 }
1245
1246 /*
1247 * [JS API Prototype]
1248 * setSyncParam(defaultAllowedDelayMs:number, callback: AsyncCallback<number>):void
1249 * setSyncParam(defaultAllowedDelayMs:number):Promise<void>
1250 */
SetSyncParam(napi_env env,napi_callback_info info)1251 napi_value JsSingleKVStore::SetSyncParam(napi_env env, napi_callback_info info)
1252 {
1253 struct SyncParamContext : public ContextBase {
1254 uint32_t allowedDelayMs;
1255 };
1256 auto ctxt = std::make_shared<SyncParamContext>();
1257 auto input = [env, ctxt](size_t argc, napi_value* argv) {
1258 // required 1 arguments :: <allowedDelayMs>
1259 ASSERT_BUSINESS_ERR(ctxt, argc >= 1, Status::INVALID_ARGUMENT,
1260 "Parameter error:Mandatory parameters are left unspecified");
1261 ctxt->status = JSUtil::GetValue(env, argv[0], ctxt->allowedDelayMs);
1262 ASSERT_BUSINESS_ERR(ctxt, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
1263 "Parameter error:Parameters delay must be int");
1264 };
1265 ctxt->GetCbInfo(env, info, input);
1266 ASSERT_NULL(!ctxt->isThrowError, "SetSyncParam exit");
1267
1268 auto execute = [ctxt]() {
1269 auto kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->GetKvStorePtr();
1270 KvSyncParam syncParam { ctxt->allowedDelayMs };
1271 Status status = kvStore->SetSyncParam(syncParam);
1272 ZLOGD("kvStore->SetSyncParam return %{public}d", status);
1273 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
1274 napi_ok : napi_generic_failure;
1275 };
1276 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute);
1277 }
1278
1279 /*
1280 * [JS API Prototype]
1281 * getSecurityLevel(callback: AsyncCallback<SecurityLevel>):void
1282 * getSecurityLevel():Promise<SecurityLevel>
1283 */
GetSecurityLevel(napi_env env,napi_callback_info info)1284 napi_value JsSingleKVStore::GetSecurityLevel(napi_env env, napi_callback_info info)
1285 {
1286 struct SecurityLevelContext : public ContextBase {
1287 SecurityLevel securityLevel;
1288 };
1289 auto ctxt = std::make_shared<SecurityLevelContext>();
1290 ctxt->GetCbInfo(env, info);
1291
1292 auto execute = [ctxt]() {
1293 auto kvStore = reinterpret_cast<JsSingleKVStore*>(ctxt->native)->GetKvStorePtr();
1294 Status status = kvStore->GetSecurityLevel(ctxt->securityLevel);
1295 ZLOGD("kvStore->GetSecurityLevel return %{public}d", status);
1296 ctxt->status = (GenerateNapiError(status, ctxt->jsCode, ctxt->error) == Status::SUCCESS) ?
1297 napi_ok : napi_generic_failure;
1298 };
1299 auto output = [env, ctxt](napi_value& result) {
1300 ctxt->status = JSUtil::SetValue(env, static_cast<uint8_t>(ctxt->securityLevel), result);
1301 ASSERT_STATUS(ctxt, "output failed!");
1302 };
1303 return NapiQueue::AsyncWork(env, ctxt, std::string(__FUNCTION__), execute, output);
1304 }
1305
New(napi_env env,napi_callback_info info)1306 napi_value JsSingleKVStore::New(napi_env env, napi_callback_info info)
1307 {
1308 ZLOGD("Constructor single kv store!");
1309 std::string storeId;
1310 auto ctxt = std::make_shared<ContextBase>();
1311 auto input = [env, ctxt, &storeId](size_t argc, napi_value* argv) {
1312 // required 2 arguments :: <storeId> <options>
1313 ASSERT_BUSINESS_ERR(ctxt, argc >= 2, Status::INVALID_ARGUMENT,
1314 "Parameter error:Mandatory parameters are left unspecified");
1315 ctxt->status = JSUtil::GetValue(env, argv[0], storeId);
1316 ASSERT_BUSINESS_ERR(ctxt, (ctxt->status == napi_ok) && !storeId.empty(), Status::INVALID_ARGUMENT,
1317 "Parameter error:Parameters storeId must be string");
1318 };
1319 ctxt->GetCbInfoSync(env, info, input);
1320 ASSERT_NULL(!ctxt->isThrowError, "SingleKVStore new exit");
1321 ASSERT_ERR(env, ctxt->status == napi_ok, Status::INVALID_ARGUMENT,
1322 "Parameter error:get params failed");
1323
1324 JsSingleKVStore* kvStore = new (std::nothrow) JsSingleKVStore(storeId);
1325 ASSERT_ERR(env, kvStore != nullptr, Status::INVALID_ARGUMENT,
1326 "Parameter error:kvStore nullptr");
1327
1328 auto finalize = [](napi_env env, void* data, void* hint) {
1329 ZLOGI("singleKVStore finalize.");
1330 auto* kvStore = reinterpret_cast<JsSingleKVStore*>(data);
1331 ASSERT_VOID(kvStore != nullptr, "kvStore is null!");
1332 delete kvStore;
1333 };
1334 ASSERT_CALL(env, napi_wrap(env, ctxt->self, kvStore, finalize, nullptr, nullptr), kvStore);
1335 return ctxt->self;
1336 }
1337 } // namespace OHOS::DistributedKVStore
1338