@graphscope-neug/linux-x64 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,114 @@
1
+ /** Copyright 2020 Alibaba Group Holding Limited.
2
+ *
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
5
+ * You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software
10
+ * distributed under the License is distributed on an "AS IS" BASIS,
11
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the License for the specific language governing permissions and
13
+ * limitations under the License.
14
+ */
15
+
16
+ #include "node_connection.h"
17
+
18
+ #include <memory>
19
+ #include <string>
20
+
21
+ #include "neug/execution/common/params_map.h"
22
+ #include "neug/main/neug_db.h"
23
+ #include "neug/utils/exception/exception.h"
24
+ #include "neug/utils/pb_utils.h"
25
+ #include "neug/utils/yaml_utils.h"
26
+ #include "node_query_request.h"
27
+
28
+ #include <rapidjson/document.h>
29
+
30
+ namespace neug {
31
+
32
+ Napi::FunctionReference NodeConnection::constructor;
33
+
34
+ Napi::Object NodeConnection::Init(Napi::Env env, Napi::Object exports) {
35
+ Napi::Function func = DefineClass(
36
+ env, "NodeConnection",
37
+ {
38
+ InstanceMethod("execute", &NodeConnection::Execute),
39
+ InstanceMethod("getSchema", &NodeConnection::GetSchema),
40
+ InstanceMethod("close", &NodeConnection::Close),
41
+ });
42
+ constructor = Napi::Persistent(func);
43
+ constructor.SuppressDestruct();
44
+ exports.Set("NodeConnection", func);
45
+ return exports;
46
+ }
47
+
48
+ NodeConnection::NodeConnection(const Napi::CallbackInfo& info)
49
+ : Napi::ObjectWrap<NodeConnection>(info), db_(nullptr), conn_(nullptr) {}
50
+
51
+ void NodeConnection::SetConnection(NeugDB* db,
52
+ std::shared_ptr<Connection> conn) {
53
+ db_ = db;
54
+ conn_ = std::move(conn);
55
+ if (!conn_) {
56
+ THROW_RUNTIME_ERROR("Connection is null");
57
+ }
58
+ }
59
+
60
+ Napi::Object NodeConnection::NewInstance(Napi::Env env, NeugDB& db,
61
+ std::shared_ptr<Connection> conn) {
62
+ Napi::Object obj = constructor.New({});
63
+ NodeConnection* wrapped = Napi::ObjectWrap<NodeConnection>::Unwrap(obj);
64
+ wrapped->SetConnection(&db, std::move(conn));
65
+ return obj;
66
+ }
67
+
68
+ Napi::Value NodeConnection::Execute(const Napi::CallbackInfo& info) {
69
+ Napi::Env env = info.Env();
70
+
71
+ if (info.Length() < 1 || !info[0].IsString()) {
72
+ Napi::TypeError::New(env, "Query string required")
73
+ .ThrowAsJavaScriptException();
74
+ return env.Null();
75
+ }
76
+
77
+ std::string query_string = info[0].As<Napi::String>().Utf8Value();
78
+ std::string access_mode = "";
79
+ if (info.Length() >= 2 && info[1].IsString()) {
80
+ access_mode = info[1].As<Napi::String>().Utf8Value();
81
+ }
82
+
83
+ // Parse parameters from JavaScript object
84
+ rapidjson::Document params_json;
85
+ if (info.Length() >= 3 && info[2].IsObject()) {
86
+ Napi::Object params_obj = info[2].As<Napi::Object>();
87
+ Napi::Array keys = params_obj.GetPropertyNames();
88
+ for (uint32_t i = 0; i < keys.Length(); ++i) {
89
+ std::string key = keys.Get(i).As<Napi::String>().Utf8Value();
90
+ Napi::Value value = params_obj.Get(key);
91
+ NodeParameterSerializer::SerializeParameter(params_json, key, value);
92
+ }
93
+ }
94
+
95
+ auto query_result = conn_->Query(query_string, access_mode, params_json);
96
+ if (!query_result) {
97
+ return NodeQueryResult::NewInstanceFromStatus(env, query_result.error());
98
+ }
99
+ return NodeQueryResult::NewInstance(env, std::move(query_result.value()));
100
+ }
101
+
102
+ Napi::Value NodeConnection::GetSchema(const Napi::CallbackInfo& info) {
103
+ return Napi::String::New(info.Env(), conn_->GetSchema());
104
+ }
105
+
106
+ Napi::Value NodeConnection::Close(const Napi::CallbackInfo& info) {
107
+ if (conn_) {
108
+ db_->RemoveConnection(conn_);
109
+ conn_.reset();
110
+ }
111
+ return info.Env().Undefined();
112
+ }
113
+
114
+ } // namespace neug
@@ -0,0 +1,55 @@
1
+ /** Copyright 2020 Alibaba Group Holding Limited.
2
+ *
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
5
+ * You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software
10
+ * distributed under the License is distributed on an "AS IS" BASIS,
11
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the License for the specific language governing permissions and
13
+ * limitations under the License.
14
+ */
15
+
16
+ #ifndef TOOLS_NODEJS_BIND_SRC_NODE_CONNECTION_H_
17
+ #define TOOLS_NODEJS_BIND_SRC_NODE_CONNECTION_H_
18
+
19
+ #include <napi.h>
20
+
21
+ #include <memory>
22
+ #include <string>
23
+
24
+ #include "neug/execution/common/types/value.h"
25
+ #include "neug/main/connection.h"
26
+ #include "neug/main/neug_db.h"
27
+ #include "node_query_result.h"
28
+
29
+ namespace neug {
30
+
31
+ class NodeConnection : public Napi::ObjectWrap<NodeConnection> {
32
+ public:
33
+ static Napi::Object Init(Napi::Env env, Napi::Object exports);
34
+ static Napi::Object NewInstance(Napi::Env env, NeugDB& db,
35
+ std::shared_ptr<Connection> conn);
36
+
37
+ NodeConnection(const Napi::CallbackInfo& info);
38
+ ~NodeConnection() = default;
39
+
40
+ void SetConnection(NeugDB* db, std::shared_ptr<Connection> conn);
41
+
42
+ private:
43
+ static Napi::FunctionReference constructor;
44
+
45
+ Napi::Value Execute(const Napi::CallbackInfo& info);
46
+ Napi::Value GetSchema(const Napi::CallbackInfo& info);
47
+ Napi::Value Close(const Napi::CallbackInfo& info);
48
+
49
+ NeugDB* db_{nullptr};
50
+ std::shared_ptr<Connection> conn_;
51
+ };
52
+
53
+ } // namespace neug
54
+
55
+ #endif // TOOLS_NODEJS_BIND_SRC_NODE_CONNECTION_H_
@@ -0,0 +1,254 @@
1
+ /** Copyright 2020 Alibaba Group Holding Limited.
2
+ *
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
5
+ * You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software
10
+ * distributed under the License is distributed on an "AS IS" BASIS,
11
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the License for the specific language governing permissions and
13
+ * limitations under the License.
14
+ */
15
+
16
+ #include "node_database.h"
17
+
18
+ #include <string>
19
+
20
+ #include "neug/config.h"
21
+ #include "neug/utils/exception/exception.h"
22
+
23
+ namespace neug {
24
+
25
+ Napi::FunctionReference NodeDatabase::constructor;
26
+
27
+ Napi::Object NodeDatabase::Init(Napi::Env env, Napi::Object exports) {
28
+ Napi::Function func = DefineClass(
29
+ env, "NodeDatabase",
30
+ {
31
+ InstanceMethod("connect", &NodeDatabase::Connect),
32
+ InstanceMethod("close", &NodeDatabase::Close),
33
+ InstanceMethod("serve", &NodeDatabase::Serve),
34
+ InstanceMethod("stopServing", &NodeDatabase::StopServing),
35
+ });
36
+ constructor = Napi::Persistent(func);
37
+ constructor.SuppressDestruct();
38
+ exports.Set("NodeDatabase", func);
39
+ return exports;
40
+ }
41
+
42
+ NodeDatabase::NodeDatabase(const Napi::CallbackInfo& info)
43
+ : Napi::ObjectWrap<NodeDatabase>(info) {
44
+ Napi::Env env = info.Env();
45
+
46
+ if (info.Length() < 1 || !info[0].IsObject()) {
47
+ Napi::TypeError::New(env, "Options object required")
48
+ .ThrowAsJavaScriptException();
49
+ return;
50
+ }
51
+
52
+ Napi::Object opts = info[0].As<Napi::Object>();
53
+
54
+ // Parse options
55
+ std::string database_path = "";
56
+ if (opts.Has("databasePath") && opts.Get("databasePath").IsString()) {
57
+ database_path = opts.Get("databasePath").As<Napi::String>().Utf8Value();
58
+ }
59
+
60
+ int32_t max_thread_num = 0;
61
+ if (opts.Has("maxThreadNum") && opts.Get("maxThreadNum").IsNumber()) {
62
+ max_thread_num = opts.Get("maxThreadNum").As<Napi::Number>().Int32Value();
63
+ }
64
+
65
+ std::string mode = "r";
66
+ if (opts.Has("mode") && opts.Get("mode").IsString()) {
67
+ mode = opts.Get("mode").As<Napi::String>().Utf8Value();
68
+ }
69
+
70
+ std::string planner = "gopt";
71
+ if (opts.Has("planner") && opts.Get("planner").IsString()) {
72
+ planner = opts.Get("planner").As<Napi::String>().Utf8Value();
73
+ }
74
+
75
+ bool checkpoint_on_close = true;
76
+ if (opts.Has("checkpointOnClose") && opts.Get("checkpointOnClose").IsBoolean()) {
77
+ checkpoint_on_close = opts.Get("checkpointOnClose").As<Napi::Boolean>().Value();
78
+ }
79
+
80
+ std::string buffer_strategy = "M_FULL";
81
+ if (opts.Has("bufferStrategy") && opts.Get("bufferStrategy").IsString()) {
82
+ buffer_strategy = opts.Get("bufferStrategy").As<Napi::String>().Utf8Value();
83
+ }
84
+
85
+ // Parse mode
86
+ neug::DBMode mode_;
87
+ if (mode == "read" || mode == "r" || mode == "read-only" ||
88
+ mode == "read_only") {
89
+ mode_ = DBMode::READ_ONLY;
90
+ } else if (mode == "read_write" || mode == "rw" || mode == "w" ||
91
+ mode == "wr" || mode == "write" || mode == "readwrite" ||
92
+ mode == "read-write") {
93
+ mode_ = DBMode::READ_WRITE;
94
+ } else {
95
+ Napi::Error::New(env, "Invalid mode: " + mode)
96
+ .ThrowAsJavaScriptException();
97
+ return;
98
+ }
99
+
100
+ db_dir_ = database_path;
101
+ database = std::make_unique<NeugDB>();
102
+ NeugDBConfig config(db_dir_, max_thread_num);
103
+ config.mode = mode_;
104
+ config.planner_kind = planner;
105
+ config.checkpoint_on_close = checkpoint_on_close;
106
+ try {
107
+ config.memory_level = ParseBufferStrategy(buffer_strategy);
108
+ database->Open(config);
109
+ } catch (const neug::exception::Exception& e) {
110
+ Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
111
+ database.reset();
112
+ return;
113
+ } catch (const std::exception& e) {
114
+ Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
115
+ database.reset();
116
+ return;
117
+ }
118
+ }
119
+
120
+ NodeDatabase::~NodeDatabase() {
121
+ std::lock_guard<std::recursive_mutex> lock(mtx_);
122
+ #ifdef BUILD_HTTP_SERVER
123
+ if (service_) {
124
+ service_->Stop();
125
+ service_.reset();
126
+ }
127
+ #endif
128
+ if (database) {
129
+ database->Close();
130
+ database.reset();
131
+ }
132
+ }
133
+
134
+ Napi::Value NodeDatabase::Connect(const Napi::CallbackInfo& info) {
135
+ Napi::Env env = info.Env();
136
+ if (!database) {
137
+ Napi::Error::New(env, "Database is not initialized.")
138
+ .ThrowAsJavaScriptException();
139
+ return env.Null();
140
+ }
141
+ try {
142
+ auto conn = database->Connect();
143
+ return NodeConnection::NewInstance(env, *database, conn);
144
+ } catch (const neug::exception::Exception& e) {
145
+ Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
146
+ return env.Null();
147
+ } catch (const std::exception& e) {
148
+ Napi::Error::New(env, e.what()).ThrowAsJavaScriptException();
149
+ return env.Null();
150
+ }
151
+ }
152
+
153
+ Napi::Value NodeDatabase::Close(const Napi::CallbackInfo& info) {
154
+ std::lock_guard<std::recursive_mutex> lock(mtx_);
155
+ #ifdef BUILD_HTTP_SERVER
156
+ if (service_) {
157
+ service_->Stop();
158
+ service_.reset();
159
+ }
160
+ #endif
161
+ if (database) {
162
+ database->Close();
163
+ database.reset();
164
+ }
165
+ return info.Env().Undefined();
166
+ }
167
+
168
+ Napi::Value NodeDatabase::Serve(const Napi::CallbackInfo& info) {
169
+ Napi::Env env = info.Env();
170
+ #ifdef BUILD_HTTP_SERVER
171
+ if (!database) {
172
+ Napi::Error::New(env, "Database is not initialized.")
173
+ .ThrowAsJavaScriptException();
174
+ return env.Null();
175
+ }
176
+ if (service_) {
177
+ Napi::Error::New(env, "Server is already running.")
178
+ .ThrowAsJavaScriptException();
179
+ return env.Null();
180
+ }
181
+
182
+ int port = 10000;
183
+ std::string host = "localhost";
184
+ int32_t num_thread = 0;
185
+ bool blocking = false;
186
+
187
+ if (info.Length() >= 1 && info[0].IsNumber()) {
188
+ port = info[0].As<Napi::Number>().Int32Value();
189
+ }
190
+ if (info.Length() >= 2 && info[1].IsString()) {
191
+ host = info[1].As<Napi::String>().Utf8Value();
192
+ }
193
+ if (info.Length() >= 3 && info[2].IsNumber()) {
194
+ num_thread = info[2].As<Napi::Number>().Int32Value();
195
+ }
196
+ if (info.Length() >= 4 && info[3].IsBoolean()) {
197
+ blocking = info[3].As<Napi::Boolean>().Value();
198
+ }
199
+
200
+ std::lock_guard<std::recursive_mutex> lock(mtx_);
201
+ database->Close();
202
+ database->Open(database->config());
203
+
204
+ neug::ServiceConfig config;
205
+ config.query_port = port;
206
+ config.host_str = host;
207
+ config.shard_num =
208
+ (num_thread == 0) ? std::thread::hardware_concurrency() : num_thread;
209
+ #ifdef __APPLE__
210
+ if (host == "localhost") {
211
+ config.host_str = "127.0.0.1";
212
+ }
213
+ #endif
214
+
215
+ service_ = std::make_unique<neug::NeugDBService>(*database, config);
216
+ if (blocking) {
217
+ service_->run_and_wait_for_exit();
218
+ return Napi::String::New(env, "");
219
+ }
220
+ return Napi::String::New(env, service_->Start());
221
+ #else
222
+ Napi::Error::New(env, "HTTP server is not enabled in this build.")
223
+ .ThrowAsJavaScriptException();
224
+ return env.Null();
225
+ #endif
226
+ }
227
+
228
+ Napi::Value NodeDatabase::StopServing(const Napi::CallbackInfo& info) {
229
+ std::lock_guard<std::recursive_mutex> lock(mtx_);
230
+ #ifdef BUILD_HTTP_SERVER
231
+ if (service_) {
232
+ service_->Stop();
233
+ service_.reset();
234
+ }
235
+ #endif
236
+ return info.Env().Undefined();
237
+ }
238
+
239
+ MemoryLevel NodeDatabase::ParseBufferStrategy(const std::string& level) {
240
+ if (level == "InMemory" || level == "inmemory" || level == "in_memory" ||
241
+ level == "M_FULL") {
242
+ return MemoryLevel::kInMemory;
243
+ } else if (level == "SyncToFile" || level == "synctofile" ||
244
+ level == "sync_to_file" || level == "M_LAZY") {
245
+ return MemoryLevel::kSyncToFile;
246
+ } else if (level == "HugePagePreferred" || level == "hugepagepreferred" ||
247
+ level == "huge_page_preferred" || level == "M_HUGE") {
248
+ return MemoryLevel::kHugePagePreferred;
249
+ } else {
250
+ THROW_INVALID_ARGUMENT_EXCEPTION("Invalid memory level: " + level);
251
+ }
252
+ }
253
+
254
+ } // namespace neug
@@ -0,0 +1,60 @@
1
+ /** Copyright 2020 Alibaba Group Holding Limited.
2
+ *
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
5
+ * You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software
10
+ * distributed under the License is distributed on an "AS IS" BASIS,
11
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the License for the specific language governing permissions and
13
+ * limitations under the License.
14
+ */
15
+
16
+ #ifndef TOOLS_NODEJS_BIND_SRC_NODE_DATABASE_H_
17
+ #define TOOLS_NODEJS_BIND_SRC_NODE_DATABASE_H_
18
+
19
+ #include <napi.h>
20
+
21
+ #include <memory>
22
+ #include <mutex>
23
+ #include <string>
24
+
25
+ #include "neug/main/neug_db.h"
26
+ #ifdef BUILD_HTTP_SERVER
27
+ #include "neug/server/neug_db_service.h"
28
+ #endif
29
+ #include "node_connection.h"
30
+
31
+ namespace neug {
32
+
33
+ class NodeDatabase : public Napi::ObjectWrap<NodeDatabase> {
34
+ public:
35
+ static Napi::Object Init(Napi::Env env, Napi::Object exports);
36
+
37
+ NodeDatabase(const Napi::CallbackInfo& info);
38
+ ~NodeDatabase();
39
+
40
+ Napi::Value Connect(const Napi::CallbackInfo& info);
41
+ Napi::Value Close(const Napi::CallbackInfo& info);
42
+ Napi::Value Serve(const Napi::CallbackInfo& info);
43
+ Napi::Value StopServing(const Napi::CallbackInfo& info);
44
+
45
+ private:
46
+ static Napi::FunctionReference constructor;
47
+
48
+ MemoryLevel ParseBufferStrategy(const std::string& level);
49
+
50
+ std::recursive_mutex mtx_;
51
+ std::string db_dir_;
52
+ std::unique_ptr<NeugDB> database;
53
+ #ifdef BUILD_HTTP_SERVER
54
+ std::unique_ptr<NeugDBService> service_;
55
+ #endif
56
+ };
57
+
58
+ } // namespace neug
59
+
60
+ #endif // TOOLS_NODEJS_BIND_SRC_NODE_DATABASE_H_
@@ -0,0 +1,162 @@
1
+ /** Copyright 2020 Alibaba Group Holding Limited.
2
+ *
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
5
+ * You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software
10
+ * distributed under the License is distributed on an "AS IS" BASIS,
11
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the License for the specific language governing permissions and
13
+ * limitations under the License.
14
+ */
15
+
16
+ #include "node_query_request.h"
17
+
18
+ #include <sstream>
19
+ #include <string>
20
+
21
+ #include "neug/execution/common/types/value.h"
22
+ #include "neug/main/query_request.h"
23
+ #include "neug/utils/access_mode.h"
24
+ #include "neug/utils/exception/exception.h"
25
+ #include "neug/utils/property/types.h"
26
+ #include "neug/utils/serialization/in_archive.h"
27
+
28
+ #include <rapidjson/document.h>
29
+ #include <rapidjson/stringbuffer.h>
30
+ #include <rapidjson/writer.h>
31
+
32
+ namespace neug {
33
+
34
+ Napi::FunctionReference NodeQueryRequest::constructor;
35
+
36
+ rapidjson::Document napi_value_to_rapidjson_document(
37
+ const Napi::Value& val, rapidjson::Document::AllocatorType& allocator) {
38
+ rapidjson::Document doc(&allocator);
39
+
40
+ if (val.IsNull() || val.IsUndefined()) {
41
+ doc.SetNull();
42
+ } else if (val.IsBoolean()) {
43
+ doc.SetBool(val.As<Napi::Boolean>().Value());
44
+ } else if (val.IsNumber()) {
45
+ Napi::Number num = val.As<Napi::Number>();
46
+ double d = num.DoubleValue();
47
+ // Check if it's an integer
48
+ if (d == static_cast<double>(static_cast<int64_t>(d))) {
49
+ doc.SetInt64(static_cast<int64_t>(d));
50
+ } else {
51
+ doc.SetDouble(d);
52
+ }
53
+ } else if (val.IsString()) {
54
+ std::string s = val.As<Napi::String>().Utf8Value();
55
+ doc.SetString(s.c_str(), s.length(), allocator);
56
+ } else if (val.IsArray()) {
57
+ Napi::Array arr = val.As<Napi::Array>();
58
+ doc.SetArray();
59
+ for (uint32_t i = 0; i < arr.Length(); ++i) {
60
+ rapidjson::Document element_doc =
61
+ napi_value_to_rapidjson_document(arr.Get(i), allocator);
62
+ doc.PushBack(element_doc, allocator);
63
+ }
64
+ } else if (val.IsDate()) {
65
+ // Convert Date to ISO string
66
+ Napi::Object date_obj = val.As<Napi::Object>();
67
+ Napi::Function to_iso =
68
+ date_obj.Get("toISOString").As<Napi::Function>();
69
+ std::string iso_str =
70
+ to_iso.Call(date_obj, {}).As<Napi::String>().Utf8Value();
71
+ doc.SetString(iso_str.c_str(), iso_str.length(), allocator);
72
+ } else if (val.IsObject()) {
73
+ // Serialize plain object as JSON object
74
+ Napi::Object obj = val.As<Napi::Object>();
75
+ Napi::Array keys = obj.GetPropertyNames();
76
+ doc.SetObject();
77
+ for (uint32_t i = 0; i < keys.Length(); ++i) {
78
+ std::string key = keys.Get(i).As<Napi::String>().Utf8Value();
79
+ rapidjson::Document val_doc =
80
+ napi_value_to_rapidjson_document(obj.Get(key), allocator);
81
+ rapidjson::Value json_key;
82
+ json_key.SetString(key.c_str(), key.length(), allocator);
83
+ doc.AddMember(json_key, val_doc, allocator);
84
+ }
85
+ } else {
86
+ throw std::invalid_argument(
87
+ "Unsupported parameter type for serialization.");
88
+ }
89
+ return doc;
90
+ }
91
+
92
+ void NodeParameterSerializer::SerializeParameter(rapidjson::Document& doc,
93
+ const std::string& key,
94
+ const Napi::Value& parameter) {
95
+ if (doc.IsNull()) {
96
+ doc.SetObject();
97
+ }
98
+ auto& allocator = doc.GetAllocator();
99
+ rapidjson::Value json_key;
100
+ json_key.SetString(key.c_str(), key.length(), allocator);
101
+ rapidjson::Document json_value =
102
+ napi_value_to_rapidjson_document(parameter, allocator);
103
+ doc.AddMember(json_key, json_value, allocator);
104
+ }
105
+
106
+ Napi::Object NodeQueryRequest::Init(Napi::Env env, Napi::Object exports) {
107
+ Napi::Function func = DefineClass(
108
+ env, "NodeQueryRequest",
109
+ {
110
+ StaticMethod("serializeRequest", &NodeQueryRequest::SerializeRequest),
111
+ });
112
+ constructor = Napi::Persistent(func);
113
+ constructor.SuppressDestruct();
114
+ exports.Set("NodeQueryRequest", func);
115
+ return exports;
116
+ }
117
+
118
+ NodeQueryRequest::NodeQueryRequest(const Napi::CallbackInfo& info)
119
+ : Napi::ObjectWrap<NodeQueryRequest>(info) {}
120
+
121
+ Napi::Value NodeQueryRequest::SerializeRequest(const Napi::CallbackInfo& info) {
122
+ Napi::Env env = info.Env();
123
+
124
+ if (info.Length() < 1 || !info[0].IsString()) {
125
+ Napi::TypeError::New(env, "Query string required")
126
+ .ThrowAsJavaScriptException();
127
+ return env.Null();
128
+ }
129
+
130
+ std::string query = info[0].As<Napi::String>().Utf8Value();
131
+ std::string access_mode = "update";
132
+ if (info.Length() >= 2 && info[1].IsString()) {
133
+ access_mode = info[1].As<Napi::String>().Utf8Value();
134
+ }
135
+
136
+ rapidjson::Document req_doc(rapidjson::kObjectType);
137
+ auto& allocator = req_doc.GetAllocator();
138
+ req_doc.AddMember("query", rapidjson::Value(query.c_str(), allocator),
139
+ allocator);
140
+ req_doc.AddMember("access_mode",
141
+ rapidjson::Value(access_mode.c_str(), allocator),
142
+ allocator);
143
+
144
+ rapidjson::Document params_doc;
145
+ if (info.Length() >= 3 && info[2].IsObject()) {
146
+ Napi::Object params_obj = info[2].As<Napi::Object>();
147
+ Napi::Array keys = params_obj.GetPropertyNames();
148
+ for (uint32_t i = 0; i < keys.Length(); ++i) {
149
+ std::string key = keys.Get(i).As<Napi::String>().Utf8Value();
150
+ NodeParameterSerializer::SerializeParameter(params_doc, key,
151
+ params_obj.Get(key));
152
+ }
153
+ }
154
+ req_doc.AddMember("parameters", params_doc, allocator);
155
+
156
+ rapidjson::StringBuffer buffer;
157
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
158
+ req_doc.Accept(writer);
159
+ return Napi::String::New(env, buffer.GetString());
160
+ }
161
+
162
+ } // namespace neug
@@ -0,0 +1,47 @@
1
+ /** Copyright 2020 Alibaba Group Holding Limited.
2
+ *
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
5
+ * You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software
10
+ * distributed under the License is distributed on an "AS IS" BASIS,
11
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the License for the specific language governing permissions and
13
+ * limitations under the License.
14
+ */
15
+
16
+ #pragma once
17
+
18
+ #include <napi.h>
19
+
20
+ #include <string>
21
+
22
+ #include <rapidjson/document.h>
23
+
24
+ namespace neug {
25
+
26
+ /**
27
+ * A helper struct for serializing parameters from NAPI objects to JSON strings.
28
+ */
29
+ struct NodeParameterSerializer {
30
+ static void SerializeParameter(rapidjson::Document& doc,
31
+ const std::string& key,
32
+ const Napi::Value& parameter);
33
+ };
34
+
35
+ class NodeQueryRequest : public Napi::ObjectWrap<NodeQueryRequest> {
36
+ public:
37
+ static Napi::Object Init(Napi::Env env, Napi::Object exports);
38
+
39
+ NodeQueryRequest(const Napi::CallbackInfo& info);
40
+
41
+ private:
42
+ static Napi::FunctionReference constructor;
43
+
44
+ static Napi::Value SerializeRequest(const Napi::CallbackInfo& info);
45
+ };
46
+
47
+ } // namespace neug