@strand-js/react-native 0.1.0 → 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.
@@ -0,0 +1,4 @@
1
+ declare function createXHRStreamingFetch(): typeof fetch;
2
+ declare function applyStreamingFetchPatch(): void;
3
+
4
+ export { applyStreamingFetchPatch, createXHRStreamingFetch };
@@ -0,0 +1,4 @@
1
+ declare function createXHRStreamingFetch(): typeof fetch;
2
+ declare function applyStreamingFetchPatch(): void;
3
+
4
+ export { applyStreamingFetchPatch, createXHRStreamingFetch };
package/dist/index.js ADDED
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ applyStreamingFetchPatch: () => applyStreamingFetchPatch,
24
+ createXHRStreamingFetch: () => createXHRStreamingFetch
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/patch.ts
29
+ var encoder = new TextEncoder();
30
+ function parseResponseHeaders(headersStr) {
31
+ const headers = {};
32
+ for (const line of headersStr.trim().split("\r\n")) {
33
+ const idx = line.indexOf(": ");
34
+ if (idx > 0) headers[line.slice(0, idx).toLowerCase()] = line.slice(idx + 2);
35
+ }
36
+ return headers;
37
+ }
38
+ function createXHRStreamingFetch() {
39
+ return (input, init) => {
40
+ const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
41
+ const method = init?.method ?? (typeof input !== "string" && !(input instanceof URL) ? input.method : "GET");
42
+ return new Promise((resolve, reject) => {
43
+ const xhr = new XMLHttpRequest();
44
+ xhr.open(method, url, true);
45
+ xhr.responseType = "text";
46
+ const reqHeaders = init?.headers ? new Headers(init.headers) : new Headers();
47
+ reqHeaders.forEach((value, key) => xhr.setRequestHeader(key, value));
48
+ let resolved = false;
49
+ let streamController = null;
50
+ let processedLength = 0;
51
+ const readableStream = new ReadableStream({
52
+ start(controller) {
53
+ streamController = controller;
54
+ },
55
+ cancel() {
56
+ xhr.abort();
57
+ }
58
+ });
59
+ function pushChunk() {
60
+ const text = xhr.responseText;
61
+ const newText = text.slice(processedLength);
62
+ processedLength = text.length;
63
+ if (newText && streamController) {
64
+ streamController.enqueue(encoder.encode(newText));
65
+ }
66
+ }
67
+ function resolveResponse() {
68
+ if (!resolved) {
69
+ resolved = true;
70
+ resolve(
71
+ new Response(readableStream, {
72
+ status: xhr.status,
73
+ statusText: xhr.statusText,
74
+ headers: parseResponseHeaders(xhr.getAllResponseHeaders())
75
+ })
76
+ );
77
+ }
78
+ }
79
+ xhr.onprogress = () => {
80
+ pushChunk();
81
+ resolveResponse();
82
+ };
83
+ xhr.onload = () => {
84
+ pushChunk();
85
+ streamController?.close();
86
+ resolveResponse();
87
+ };
88
+ xhr.onerror = () => {
89
+ const err = new TypeError("Network request failed");
90
+ streamController?.error(err);
91
+ if (!resolved) reject(err);
92
+ };
93
+ xhr.onabort = () => {
94
+ const err = new DOMException("Request aborted", "AbortError");
95
+ streamController?.error(err);
96
+ if (!resolved) reject(err);
97
+ };
98
+ if (init?.signal) {
99
+ init.signal.addEventListener("abort", () => xhr.abort());
100
+ }
101
+ xhr.send(init?.body ?? null);
102
+ });
103
+ };
104
+ }
105
+ var patched = false;
106
+ function applyStreamingFetchPatch() {
107
+ if (patched) return;
108
+ patched = true;
109
+ const nav = typeof navigator !== "undefined" ? navigator : null;
110
+ const isReactNative = nav?.product === "ReactNative";
111
+ if (isReactNative) {
112
+ globalThis.fetch = createXHRStreamingFetch();
113
+ }
114
+ }
115
+
116
+ // src/index.ts
117
+ applyStreamingFetchPatch();
118
+ // Annotate the CommonJS export names for ESM import in node:
119
+ 0 && (module.exports = {
120
+ applyStreamingFetchPatch,
121
+ createXHRStreamingFetch
122
+ });
package/dist/index.mjs ADDED
@@ -0,0 +1,94 @@
1
+ // src/patch.ts
2
+ var encoder = new TextEncoder();
3
+ function parseResponseHeaders(headersStr) {
4
+ const headers = {};
5
+ for (const line of headersStr.trim().split("\r\n")) {
6
+ const idx = line.indexOf(": ");
7
+ if (idx > 0) headers[line.slice(0, idx).toLowerCase()] = line.slice(idx + 2);
8
+ }
9
+ return headers;
10
+ }
11
+ function createXHRStreamingFetch() {
12
+ return (input, init) => {
13
+ const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url;
14
+ const method = init?.method ?? (typeof input !== "string" && !(input instanceof URL) ? input.method : "GET");
15
+ return new Promise((resolve, reject) => {
16
+ const xhr = new XMLHttpRequest();
17
+ xhr.open(method, url, true);
18
+ xhr.responseType = "text";
19
+ const reqHeaders = init?.headers ? new Headers(init.headers) : new Headers();
20
+ reqHeaders.forEach((value, key) => xhr.setRequestHeader(key, value));
21
+ let resolved = false;
22
+ let streamController = null;
23
+ let processedLength = 0;
24
+ const readableStream = new ReadableStream({
25
+ start(controller) {
26
+ streamController = controller;
27
+ },
28
+ cancel() {
29
+ xhr.abort();
30
+ }
31
+ });
32
+ function pushChunk() {
33
+ const text = xhr.responseText;
34
+ const newText = text.slice(processedLength);
35
+ processedLength = text.length;
36
+ if (newText && streamController) {
37
+ streamController.enqueue(encoder.encode(newText));
38
+ }
39
+ }
40
+ function resolveResponse() {
41
+ if (!resolved) {
42
+ resolved = true;
43
+ resolve(
44
+ new Response(readableStream, {
45
+ status: xhr.status,
46
+ statusText: xhr.statusText,
47
+ headers: parseResponseHeaders(xhr.getAllResponseHeaders())
48
+ })
49
+ );
50
+ }
51
+ }
52
+ xhr.onprogress = () => {
53
+ pushChunk();
54
+ resolveResponse();
55
+ };
56
+ xhr.onload = () => {
57
+ pushChunk();
58
+ streamController?.close();
59
+ resolveResponse();
60
+ };
61
+ xhr.onerror = () => {
62
+ const err = new TypeError("Network request failed");
63
+ streamController?.error(err);
64
+ if (!resolved) reject(err);
65
+ };
66
+ xhr.onabort = () => {
67
+ const err = new DOMException("Request aborted", "AbortError");
68
+ streamController?.error(err);
69
+ if (!resolved) reject(err);
70
+ };
71
+ if (init?.signal) {
72
+ init.signal.addEventListener("abort", () => xhr.abort());
73
+ }
74
+ xhr.send(init?.body ?? null);
75
+ });
76
+ };
77
+ }
78
+ var patched = false;
79
+ function applyStreamingFetchPatch() {
80
+ if (patched) return;
81
+ patched = true;
82
+ const nav = typeof navigator !== "undefined" ? navigator : null;
83
+ const isReactNative = nav?.product === "ReactNative";
84
+ if (isReactNative) {
85
+ globalThis.fetch = createXHRStreamingFetch();
86
+ }
87
+ }
88
+
89
+ // src/index.ts
90
+ applyStreamingFetchPatch();
91
+ export {
92
+ applyStreamingFetchPatch,
93
+ createXHRStreamingFetch
94
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strand-js/react-native",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "React Native transport adapter for Strand — patches streaming fetch support",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -15,8 +15,15 @@
15
15
  "files": [
16
16
  "dist"
17
17
  ],
18
+ "scripts": {
19
+ "build": "tsup src/index.ts --format esm,cjs --dts --clean",
20
+ "dev": "tsup src/index.ts --format esm,cjs --dts --watch",
21
+ "typecheck": "tsc --noEmit",
22
+ "test": "vitest run",
23
+ "lint": "eslint src"
24
+ },
18
25
  "dependencies": {
19
- "@strand-js/core": "0.1.0"
26
+ "@strand-js/core": "workspace:*"
20
27
  },
21
28
  "peerDependencies": {
22
29
  "react": "^18.0.0",
@@ -29,12 +36,5 @@
29
36
  },
30
37
  "publishConfig": {
31
38
  "access": "public"
32
- },
33
- "scripts": {
34
- "build": "tsup src/index.ts --format esm,cjs --dts --clean",
35
- "dev": "tsup src/index.ts --format esm,cjs --dts --watch",
36
- "typecheck": "tsc --noEmit",
37
- "test": "vitest run",
38
- "lint": "eslint src"
39
39
  }
40
- }
40
+ }