@archipelago-js/client 0.1.0 → 0.2.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/dist/fetch.d.ts +1 -0
- package/dist/fetch.js +56 -19
- package/dist/fetch.js.map +1 -1
- package/dist/types.d.ts +12 -1
- package/dist/types.js +17 -9
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
package/dist/fetch.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export type IslandFetchOptions = {
|
|
|
7
7
|
signal?: AbortSignal;
|
|
8
8
|
fetchImpl?: typeof fetch;
|
|
9
9
|
navigate?: (location: string) => void;
|
|
10
|
+
stream?: string;
|
|
10
11
|
};
|
|
11
12
|
export type IslandFetchPayload = Record<string, unknown>;
|
|
12
13
|
export declare function buildIslandPayload(payload?: IslandFetchPayload, fixedParams?: Record<string, unknown>, overridePayload?: Record<string, unknown>): Record<string, unknown>;
|
package/dist/fetch.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { clearCsrfCache, getCsrfToken } from "./csrf";
|
|
2
|
-
import { parseIslandResponse } from "./types";
|
|
2
|
+
import { ArchipelagoTransportError, parseIslandResponse } from "./types";
|
|
3
3
|
function defaultNavigate(location) {
|
|
4
4
|
const turbo = window.Turbo;
|
|
5
5
|
if (turbo?.visit) {
|
|
@@ -12,6 +12,10 @@ function hasContent(response) {
|
|
|
12
12
|
const contentLength = response.headers.get("content-length");
|
|
13
13
|
return contentLength == null || contentLength !== "0";
|
|
14
14
|
}
|
|
15
|
+
function looksLikeHtml(text) {
|
|
16
|
+
const trimmed = text.trimStart();
|
|
17
|
+
return trimmed.startsWith("<!") || trimmed.startsWith("<html") || trimmed.startsWith("<HTML");
|
|
18
|
+
}
|
|
15
19
|
export function buildIslandPayload(payload = {}, fixedParams = {}, overridePayload = {}) {
|
|
16
20
|
return {
|
|
17
21
|
...fixedParams,
|
|
@@ -24,20 +28,27 @@ export async function islandFetch(component, operation, payload = {}, options =
|
|
|
24
28
|
const endpoint = options.endpoint ?? "/islands";
|
|
25
29
|
const mergedPayload = buildIslandPayload(payload, options.fixedParams, options.overridePayload);
|
|
26
30
|
const csrfToken = getCsrfToken();
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
const requestHeaders = {
|
|
32
|
+
"content-type": "application/json",
|
|
33
|
+
"x-requested-with": "XMLHttpRequest",
|
|
34
|
+
...(csrfToken ? { "x-csrf-token": csrfToken } : {}),
|
|
35
|
+
...(options.stream ? { "x-archipelago-stream": options.stream } : {}),
|
|
36
|
+
...(options.headers ?? {})
|
|
37
|
+
};
|
|
38
|
+
let response;
|
|
39
|
+
try {
|
|
40
|
+
response = await fetchImpl(`${endpoint}/${encodeURIComponent(component)}/${encodeURIComponent(operation)}`, {
|
|
41
|
+
method: "POST",
|
|
42
|
+
signal: options.signal,
|
|
43
|
+
credentials: "same-origin",
|
|
44
|
+
headers: requestHeaders,
|
|
45
|
+
body: JSON.stringify(mergedPayload)
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
catch (error) {
|
|
49
|
+
throw new ArchipelagoTransportError("Network request failed", { cause: error });
|
|
50
|
+
}
|
|
39
51
|
if (response.status === 422) {
|
|
40
|
-
// Rails may rotate CSRF token; force re-read on next request.
|
|
41
52
|
clearCsrfCache();
|
|
42
53
|
}
|
|
43
54
|
if (response.status === 403 && !hasContent(response)) {
|
|
@@ -46,15 +57,41 @@ export async function islandFetch(component, operation, payload = {}, options =
|
|
|
46
57
|
if (!hasContent(response)) {
|
|
47
58
|
return { status: "ok", props: {}, version: Date.now() };
|
|
48
59
|
}
|
|
49
|
-
|
|
60
|
+
let text;
|
|
61
|
+
try {
|
|
62
|
+
text = await response.text();
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
throw new ArchipelagoTransportError("Failed to read response body", {
|
|
66
|
+
statusCode: response.status,
|
|
67
|
+
cause: error
|
|
68
|
+
});
|
|
69
|
+
}
|
|
50
70
|
if (text.trim().length === 0) {
|
|
51
71
|
return { status: "ok", props: {}, version: Date.now() };
|
|
52
72
|
}
|
|
53
|
-
|
|
54
|
-
|
|
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") {
|
|
55
92
|
const navigate = options.navigate ?? defaultNavigate;
|
|
56
|
-
navigate(
|
|
93
|
+
navigate(result.location);
|
|
57
94
|
}
|
|
58
|
-
return
|
|
95
|
+
return result;
|
|
59
96
|
}
|
|
60
97
|
//# 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,
|
|
1
|
+
{"version":3,"file":"fetch.js","sourceRoot":"","sources":["../src/fetch.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
export type IslandProps = Record<string, unknown>;
|
|
2
|
+
export declare const FORM_ERROR: "_base";
|
|
3
|
+
export declare class ArchipelagoTransportError extends Error {
|
|
4
|
+
readonly statusCode: number | undefined;
|
|
5
|
+
readonly responseBody: string | undefined;
|
|
6
|
+
constructor(message: string, options?: {
|
|
7
|
+
statusCode?: number;
|
|
8
|
+
responseBody?: string;
|
|
9
|
+
cause?: unknown;
|
|
10
|
+
});
|
|
11
|
+
}
|
|
2
12
|
export type IslandOkResponse = {
|
|
3
13
|
status: "ok";
|
|
4
14
|
props: IslandProps;
|
|
5
|
-
version
|
|
15
|
+
version: number;
|
|
6
16
|
};
|
|
7
17
|
export type IslandRedirectResponse = {
|
|
8
18
|
status: "redirect";
|
|
@@ -16,4 +26,5 @@ export type IslandForbiddenResponse = {
|
|
|
16
26
|
status: "forbidden";
|
|
17
27
|
};
|
|
18
28
|
export type IslandResponse = IslandOkResponse | IslandRedirectResponse | IslandErrorResponse | IslandForbiddenResponse;
|
|
29
|
+
export type ArchipelagoResponse = IslandResponse;
|
|
19
30
|
export declare function parseIslandResponse(value: unknown): IslandResponse;
|
package/dist/types.js
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
export const FORM_ERROR = "_base";
|
|
2
|
+
export class ArchipelagoTransportError extends Error {
|
|
3
|
+
statusCode;
|
|
4
|
+
responseBody;
|
|
5
|
+
constructor(message, options) {
|
|
6
|
+
super(message, options?.cause ? { cause: options.cause } : undefined);
|
|
7
|
+
this.name = "ArchipelagoTransportError";
|
|
8
|
+
this.statusCode = options?.statusCode;
|
|
9
|
+
this.responseBody = options?.responseBody;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
1
12
|
function isRecord(value) {
|
|
2
13
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3
14
|
}
|
|
@@ -11,38 +22,35 @@ function isErrorMap(value) {
|
|
|
11
22
|
}
|
|
12
23
|
export function parseIslandResponse(value) {
|
|
13
24
|
if (!isRecord(value) || typeof value.status !== "string") {
|
|
14
|
-
throw new
|
|
25
|
+
throw new ArchipelagoTransportError("Invalid island response payload");
|
|
15
26
|
}
|
|
16
27
|
switch (value.status) {
|
|
17
28
|
case "ok": {
|
|
18
29
|
if (!isRecord(value.props)) {
|
|
19
|
-
throw new
|
|
20
|
-
}
|
|
21
|
-
if (value.version != null && typeof value.version !== "number") {
|
|
22
|
-
throw new Error("Invalid ok version");
|
|
30
|
+
throw new ArchipelagoTransportError("Invalid ok payload");
|
|
23
31
|
}
|
|
24
32
|
return {
|
|
25
33
|
status: "ok",
|
|
26
34
|
props: value.props,
|
|
27
|
-
version: typeof value.version === "number" ? value.version :
|
|
35
|
+
version: typeof value.version === "number" ? value.version : Date.now()
|
|
28
36
|
};
|
|
29
37
|
}
|
|
30
38
|
case "redirect": {
|
|
31
39
|
if (typeof value.location !== "string") {
|
|
32
|
-
throw new
|
|
40
|
+
throw new ArchipelagoTransportError("Invalid redirect payload");
|
|
33
41
|
}
|
|
34
42
|
return { status: "redirect", location: value.location };
|
|
35
43
|
}
|
|
36
44
|
case "error": {
|
|
37
45
|
if (!isErrorMap(value.errors)) {
|
|
38
|
-
throw new
|
|
46
|
+
throw new ArchipelagoTransportError("Invalid error payload");
|
|
39
47
|
}
|
|
40
48
|
return { status: "error", errors: value.errors };
|
|
41
49
|
}
|
|
42
50
|
case "forbidden":
|
|
43
51
|
return { status: "forbidden" };
|
|
44
52
|
default:
|
|
45
|
-
throw new
|
|
53
|
+
throw new ArchipelagoTransportError("Unknown island response status");
|
|
46
54
|
}
|
|
47
55
|
}
|
|
48
56
|
//# sourceMappingURL=types.js.map
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,UAAU,GAAG,OAAgB,CAAA;AAE1C,MAAM,OAAO,yBAA0B,SAAQ,KAAK;IAClC,UAAU,CAAoB;IAC9B,YAAY,CAAoB;IAEhD,YACE,OAAe,EACf,OAAyE;QAEzE,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAA;QACrE,IAAI,CAAC,IAAI,GAAG,2BAA2B,CAAA;QACvC,IAAI,CAAC,UAAU,GAAG,OAAO,EAAE,UAAU,CAAA;QACrC,IAAI,CAAC,YAAY,GAAG,OAAO,EAAE,YAAY,CAAA;IAC3C,CAAC;CACF;AA8BD,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;AAC7E,CAAC;AAED,SAAS,UAAU,CAAC,KAAc;IAChC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,KAAK,CAAA;IACd,CAAC;IAED,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,EAAE;QAC7C,OAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAA;IAC5F,CAAC,CAAC,CAAA;AACJ,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,KAAc;IAChD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACzD,MAAM,IAAI,yBAAyB,CAAC,iCAAiC,CAAC,CAAA;IACxE,CAAC;IAED,QAAQ,KAAK,CAAC,MAAM,EAAE,CAAC;QACrB,KAAK,IAAI,CAAC,CAAC,CAAC;YACV,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBAC3B,MAAM,IAAI,yBAAyB,CAAC,oBAAoB,CAAC,CAAA;YAC3D,CAAC;YAED,OAAO;gBACL,MAAM,EAAE,IAAI;gBACZ,KAAK,EAAE,KAAK,CAAC,KAAK;gBAClB,OAAO,EAAE,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE;aACxE,CAAA;QACH,CAAC;QACD,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,IAAI,OAAO,KAAK,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;gBACvC,MAAM,IAAI,yBAAyB,CAAC,0BAA0B,CAAC,CAAA;YACjE,CAAC;YAED,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,KAAK,CAAC,QAAQ,EAAE,CAAA;QACzD,CAAC;QACD,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC9B,MAAM,IAAI,yBAAyB,CAAC,uBAAuB,CAAC,CAAA;YAC9D,CAAC;YAED,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAA;QAClD,CAAC;QACD,KAAK,WAAW;YACd,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,CAAA;QAChC;YACE,MAAM,IAAI,yBAAyB,CAAC,gCAAgC,CAAC,CAAA;IACzE,CAAC;AACH,CAAC"}
|