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