@archipelago-js/client 0.9.0 → 0.10.0
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/README.md +6 -1
- package/dist/fetch.d.ts +6 -0
- package/dist/fetch.js +87 -29
- package/dist/fetch.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -36,7 +36,11 @@ const response = await islandFetch("TeamMembers", "add_member", payload, {
|
|
|
36
36
|
signal: abortController.signal,
|
|
37
37
|
stream: "TeamMembers:42", // sent as X-Archipelago-Stream header
|
|
38
38
|
navigate: (url) => { ... }, // called on redirect responses (default: Turbo.visit or location.assign)
|
|
39
|
-
fetchImpl: fetch
|
|
39
|
+
fetchImpl: fetch, // swap fetch for testing
|
|
40
|
+
onUploadProgress: (progress) => {
|
|
41
|
+
// progress.percentage (0-100), progress.loaded, progress.total
|
|
42
|
+
// automatically switches to XHR transport when provided
|
|
43
|
+
}
|
|
40
44
|
})
|
|
41
45
|
```
|
|
42
46
|
|
|
@@ -166,3 +170,4 @@ clearCsrfCache() // clear cache (next call reads from DOM)
|
|
|
166
170
|
| `IslandForbiddenResponse` | `{ status: "forbidden" }` |
|
|
167
171
|
| `IslandFetchOptions` | Options type for `islandFetch` |
|
|
168
172
|
| `IslandFetchPayload` | Payload type (`Record<string, unknown>`) |
|
|
173
|
+
| `UploadProgress` | `{ percentage, loaded, total }` for upload tracking |
|
package/dist/fetch.d.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { IslandResponse } from "./types";
|
|
2
|
+
export type UploadProgress = {
|
|
3
|
+
percentage: number;
|
|
4
|
+
loaded: number;
|
|
5
|
+
total: number | undefined;
|
|
6
|
+
};
|
|
2
7
|
export type IslandFetchOptions = {
|
|
3
8
|
endpoint?: string;
|
|
4
9
|
fixedParams?: Record<string, unknown>;
|
|
@@ -8,6 +13,7 @@ export type IslandFetchOptions = {
|
|
|
8
13
|
fetchImpl?: typeof fetch;
|
|
9
14
|
navigate?: (location: string) => void;
|
|
10
15
|
stream?: string;
|
|
16
|
+
onUploadProgress?: (progress: UploadProgress) => void;
|
|
11
17
|
};
|
|
12
18
|
export type IslandFetchPayload = Record<string, unknown>;
|
|
13
19
|
export declare function buildIslandPayload(payload?: IslandFetchPayload, fixedParams?: Record<string, unknown>, overridePayload?: Record<string, unknown>): Record<string, unknown>;
|
package/dist/fetch.js
CHANGED
|
@@ -23,11 +23,76 @@ export function buildIslandPayload(payload = {}, fixedParams = {}, overridePaylo
|
|
|
23
23
|
...overridePayload
|
|
24
24
|
};
|
|
25
25
|
}
|
|
26
|
+
function xhrFetch(url, headers, body, signal, onUploadProgress) {
|
|
27
|
+
return new Promise((resolve, reject) => {
|
|
28
|
+
const xhr = new XMLHttpRequest();
|
|
29
|
+
xhr.open("POST", url, true);
|
|
30
|
+
xhr.withCredentials = true;
|
|
31
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
32
|
+
xhr.setRequestHeader(key, value);
|
|
33
|
+
}
|
|
34
|
+
xhr.upload.addEventListener("progress", (event) => {
|
|
35
|
+
onUploadProgress({
|
|
36
|
+
percentage: event.lengthComputable ? Math.round((event.loaded / event.total) * 100) : 0,
|
|
37
|
+
loaded: event.loaded,
|
|
38
|
+
total: event.lengthComputable ? event.total : undefined
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
xhr.addEventListener("load", () => {
|
|
42
|
+
resolve({
|
|
43
|
+
status: xhr.status,
|
|
44
|
+
text: xhr.responseText,
|
|
45
|
+
getHeader: (name) => xhr.getResponseHeader(name)
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
xhr.addEventListener("error", () => {
|
|
49
|
+
reject(new ArchipelagoTransportError("Network request failed"));
|
|
50
|
+
});
|
|
51
|
+
xhr.addEventListener("abort", () => {
|
|
52
|
+
reject(new DOMException("The operation was aborted.", "AbortError"));
|
|
53
|
+
});
|
|
54
|
+
if (signal) {
|
|
55
|
+
if (signal.aborted) {
|
|
56
|
+
xhr.abort();
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
signal.addEventListener("abort", () => xhr.abort(), { once: true });
|
|
60
|
+
}
|
|
61
|
+
xhr.send(body);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
function parseResponseText(text, statusCode, navigate) {
|
|
65
|
+
if (text.trim().length === 0) {
|
|
66
|
+
return { status: "ok", props: {}, version: Date.now() };
|
|
67
|
+
}
|
|
68
|
+
if (looksLikeHtml(text)) {
|
|
69
|
+
throw new ArchipelagoTransportError("Received HTML instead of JSON", {
|
|
70
|
+
statusCode,
|
|
71
|
+
responseBody: text.slice(0, 500)
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
let parsed;
|
|
75
|
+
try {
|
|
76
|
+
parsed = JSON.parse(text);
|
|
77
|
+
}
|
|
78
|
+
catch (error) {
|
|
79
|
+
throw new ArchipelagoTransportError("Failed to parse JSON response", {
|
|
80
|
+
statusCode,
|
|
81
|
+
responseBody: text.slice(0, 500),
|
|
82
|
+
cause: error
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
const result = parseIslandResponse(parsed);
|
|
86
|
+
if (result.status === "redirect") {
|
|
87
|
+
navigate(result.location);
|
|
88
|
+
}
|
|
89
|
+
return result;
|
|
90
|
+
}
|
|
26
91
|
export async function islandFetch(component, operation, payload = {}, options = {}) {
|
|
27
|
-
const fetchImpl = options.fetchImpl ?? fetch;
|
|
28
92
|
const endpoint = options.endpoint ?? "/islands";
|
|
29
93
|
const mergedPayload = buildIslandPayload(payload, options.fixedParams, options.overridePayload);
|
|
30
94
|
const csrfToken = getCsrfToken();
|
|
95
|
+
const navigate = options.navigate ?? defaultNavigate;
|
|
31
96
|
const requestHeaders = {
|
|
32
97
|
"content-type": "application/json",
|
|
33
98
|
"x-requested-with": "XMLHttpRequest",
|
|
@@ -35,14 +100,32 @@ export async function islandFetch(component, operation, payload = {}, options =
|
|
|
35
100
|
...(options.stream ? { "x-archipelago-stream": options.stream } : {}),
|
|
36
101
|
...(options.headers ?? {})
|
|
37
102
|
};
|
|
103
|
+
const url = `${endpoint}/${encodeURIComponent(component)}/${encodeURIComponent(operation)}`;
|
|
104
|
+
const body = JSON.stringify(mergedPayload);
|
|
105
|
+
if (options.onUploadProgress) {
|
|
106
|
+
const xhrResult = await xhrFetch(url, requestHeaders, body, options.signal, options.onUploadProgress);
|
|
107
|
+
if (xhrResult.status === 422) {
|
|
108
|
+
clearCsrfCache();
|
|
109
|
+
}
|
|
110
|
+
const contentLength = xhrResult.getHeader("content-length");
|
|
111
|
+
const hasBody = contentLength == null || contentLength !== "0";
|
|
112
|
+
if (xhrResult.status === 403 && !hasBody) {
|
|
113
|
+
return { status: "forbidden" };
|
|
114
|
+
}
|
|
115
|
+
if (!hasBody) {
|
|
116
|
+
return { status: "ok", props: {}, version: Date.now() };
|
|
117
|
+
}
|
|
118
|
+
return parseResponseText(xhrResult.text, xhrResult.status, navigate);
|
|
119
|
+
}
|
|
120
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
38
121
|
let response;
|
|
39
122
|
try {
|
|
40
|
-
response = await fetchImpl(
|
|
123
|
+
response = await fetchImpl(url, {
|
|
41
124
|
method: "POST",
|
|
42
125
|
signal: options.signal,
|
|
43
126
|
credentials: "same-origin",
|
|
44
127
|
headers: requestHeaders,
|
|
45
|
-
body
|
|
128
|
+
body
|
|
46
129
|
});
|
|
47
130
|
}
|
|
48
131
|
catch (error) {
|
|
@@ -67,31 +150,6 @@ export async function islandFetch(component, operation, payload = {}, options =
|
|
|
67
150
|
cause: error
|
|
68
151
|
});
|
|
69
152
|
}
|
|
70
|
-
|
|
71
|
-
return { status: "ok", props: {}, version: Date.now() };
|
|
72
|
-
}
|
|
73
|
-
if (looksLikeHtml(text)) {
|
|
74
|
-
throw new ArchipelagoTransportError("Received HTML instead of JSON", {
|
|
75
|
-
statusCode: response.status,
|
|
76
|
-
responseBody: text.slice(0, 500)
|
|
77
|
-
});
|
|
78
|
-
}
|
|
79
|
-
let parsed;
|
|
80
|
-
try {
|
|
81
|
-
parsed = JSON.parse(text);
|
|
82
|
-
}
|
|
83
|
-
catch (error) {
|
|
84
|
-
throw new ArchipelagoTransportError("Failed to parse JSON response", {
|
|
85
|
-
statusCode: response.status,
|
|
86
|
-
responseBody: text.slice(0, 500),
|
|
87
|
-
cause: error
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
const result = parseIslandResponse(parsed);
|
|
91
|
-
if (result.status === "redirect") {
|
|
92
|
-
const navigate = options.navigate ?? defaultNavigate;
|
|
93
|
-
navigate(result.location);
|
|
94
|
-
}
|
|
95
|
-
return result;
|
|
153
|
+
return parseResponseText(text, response.status, navigate);
|
|
96
154
|
}
|
|
97
155
|
//# sourceMappingURL=fetch.js.map
|
package/dist/fetch.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["../src/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AACrD,OAAO,EACL,yBAAyB,EAEzB,mBAAmB,EACpB,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["../src/fetch.ts"],"names":[],"mappings":"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"}
|