@glassly/crust 0.3.5-dev.750 → 0.3.5-dev.753

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.
@@ -219,6 +219,13 @@ object JSCPolyfillBridge {
219
219
  ks to vs
220
220
  }?.toMap() ?: emptyMap()
221
221
  val bodyString = req["body"] as? String
222
+ val bodyBytes = (req["bodyBase64"] as? String)?.let { encoded ->
223
+ try {
224
+ Base64.decode(encoded, Base64.DEFAULT)
225
+ } catch (e: IllegalArgumentException) {
226
+ return@register JSCDispatchOutcome.Error("INVALID_ARGS", "fetch.request: bodyBase64 is not base64")
227
+ }
228
+ }
222
229
 
223
230
  val builder = Request.Builder().url(url)
224
231
  for ((k, v) in headers) builder.header(k, v)
@@ -228,10 +235,16 @@ object JSCPolyfillBridge {
228
235
  val contentType = headers.entries
229
236
  .firstOrNull { (name, _) -> name.equals("content-type", ignoreCase = true) }
230
237
  ?.value
231
- val body = if (bodyString.isNullOrEmpty()) null else bodyString.toRequestBody(
232
- (contentType ?: "application/octet-stream").toMediaTypeOrNull()
233
- )
234
- builder.method(method.uppercase(), body)
238
+ val mediaType = (contentType ?: "application/octet-stream").toMediaTypeOrNull()
239
+ val upperMethod = method.uppercase()
240
+ val body = when {
241
+ upperMethod == "GET" || upperMethod == "HEAD" -> null
242
+ bodyBytes != null -> bodyBytes.toRequestBody(mediaType)
243
+ bodyString != null -> bodyString.toRequestBody(mediaType)
244
+ upperMethod == "POST" || upperMethod == "PUT" || upperMethod == "PATCH" -> "".toRequestBody(null)
245
+ else -> null
246
+ }
247
+ builder.method(upperMethod, body)
235
248
 
236
249
  httpClient.newCall(builder.build()).enqueue(object : Callback {
237
250
  override fun onFailure(call: Call, e: IOException) {
@@ -546,15 +546,36 @@
546
546
  return out;
547
547
  };
548
548
  }
549
+ function bytesToBase64(bytes) {
550
+ const b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
551
+ let out = "";
552
+ let i = 0;
553
+ while (i < bytes.length) {
554
+ const c1 = bytes[i++];
555
+ const c2 = i < bytes.length ? bytes[i++] : NaN;
556
+ const c3 = i < bytes.length ? bytes[i++] : NaN;
557
+ const e1 = c1 >> 2;
558
+ const e2 = (c1 & 3) << 4 | (Number.isNaN(c2) ? 0 : c2 >> 4);
559
+ const e3 = Number.isNaN(c2) ? 64 : (c2 & 15) << 2 | (Number.isNaN(c3) ? 0 : c3 >> 6);
560
+ const e4 = Number.isNaN(c3) ? 64 : c3 & 63;
561
+ out += b64[e1] + b64[e2] + (e3 === 64 ? "=" : b64[e3]) + (e4 === 64 ? "=" : b64[e4]);
562
+ }
563
+ return out;
564
+ }
549
565
  if (typeof g.fetch !== "function") {
550
566
  ;
551
567
  g.fetch = async (input, init) => {
552
568
  const url = typeof input === "string" ? input : input.toString();
553
569
  const method = (init?.method ?? "GET").toUpperCase();
554
570
  let bodyString = null;
571
+ let bodyBase64 = null;
555
572
  const reqBody = init?.body;
556
573
  if (typeof reqBody === "string") {
557
574
  bodyString = reqBody;
575
+ } else if (reqBody instanceof ArrayBuffer) {
576
+ bodyBase64 = bytesToBase64(new Uint8Array(reqBody));
577
+ } else if (ArrayBuffer.isView(reqBody)) {
578
+ bodyBase64 = bytesToBase64(new Uint8Array(reqBody.buffer, reqBody.byteOffset, reqBody.byteLength));
558
579
  } else if (reqBody && typeof reqBody.toString === "function") {
559
580
  bodyString = reqBody.toString();
560
581
  }
@@ -577,7 +598,7 @@
577
598
  }
578
599
  }
579
600
  const sendRequest = g.__sendRequest;
580
- const result = await sendRequest("fetch", "request", [{ url, method, headers, body: bodyString }]);
601
+ const result = await sendRequest("fetch", "request", [{ url, method, headers, body: bodyString, bodyBase64 }]);
581
602
  const bodyText = typeof result.body === "string" ? result.body : "";
582
603
  const responseHeaders = new Map(Object.entries(result.headers ?? {}));
583
604
  class ResponseLike {
@@ -617,22 +638,7 @@
617
638
  };
618
639
  }
619
640
  if (typeof g.WebSocket !== "function") {
620
- let bytesToBase642 = function(bytes) {
621
- const b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
622
- let out = "";
623
- let i = 0;
624
- while (i < bytes.length) {
625
- const c1 = bytes[i++];
626
- const c2 = i < bytes.length ? bytes[i++] : NaN;
627
- const c3 = i < bytes.length ? bytes[i++] : NaN;
628
- const e1 = c1 >> 2;
629
- const e2 = (c1 & 3) << 4 | (Number.isNaN(c2) ? 0 : c2 >> 4);
630
- const e3 = Number.isNaN(c2) ? 64 : (c2 & 15) << 2 | (Number.isNaN(c3) ? 0 : c3 >> 6);
631
- const e4 = Number.isNaN(c3) ? 64 : c3 & 63;
632
- out += b64[e1] + b64[e2] + (e3 === 64 ? "=" : b64[e3]) + (e4 === 64 ? "=" : b64[e4]);
633
- }
634
- return out;
635
- }, base64ToBytes2 = function(s) {
641
+ let base64ToBytes2 = function(s) {
636
642
  const b64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
637
643
  const clean = s.replace(/=+$/, "");
638
644
  const out = [];
@@ -654,7 +660,7 @@
654
660
  if (typeof q === "function") q(fn);
655
661
  else g.Promise.resolve().then(fn);
656
662
  };
657
- var bytesToBase64 = bytesToBase642, base64ToBytes = base64ToBytes2, queueMicrotaskSafe = queueMicrotaskSafe2;
663
+ var base64ToBytes = base64ToBytes2, queueMicrotaskSafe = queueMicrotaskSafe2;
658
664
  const sockets = /* @__PURE__ */ new Map();
659
665
  g.__deliverWebSocketEvent = (sid, type, payload) => {
660
666
  const sock = sockets.get(sid);
@@ -713,7 +719,7 @@
713
719
  } else {
714
720
  kind = "binary";
715
721
  const bytes = data instanceof ArrayBuffer ? new Uint8Array(data) : new Uint8Array(data.buffer, data.byteOffset, data.byteLength);
716
- payload = bytesToBase642(bytes);
722
+ payload = bytesToBase64(bytes);
717
723
  }
718
724
  try {
719
725
  __dispatch("ws", "send", JSON.stringify([{ sid: this.sid, kind, payload }]));
@@ -100,14 +100,25 @@ public enum JSCPolyfillBridge {
100
100
  }
101
101
 
102
102
  var urlRequest = URLRequest(url: url)
103
- urlRequest.httpMethod = (req["method"] as? String) ?? "GET"
103
+ let method = (req["method"] as? String) ?? "GET"
104
+ urlRequest.httpMethod = method
104
105
  if let headers = req["headers"] as? [String: Any] {
105
106
  for (k, v) in headers {
106
107
  urlRequest.setValue(String(describing: v), forHTTPHeaderField: k)
107
108
  }
108
109
  }
109
- if let body = req["body"] as? String, !body.isEmpty {
110
- urlRequest.httpBody = body.data(using: .utf8)
110
+ let upperMethod = method.uppercased()
111
+ if upperMethod == "GET" || upperMethod == "HEAD" {
112
+ urlRequest.httpBody = nil
113
+ } else if let encoded = req["bodyBase64"] as? String {
114
+ guard let data = Data(base64Encoded: encoded) else {
115
+ return .error(code: "INVALID_ARGS", message: "fetch.request: bodyBase64 is not base64")
116
+ }
117
+ urlRequest.httpBody = data
118
+ } else if let body = req["body"] as? String {
119
+ urlRequest.httpBody = Data(body.utf8)
120
+ } else if ["POST", "PUT", "PATCH"].contains(upperMethod) {
121
+ urlRequest.httpBody = Data()
111
122
  }
112
123
 
113
124
  // Reasonable defaults — caller can override later by passing
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@glassly/crust",
3
- "version": "0.3.5-dev.750",
3
+ "version": "0.3.5-dev.753",
4
4
  "description": "Glassly Native Module",
5
5
  "main": "build/index.js",
6
6
  "types": "build/index.d.ts",
@@ -35,7 +35,7 @@
35
35
  "license": "MIT",
36
36
  "homepage": "https://github.com/fossephate/crust#readme",
37
37
  "dependencies": {
38
- "@glassly/jspolyfill": "0.3.5-dev.750"
38
+ "@glassly/jspolyfill": "0.3.5-dev.753"
39
39
  },
40
40
  "devDependencies": {
41
41
  "@expo/config-plugins": ">=8.0.0",