windowpp 0.1.1

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.
Files changed (88) hide show
  1. package/bin/windowpp.js +86 -0
  2. package/cmake/embed_assets.py +144 -0
  3. package/framework/CMakeLists.txt +176 -0
  4. package/framework/include/windowpp/windowpp.h +704 -0
  5. package/framework/src/AppData/API/AppData.ts +137 -0
  6. package/framework/src/AppData/appdata_bridge.h +138 -0
  7. package/framework/src/AppData/appdata_manager.cpp +126 -0
  8. package/framework/src/AppData/appdata_manager.h +3 -0
  9. package/framework/src/FileSystem/API/FileSystem.ts +389 -0
  10. package/framework/src/FileSystem/Linux/filesearch.cpp +148 -0
  11. package/framework/src/FileSystem/Linux/readfile.cpp +79 -0
  12. package/framework/src/FileSystem/Linux/savefile.cpp +333 -0
  13. package/framework/src/FileSystem/MacOS/filesearch.cpp +149 -0
  14. package/framework/src/FileSystem/MacOS/readfile.cpp +80 -0
  15. package/framework/src/FileSystem/MacOS/savefile.cpp +264 -0
  16. package/framework/src/FileSystem/Windows/filesearch.cpp +195 -0
  17. package/framework/src/FileSystem/Windows/readfile.cpp +122 -0
  18. package/framework/src/FileSystem/Windows/savefile.cpp +290 -0
  19. package/framework/src/FileSystem/file_index_service.cpp +262 -0
  20. package/framework/src/FileSystem/file_index_service.h +55 -0
  21. package/framework/src/FileSystem/filesystem_bridge.h +243 -0
  22. package/framework/src/FileSystem/filesystem_handler.h +93 -0
  23. package/framework/src/FileSystem/filesystem_json.h +241 -0
  24. package/framework/src/FileSystem/filesystem_search_service.cpp +414 -0
  25. package/framework/src/FileSystem/filesystem_search_service.h +94 -0
  26. package/framework/src/Input/API/Input.ts +161 -0
  27. package/framework/src/Input/Linux/linux_key_utils.h +135 -0
  28. package/framework/src/Input/MacOS/macos_key_utils.h +137 -0
  29. package/framework/src/Input/Windows/win32_key_utils.h +199 -0
  30. package/framework/src/Input/input_bridge.h +192 -0
  31. package/framework/src/Input/input_service.cpp +584 -0
  32. package/framework/src/Input/input_service.h +21 -0
  33. package/framework/src/application.cpp +29 -0
  34. package/framework/src/common/hit_test.cpp +40 -0
  35. package/framework/src/common/image_loader.cpp +24 -0
  36. package/framework/src/common/paths.cpp +75 -0
  37. package/framework/src/filedrop/filedrop.cpp +316 -0
  38. package/framework/src/filedrop/filedrop.css +421 -0
  39. package/framework/src/filedrop/filedrop.hpp +92 -0
  40. package/framework/src/filedrop/filedrop.ts +183 -0
  41. package/framework/src/platform/API/App.ts +156 -0
  42. package/framework/src/platform/API/Window.ts +249 -0
  43. package/framework/src/platform/linux/app_linux.cpp +256 -0
  44. package/framework/src/platform/linux/app_linux.h +64 -0
  45. package/framework/src/platform/linux/linux_helpers.cpp +26 -0
  46. package/framework/src/platform/linux/linux_helpers.h +19 -0
  47. package/framework/src/platform/linux/tray_linux.cpp +21 -0
  48. package/framework/src/platform/linux/tray_linux.h +26 -0
  49. package/framework/src/platform/linux/window_linux.cpp +256 -0
  50. package/framework/src/platform/linux/window_linux.h +70 -0
  51. package/framework/src/platform/macos/app_macos.h +59 -0
  52. package/framework/src/platform/macos/app_macos.mm +223 -0
  53. package/framework/src/platform/macos/macos_helpers.h +21 -0
  54. package/framework/src/platform/macos/tray_macos.h +22 -0
  55. package/framework/src/platform/macos/tray_macos.mm +53 -0
  56. package/framework/src/platform/macos/window_macos.h +74 -0
  57. package/framework/src/platform/macos/window_macos.mm +318 -0
  58. package/framework/src/platform/platform_bridge.h +514 -0
  59. package/framework/src/platform/platform_factory.cpp +33 -0
  60. package/framework/src/platform/platform_factory.h +19 -0
  61. package/framework/src/platform/win32/app_win32.cpp +572 -0
  62. package/framework/src/platform/win32/app_win32.h +83 -0
  63. package/framework/src/platform/win32/tray_win32.cpp +57 -0
  64. package/framework/src/platform/win32/tray_win32.h +30 -0
  65. package/framework/src/platform/win32/win32_helpers.h +61 -0
  66. package/framework/src/platform/win32/window_win32.cpp +267 -0
  67. package/framework/src/platform/win32/window_win32.h +79 -0
  68. package/framework/src/renderer/webgpu.h +128 -0
  69. package/framework/src/renderer/webview/include/WebView2.h +48014 -0
  70. package/framework/src/renderer/webview/include/WebView2EnvironmentOptions.h +342 -0
  71. package/framework/src/renderer/webview/webview.h +13 -0
  72. package/framework/src/renderer/webview/webview_linux.cpp +392 -0
  73. package/framework/src/renderer/webview/webview_macos.mm +388 -0
  74. package/framework/src/renderer/webview/webview_win32.cpp +688 -0
  75. package/framework/src/renderer/webview/x64/WebView2Loader.dll +0 -0
  76. package/framework/src/renderer/webview/x64/WebView2Loader.lib +0 -0
  77. package/framework/src/renderer/webview/x64/WebView2LoaderStatic.lib +0 -0
  78. package/lib/build.js +112 -0
  79. package/lib/create.js +283 -0
  80. package/lib/dev.js +155 -0
  81. package/package.json +24 -0
  82. package/scripts/publish.js +67 -0
  83. package/scripts/sync-framework.js +73 -0
  84. package/templates/solid/CMakeLists.txt +56 -0
  85. package/templates/solid/frontend/package.json +22 -0
  86. package/templates/solid/frontend/vite.config.ts +25 -0
  87. package/templates/solid/main.cpp +72 -0
  88. package/templates/solid/package.json +12 -0
