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