@aptre/bldr-saucer 0.2.6 → 0.3.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.
package/CMakeLists.txt CHANGED
@@ -19,6 +19,7 @@ set(saucer_serializer "Glaze" CACHE STRING "" FORCE)
19
19
  set(saucer_no_version_check ON CACHE BOOL "" FORCE)
20
20
  set(saucer_examples OFF CACHE BOOL "" FORCE)
21
21
  set(saucer_tests OFF CACHE BOOL "" FORCE)
22
+ set(saucer_exceptions OFF CACHE BOOL "" FORCE)
22
23
 
23
24
  # cpp-yamux options.
24
25
  set(YAMUX_BUILD_TESTS OFF CACHE BOOL "" FORCE)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aptre/bldr-saucer",
3
- "version": "0.2.6",
3
+ "version": "0.3.1",
4
4
  "description": "Native webview bridge for Bldr using Saucer",
5
5
  "main": "index.js",
6
6
  "repository": {
@@ -33,11 +33,11 @@
33
33
  "release:publish": "git push && git push --tags"
34
34
  },
35
35
  "optionalDependencies": {
36
- "@aptre/bldr-saucer-darwin-arm64": "0.2.6",
37
- "@aptre/bldr-saucer-darwin-x64": "0.2.6",
38
- "@aptre/bldr-saucer-linux-x64": "0.2.6",
39
- "@aptre/bldr-saucer-linux-arm64": "0.2.6",
40
- "@aptre/bldr-saucer-win32-x64": "0.2.6"
36
+ "@aptre/bldr-saucer-darwin-arm64": "0.3.1",
37
+ "@aptre/bldr-saucer-darwin-x64": "0.3.1",
38
+ "@aptre/bldr-saucer-linux-x64": "0.3.1",
39
+ "@aptre/bldr-saucer-linux-arm64": "0.3.1",
40
+ "@aptre/bldr-saucer-win32-x64": "0.3.1"
41
41
  },
42
42
  "files": [
43
43
  "index.js",
@@ -49,6 +49,6 @@
49
49
  "@aptre/common": "^0.30.3"
50
50
  },
51
51
  "dependencies": {
52
- "@aptre/protobuf-es-lite": "^0.5.2"
52
+ "@aptre/protobuf-es-lite": "^1.0.0"
53
53
  }
54
54
  }
package/src/main.cpp CHANGED
@@ -113,8 +113,16 @@ coco::stray start(saucer::application* app) {
113
113
  // Register bldr:// scheme BEFORE creating the webview.
114
114
  saucer::webview::register_scheme("bldr");
115
115
 
116
+ // Construct a per-instance storage path from the runtime ID.
117
+ // This ensures concurrent bldr-saucer instances don't share webview storage.
118
+ auto storage = std::filesystem::temp_directory_path() / ("bldr-saucer-" + runtime_id);
119
+
116
120
  auto window = saucer::window::create(app).value();
117
- auto webview = saucer::smartview::create({.window = window});
121
+ auto webview = saucer::smartview::create({
122
+ .window = window,
123
+ .non_persistent_data_store = true,
124
+ .storage_path = storage,
125
+ });
118
126
 
119
127
  window->set_title("Bldr");
120
128
  window->set_size({1024, 768});
@@ -157,7 +165,7 @@ coco::stray start(saucer::application* app) {
157
165
  // The smartview's own handler returns unhandled for unrecognized messages,
158
166
  // so this handler sees them next.
159
167
  constexpr std::string_view eval_prefix = "__bldr_eval:";
160
- webview->on<saucer::webview::event::message>({{.func = [eval_registry, eval_prefix](std::string_view message) -> saucer::status {
168
+ webview->on<saucer::webview::event::message>([eval_registry, eval_prefix](std::string_view message) -> saucer::status {
161
169
  if (!message.starts_with(eval_prefix)) {
162
170
  return saucer::status::unhandled;
163
171
  }
@@ -183,7 +191,7 @@ coco::stray start(saucer::application* app) {
183
191
  eval_registry->Deliver(eval_id, "", data);
184
192
  }
185
193
  return saucer::status::handled;
186
- }}});
194
+ });
187
195
 
188
196
  // Start accept loop for Go-initiated streams (debug eval).
189
197
  // webview is a std::expected; use &(*webview) to get a pointer to the contained value.
@@ -14,14 +14,30 @@ static std::string toLower(const std::string& s) {
14
14
  return out;
15
15
  }
16
16
 
17
+ // corsHeaders are Access-Control headers added to all scheme responses.
18
+ // WebKit treats custom scheme origins as opaque (null), so all fetch requests
19
+ // from pages loaded via bldr:// are cross-origin. These headers allow them.
20
+ static const std::map<std::string, std::string> corsHeaders = {
21
+ {"Access-Control-Allow-Origin", "*"},
22
+ {"Access-Control-Allow-Methods", "GET, POST, OPTIONS"},
23
+ {"Access-Control-Allow-Headers", "*"},
24
+ };
25
+
17
26
  // sendError sends an error response to the saucer writer.
18
27
  static void sendError(saucer::scheme::stream_writer& writer, int status) {
19
- writer.start({.mime = "text/plain", .status = status});
28
+ writer.start({.mime = "text/plain", .headers = corsHeaders, .status = status});
20
29
  writer.finish();
21
30
  }
22
31
 
23
32
  void SchemeForwarder::forward(const saucer::scheme::request& req,
24
33
  saucer::scheme::stream_writer& writer) {
34
+ // Handle CORS preflight directly without forwarding to Go.
35
+ if (toLower(req.method()) == "options") {
36
+ writer.start({.mime = "text/plain", .headers = corsHeaders, .status = 204});
37
+ writer.finish();
38
+ return;
39
+ }
40
+
25
41
  // Open a new yamux stream.
26
42
  auto [stream, err] = session_->OpenStream();
27
43
  if (err != yamux::Error::OK || !stream) {
@@ -93,9 +109,9 @@ void SchemeForwarder::forward(const saucer::scheme::request& req,
93
109
  if (resp.has_info && !started) {
94
110
  started = true;
95
111
 
96
- // Extract Content-Type header (case-insensitive).
112
+ // Extract Content-Type header (case-insensitive) and merge CORS headers.
97
113
  std::string mime = "application/octet-stream";
98
- std::map<std::string, std::string> hdrs;
114
+ std::map<std::string, std::string> hdrs(corsHeaders);
99
115
  for (const auto& [key, val] : resp.info.headers) {
100
116
  if (toLower(key) == "content-type") {
101
117
  mime = val;