@@ -0,0 +1,243 @@
1
+ // ============================================================================
2
+ // FileSystem/filesystem_bridge.h
3
+ // Wires all fs:* IPC calls from the frontend into the native handlers.
4
+ //
5
+ // Usage — call once per window after creation, inside your window-config
6
+ // on_message callback or wherever you dispatch webview messages:
7
+ //
8
+ // #include "FileSystem/filesystem_bridge.h"
9
+ //
10
+ // // eval_fn executes a JavaScript string in the webview.
11
+ // // On Win32 you can use: webview->ExecuteScript(wide(js));
12
+ // // On macOS / Linux you can use: webview->send_message(js) — the
13
+ // // send_message implementations on those platforms call evaluateJavaScript /
14
+ // // webkit_web_view_run_javascript which eval the string directly.
15
+ // // The simplest one-liner for any platform that has send_message == eval:
16
+ // // auto eval = [wv](const std::string& js){ wv->send_message(js); };
17
+ //
18
+ // wpp::fs::FsBridge bridge([wv](const std::string& js){ wv->send_message(js); });
19
+ //
20
+ // config.webview.on_message = [&bridge](const std::string& raw){
21
+ // bridge.dispatch(raw);
22
+ // };
23
+ //
24
+ // ============================================================================
25
+
26
+ #pragma once
27
+
28
+ #include <functional>
29
+ #include <utility>
30
+ #include <stdexcept>
31
+ #include <string>
32
+
33
+ #include "filesystem_handler.h"
34
+ #include "filesystem_json.h"
35
+ #include "filesystem_search_service.h"
36
+
37
+ namespace wpp::fs {
38
+
39
+ // eval_fn(js) — executes `js` as JavaScript in the target webview.
40
+ using EvalFn = std::function<void(const std::string& js)>;
41
+ using DispatchFn = std::function<void(std::function<void()>)>;
42
+
43
+ class FsBridge {
44
+ public:
45
+ explicit FsBridge(EvalFn eval_fn,
46
+ DispatchFn dispatch_fn = {},
47
+ std::string search_cache_root = {})
48
+ : eval_(std::move(eval_fn)), dispatch_(std::move(dispatch_fn)) {
49
+ if (!search_cache_root.empty()) {
50
+ FileSearchService::instance().configure_cache_root(search_cache_root);
51
+ }
52
+ }
53
+
54
+ // Call this from WebViewConfig::on_message for every incoming message.
55
+ // Non-fs:* messages are silently ignored so multiple bridges can share
56
+ // the same on_message callback.
57
+ void dispatch(const std::string& raw) {
58
+ std::string id, method;
59
+ std::vector<JsonValue> params;
60
+
61
+ // Parse envelope
62
+ try {
63
+ auto env = JsonValue::parse(raw);
64
+ id = env["id"].as_string();
65
+ method = env["method"].as_string();
66
+ params = env["params"].as_array();
67
+ } catch (...) {
68
+ return; // Malformed message — ignore
69
+ }
70
+
71
+ // Only handle fs:* methods
72
+ if (method.size() < 3 || method.compare(0, 3, "fs:") != 0) return;
73
+
74
+ // Helper: send success response — calls window.__response__(id, result)
75
+ auto reply_ok = [this, &id](const std::string& json_result) {
76
+ eval_("window.__response__(" + JsonValue::to_js_argument(id) + "," + json_result + ")");
77
+ };
78
+
79
+ // Helper: send error response
80
+ auto reply_err = [this, &id](const std::string& msg) {
81
+ eval_(
82
+ "window.__response__(" + JsonValue::to_js_argument(id) + ",null," +
83
+ JsonValue::to_js_argument(msg) + ")");
84
+ };
85
+
86
+ auto send_stream_event = [this](const std::string& search_id,
87
+ const std::string& event_name,
88
+ const std::string& json_payload) {
89
+ std::string script = "window.__wpp_fs_stream__ && window.__wpp_fs_stream__(" +
90
+ JsonValue::to_js_argument(search_id) + "," +
91
+ JsonValue::to_js_argument(event_name) + "," +
92
+ json_payload + ")";
93
+ if (dispatch_) {
94
+ dispatch_([eval = eval_, script = std::move(script)]() {
95
+ eval(script);
96
+ });
97
+ } else {
98
+ eval_(script);
99
+ }
100
+ };
101
+
102
+ // ── Dispatch ────────────────────────────────────────────────────────
103
+ try {
104
+ if (method == "fs:readFile") {
105
+ reply_ok(JsonValue::quote(handleReadFile(params[0].as_string())));
106
+
107
+ } else if (method == "fs:readBinaryFile") {
108
+ reply_ok(JsonValue::quote(handleReadBinaryFile(params[0].as_string())));
109
+
110
+ } else if (method == "fs:writeFile") {
111
+ handleWriteFile(params[0].as_string(), params[1].as_string());
112
+ reply_ok("null");
113
+
114
+ } else if (method == "fs:writeBinaryFile") {
115
+ handleWriteBinaryFile(params[0].as_string(), params[1].as_string());
116
+ reply_ok("null");
117
+
118
+ } else if (method == "fs:appendFile") {
119
+ handleAppendFile(params[0].as_string(), params[1].as_string());
120
+ reply_ok("null");
121
+
122
+ } else if (method == "fs:copyFile") {
123
+ handleCopyFile(params[0].as_string(), params[1].as_string());
124
+ reply_ok("null");
125
+
126
+ } else if (method == "fs:moveFile") {
127
+ handleMoveFile(params[0].as_string(), params[1].as_string());
128
+ reply_ok("null");
129
+
130
+ } else if (method == "fs:deleteFile") {
131
+ handleDeleteFile(params[0].as_string());
132
+ reply_ok("null");
133
+
134
+ } else if (method == "fs:exists") {
135
+ reply_ok(handleExists(params[0].as_string()) ? "true" : "false");
136
+
137
+ } else if (method == "fs:stat") {
138
+ reply_ok(statToJson(handleStat(params[0].as_string())));
139
+
140
+ } else if (method == "fs:readDir") {
141
+ reply_ok(dirEntriesToJson(handleReadDir(params[0].as_string())));
142
+
143
+ } else if (method == "fs:listRoots") {
144
+ reply_ok(stringArrayToJson(handleListRoots()));
145
+
146
+ } else if (method == "fs:createDir") {
147
+ bool recursive = params.size() > 1 && params[1].as_bool();
148
+ handleCreateDir(params[0].as_string(), recursive);
149
+ reply_ok("null");
150
+
151
+ } else if (method == "fs:removeDir") {
152
+ bool recursive = params.size() > 1 && params[1].as_bool();
153
+ handleRemoveDir(params[0].as_string(), recursive);
154
+ reply_ok("null");
155
+
156
+ } else if (method == "fs:openPath") {
157
+ handleOpenPath(params[0].as_string());
158
+ reply_ok("null");
159
+
160
+ } else if (method == "fs:revealPath") {
161
+ handleRevealPath(params[0].as_string());
162
+ reply_ok("null");
163
+
164
+ } else if (method == "fs:listApplications") {
165
+ reply_ok(applicationEntriesToJson(handleListApplications()));
166
+
167
+ } else if (method == "fs:launchApplication") {
168
+ handleLaunchApplication(params[0].as_string());
169
+ reply_ok("null");
170
+
171
+ } else if (method == "fs:searchFiles") {
172
+ SearchOptions opts;
173
+ if (params.size() > 1) {
174
+ auto& o = params[1];
175
+ opts.pattern = o.get_string("pattern", "*");
176
+ opts.recursive = o.get_bool("recursive", false);
177
+ opts.includeHidden = o.get_bool("includeHidden", false);
178
+ opts.includeDirectories = o.get_bool("includeDirectories", false);
179
+ opts.maxResults = o.get_size_t("maxResults", 0);
180
+ }
181
+ reply_ok(stringArrayToJson(handleSearchFiles(params[0].as_string(), opts)));
182
+
183
+ } else if (method == "fs:searchFilesStreamStart") {
184
+ std::vector<std::string> roots;
185
+ if (!params.empty()) {
186
+ try {
187
+ for (const auto& value : params[0].as_array()) {
188
+ roots.push_back(value.as_string());
189
+ }
190
+ } catch (...) {
191
+ roots.push_back(params[0].as_string());
192
+ }
193
+ }
194
+
195
+ SearchOptions opts;
196
+ if (params.size() > 1) {
197
+ auto& o = params[1];
198
+ opts.pattern = o.get_string("pattern", "*");
199
+ opts.recursive = o.get_bool("recursive", false);
200
+ opts.includeHidden = o.get_bool("includeHidden", false);
201
+ opts.includeDirectories = o.get_bool("includeDirectories", false);
202
+ opts.maxResults = o.get_size_t("maxResults", 0);
203
+ }
204
+ std::string requested_search_id;
205
+ if (params.size() > 2) {
206
+ requested_search_id = params[2].as_string();
207
+ }
208
+
209
+ if (roots.empty()) {
210
+ throw std::runtime_error("No search roots provided");
211
+ }
212
+
213
+ const std::string search_id = FileSearchService::instance().start(
214
+ roots,
215
+ opts,
216
+ [send_stream_event](const std::string& stream_id, std::vector<std::string> batch) {
217
+ send_stream_event(stream_id, "batch", stringArrayToJson(batch));
218
+ },
219
+ [send_stream_event](const std::string& stream_id, const StreamSearchSummary& summary) {
220
+ send_stream_event(stream_id, "done", searchSummaryToJson(summary));
221
+ },
222
+ requested_search_id);
223
+
224
+ reply_ok(JsonValue::dump_value(search_id));
225
+
226
+ } else if (method == "fs:searchFilesStreamCancel") {
227
+ FileSearchService::instance().cancel(params[0].as_string());
228
+ reply_ok("null");
229
+ }
230
+
231
+ } catch (const std::exception& e) {
232
+ reply_err(e.what());
233
+ } catch (...) {
234
+ reply_err("Unknown error in fs bridge");
235
+ }
236
+ }
237
+
238
+ private:
239
+ EvalFn eval_;
240
+ DispatchFn dispatch_;
241
+ };
242
+
243
+ } // namespace wpp::fs
@@ -0,0 +1,93 @@
1
+ // ============================================================================
2
+ // FileSystem/filesystem_handler.h
3
+ // Shared types and function declarations used by every platform
4
+ // implementation. Include this in each platform *.cpp.
5
+ // ============================================================================
6
+
7
+ #pragma once
8
+
9
+ #include <functional>
10
+ #include <cstdint>
11
+ #include <string>
12
+ #include <vector>
13
+
14
+ namespace wpp::fs {
15
+
16
+ // ─── Shared types (mirror the TypeScript interfaces) ─────────────────────────
17
+
18
+ struct FileStat {
19
+ std::string path;
20
+ std::string name;
21
+ int64_t size; // bytes
22
+ bool isDir;
23
+ bool isSymlink;
24
+ int64_t modifiedMs; // ms since Unix epoch
25
+ int64_t createdMs; // ms since Unix epoch; -1 if unsupported
26
+ int mode; // POSIX permission bits; -1 on Windows
27
+ };
28
+
29
+ struct DirEntry {
30
+ std::string name;
31
+ std::string path;
32
+ bool isDir;
33
+ bool isSymlink;
34
+ };
35
+
36
+ struct ApplicationEntry {
37
+ std::string id;
38
+ std::string name;
39
+ std::string path;
40
+ std::string launchTarget;
41
+ };
42
+
43
+ struct SearchOptions {
44
+ std::string pattern; // glob, e.g. "*.cpp" — empty → "*"
45
+ bool recursive = false;
46
+ bool includeHidden = false;
47
+ bool includeDirectories = false;
48
+ size_t maxResults = 0; // 0 = unlimited
49
+ };
50
+
51
+ struct StreamSearchSummary {
52
+ uint64_t scannedEntries = 0;
53
+ uint64_t matchedEntries = 0;
54
+ bool cancelled = false;
55
+ bool truncated = false;
56
+ std::string error;
57
+ };
58
+
59
+ using StreamBatchCallback = std::function<void(const std::string& searchId,
60
+ std::vector<std::string> batch)>;
61
+ using StreamDoneCallback = std::function<void(const std::string& searchId,
62
+ const StreamSearchSummary& summary)>;
63
+
64
+ // ─── Per-operation handler declarations ─────────────────────────────────────
65
+ // Each platform provides exactly these functions in its own .cpp files.
66
+
67
+ // readfile.cpp
68
+ std::string handleReadFile(const std::string& path);
69
+ std::string handleReadBinaryFile(const std::string& path); // → Base64
70
+
71
+ // savefile.cpp
72
+ void handleWriteFile (const std::string& path, const std::string& text);
73
+ void handleWriteBinaryFile(const std::string& path, const std::string& b64);
74
+ void handleAppendFile (const std::string& path, const std::string& text);
75
+ void handleCopyFile (const std::string& src, const std::string& dest);
76
+ void handleMoveFile (const std::string& src, const std::string& dest);
77
+ void handleDeleteFile (const std::string& path);
78
+ void handleCreateDir (const std::string& path, bool recursive);
79
+ void handleRemoveDir (const std::string& path, bool recursive);
80
+ void handleOpenPath (const std::string& path);
81
+ void handleRevealPath (const std::string& path);
82
+ std::vector<ApplicationEntry> handleListApplications();
83
+ void handleLaunchApplication(const std::string& target);
84
+
85
+ // filesearch.cpp
86
+ bool handleExists (const std::string& path);
87
+ FileStat handleStat (const std::string& path);
88
+ std::vector<DirEntry> handleReadDir (const std::string& path);
89
+ std::vector<std::string> handleListRoots ();
90
+ std::vector<std::string> handleSearchFiles(const std::string& dir,
91
+ const SearchOptions& opts);
92
+
93
+ } // namespace wpp::fs
@@ -0,0 +1,241 @@
1
+ // ============================================================================
2
+ // FileSystem/filesystem_json.h
3
+ // nlohmann/json-backed helpers for the native bridge layer.
4
+ // ============================================================================
5
+
6
+ #pragma once
7
+
8
+ #include <cstdint>
9
+ #include <stdexcept>
10
+ #include <string>
11
+ #include <vector>
12
+
13
+ #include <nlohmann/json.hpp>
14
+
15
+ #include "filesystem_handler.h"
16
+
17
+ namespace wpp::fs {
18
+
19
+ class JsonValue {
20
+ public:
21
+ using NativeJson = nlohmann::json;
22
+
23
+ JsonValue() = default;
24
+ explicit JsonValue(NativeJson value) : value_(std::move(value)) {}
25
+
26
+ static JsonValue parse(const std::string& s) {
27
+ return JsonValue(NativeJson::parse(s));
28
+ }
29
+
30
+ std::string as_string() const {
31
+ if (value_.is_string()) {
32
+ return value_.get<std::string>();
33
+ }
34
+ throw std::runtime_error("JsonValue: not a string");
35
+ }
36
+
37
+ bool as_bool() const {
38
+ if (value_.is_boolean()) {
39
+ return value_.get<bool>();
40
+ }
41
+ if (value_.is_number_integer() || value_.is_number_unsigned()) {
42
+ return value_.get<int64_t>() != 0;
43
+ }
44
+ throw std::runtime_error("JsonValue: not a bool");
45
+ }
46
+
47
+ int64_t as_int() const {
48
+ if (value_.is_number_integer() || value_.is_number_unsigned()) {
49
+ return value_.get<int64_t>();
50
+ }
51
+ if (value_.is_number_float()) {
52
+ return static_cast<int64_t>(value_.get<double>());
53
+ }
54
+ throw std::runtime_error("JsonValue: not a number");
55
+ }
56
+
57
+ double as_double() const {
58
+ if (value_.is_number_float()) {
59
+ return value_.get<double>();
60
+ }
61
+ if (value_.is_number_integer() || value_.is_number_unsigned()) {
62
+ return static_cast<double>(value_.get<int64_t>());
63
+ }
64
+ throw std::runtime_error("JsonValue: not a number");
65
+ }
66
+
67
+ std::vector<JsonValue> as_array() const {
68
+ if (value_.is_null()) {
69
+ return {};
70
+ }
71
+ if (!value_.is_array()) {
72
+ throw std::runtime_error("JsonValue: not an array");
73
+ }
74
+
75
+ std::vector<JsonValue> values;
76
+ values.reserve(value_.size());
77
+ for (const auto& item : value_) {
78
+ values.emplace_back(item);
79
+ }
80
+ return values;
81
+ }
82
+
83
+ JsonValue operator[](const std::string& key) const {
84
+ if (value_.is_object()) {
85
+ auto it = value_.find(key);
86
+ if (it != value_.end()) {
87
+ return JsonValue(*it);
88
+ }
89
+ }
90
+ return JsonValue();
91
+ }
92
+
93
+ JsonValue operator[](size_t idx) const {
94
+ if (!value_.is_array() || idx >= value_.size()) {
95
+ throw std::out_of_range("JsonValue: array index out of range");
96
+ }
97
+ return JsonValue(value_.at(idx));
98
+ }
99
+
100
+ std::string get_string(const std::string& key, const std::string& def) const {
101
+ if (!value_.is_object()) {
102
+ return def;
103
+ }
104
+ auto it = value_.find(key);
105
+ if (it != value_.end() && it->is_string()) {
106
+ return it->get<std::string>();
107
+ }
108
+ return def;
109
+ }
110
+
111
+ bool get_bool(const std::string& key, bool def) const {
112
+ if (!value_.is_object()) {
113
+ return def;
114
+ }
115
+ auto it = value_.find(key);
116
+ if (it != value_.end() && it->is_boolean()) {
117
+ return it->get<bool>();
118
+ }
119
+ return def;
120
+ }
121
+
122
+ int64_t get_int(const std::string& key, int64_t def) const {
123
+ if (!value_.is_object()) {
124
+ return def;
125
+ }
126
+ auto it = value_.find(key);
127
+ if (it == value_.end()) {
128
+ return def;
129
+ }
130
+ if (it->is_number_integer() || it->is_number_unsigned()) {
131
+ return it->get<int64_t>();
132
+ }
133
+ if (it->is_number_float()) {
134
+ return static_cast<int64_t>(it->get<double>());
135
+ }
136
+ return def;
137
+ }
138
+
139
+ size_t get_size_t(const std::string& key, size_t def) const {
140
+ const int64_t value = get_int(key, static_cast<int64_t>(def));
141
+ if (value < 0) {
142
+ return def;
143
+ }
144
+ return static_cast<size_t>(value);
145
+ }
146
+
147
+ static std::string quote(const std::string& s) {
148
+ return NativeJson(s).dump();
149
+ }
150
+
151
+ static std::string to_js_argument(const std::string& value) {
152
+ return NativeJson(value).dump();
153
+ }
154
+
155
+ static std::string to_js_argument(const char* value) {
156
+ return NativeJson(value).dump();
157
+ }
158
+
159
+ static std::string to_js_argument(bool value) {
160
+ return NativeJson(value).dump();
161
+ }
162
+
163
+ static std::string to_js_argument(std::nullptr_t) {
164
+ return "null";
165
+ }
166
+
167
+ template <typename T>
168
+ static std::string to_js_argument(const T& value) {
169
+ return NativeJson(value).dump();
170
+ }
171
+
172
+ template <typename T>
173
+ static std::string dump_value(const T& value) {
174
+ return NativeJson(value).dump();
175
+ }
176
+
177
+ private:
178
+ NativeJson value_ = nullptr;
179
+ };
180
+
181
+ template <typename Entry>
182
+ inline std::string dirEntriesToJson(const std::vector<Entry>& entries,
183
+ bool Entry::*is_dir,
184
+ bool Entry::*is_symlink) {
185
+ auto json = nlohmann::json::array();
186
+ for (const auto& entry : entries) {
187
+ json.push_back({
188
+ {"name", entry.name},
189
+ {"path", entry.path},
190
+ {"isDir", entry.*is_dir},
191
+ {"isSymlink", entry.*is_symlink},
192
+ });
193
+ }
194
+ return json.dump();
195
+ }
196
+
197
+ inline std::string dirEntriesToJson(const std::vector<DirEntry>& entries) {
198
+ return dirEntriesToJson(entries, &DirEntry::isDir, &DirEntry::isSymlink);
199
+ }
200
+
201
+ inline std::string statToJson(const FileStat& stat) {
202
+ return nlohmann::json({
203
+ {"path", stat.path},
204
+ {"name", stat.name},
205
+ {"size", stat.size},
206
+ {"isDir", stat.isDir},
207
+ {"isSymlink", stat.isSymlink},
208
+ {"modifiedMs", stat.modifiedMs},
209
+ {"createdMs", stat.createdMs},
210
+ {"mode", stat.mode},
211
+ }).dump();
212
+ }
213
+
214
+ inline std::string applicationEntriesToJson(const std::vector<ApplicationEntry>& entries) {
215
+ auto json = nlohmann::json::array();
216
+ for (const auto& entry : entries) {
217
+ json.push_back({
218
+ {"id", entry.id},
219
+ {"name", entry.name},
220
+ {"path", entry.path},
221
+ {"launchTarget", entry.launchTarget},
222
+ });
223
+ }
224
+ return json.dump();
225
+ }
226
+
227
+ inline std::string stringArrayToJson(const std::vector<std::string>& values) {
228
+ return nlohmann::json(values).dump();
229
+ }
230
+
231
+ inline std::string searchSummaryToJson(const StreamSearchSummary& summary) {
232
+ return nlohmann::json({
233
+ {"scannedEntries", summary.scannedEntries},
234
+ {"matchedEntries", summary.matchedEntries},
235
+ {"cancelled", summary.cancelled},
236
+ {"truncated", summary.truncated},
237
+ {"error", summary.error},
238
+ }).dump();
239
+ }
240
+
241
+ } // namespace wpp::fs