@seam-rpc/client 1.1.1 → 2.0.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 +16 -0
- package/dist/index.js +78 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -142,3 +142,19 @@ export async function updateUser(userId: string, userData: UserData): Promise<vo
|
|
|
142
142
|
- The generated client files contain all imports from the api implementation file in the backend that import from the current relative folder (`./`). This is the simplest way I have to include imports (at least for now). It may import functions and unused symbols but that shouldn't be too worrying.
|
|
143
143
|
- Don't include backend/server functions inside the server api files.
|
|
144
144
|
- Only exported functions will be included in the client generated files.
|
|
145
|
+
|
|
146
|
+
## Supported types
|
|
147
|
+
SeamRPC supports the following types (at least for now):
|
|
148
|
+
- string
|
|
149
|
+
- number
|
|
150
|
+
- boolean
|
|
151
|
+
- array
|
|
152
|
+
- object
|
|
153
|
+
- null
|
|
154
|
+
- undefined
|
|
155
|
+
|
|
156
|
+
Classes are technically supported, in that the data is serialized to JSON.
|
|
157
|
+
|
|
158
|
+
Other JavaScript types are not supported, although SeamRPC doesn't prevent you from using them, in which case they might lead to unexpected beahviour or even errors.
|
|
159
|
+
|
|
160
|
+
The Date object type is not supported (at least for now). However, you can use `number` and pass `Date.now()` or `string` and pass `new Date().toString()`. This is not different than a normal HTTP request using JSON. SeamRPC also uses JSON behind the scenes, that's why there's these limitations, which could be overcome but I've decided not to because it would probably add more overhead to the logic.
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import { SeamFile, extractFiles, injectFiles } from "@seam-rpc/core";
|
|
2
|
+
export { SeamFile };
|
|
3
|
+
let apiUrl = null;
|
|
4
|
+
export function setApiUrl(url) {
|
|
5
|
+
apiUrl = url;
|
|
6
|
+
}
|
|
7
|
+
export async function callApi(routerName, funcName, args) {
|
|
8
|
+
if (!apiUrl)
|
|
9
|
+
throw new Error("Missing API URL");
|
|
10
|
+
let req;
|
|
11
|
+
const { json, files, paths } = extractFiles(args);
|
|
12
|
+
if (files.length > 0) {
|
|
13
|
+
const formData = new FormData();
|
|
14
|
+
formData.append("json", JSON.stringify(json));
|
|
15
|
+
formData.append("paths", JSON.stringify(paths));
|
|
16
|
+
for (let i = 0; i < files.length; i++) {
|
|
17
|
+
const file = files[i];
|
|
18
|
+
const blob = new Blob([new Uint8Array(file.data)], {
|
|
19
|
+
type: file.mimeType || "application/octet-stream",
|
|
20
|
+
});
|
|
21
|
+
formData.append(`file-${i}`, blob, file.fileName || `file-${i}`);
|
|
22
|
+
}
|
|
23
|
+
req = {
|
|
24
|
+
method: "POST",
|
|
25
|
+
body: formData,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
else {
|
|
29
|
+
req = {
|
|
30
|
+
method: "POST",
|
|
31
|
+
headers: {
|
|
32
|
+
"Content-Type": "application/json",
|
|
33
|
+
},
|
|
34
|
+
body: JSON.stringify(args),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
const url = `${apiUrl}/${routerName}/${funcName}`;
|
|
38
|
+
let res;
|
|
39
|
+
try {
|
|
40
|
+
res = await fetch(url, req);
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
console.log(url, req, err);
|
|
44
|
+
throw new Error("Failed to send request.\n" + err);
|
|
45
|
+
}
|
|
46
|
+
if (!res.ok) {
|
|
47
|
+
if (res.status == 400) {
|
|
48
|
+
const resError = await res.json();
|
|
49
|
+
throw new Error(resError.error);
|
|
50
|
+
}
|
|
51
|
+
throw new Error(`Request failed with status ${res.status} ${res.statusText}.`);
|
|
52
|
+
}
|
|
53
|
+
const contentType = res.headers.get("content-type") || "";
|
|
54
|
+
if (contentType.startsWith("application/json")) {
|
|
55
|
+
const data = await res.json();
|
|
56
|
+
return data.result;
|
|
57
|
+
}
|
|
58
|
+
else if (contentType.startsWith("multipart/form-data")) {
|
|
59
|
+
const formData = await res.formData();
|
|
60
|
+
const jsonPart = JSON.parse(formData.get("json")?.toString() || "[]");
|
|
61
|
+
const pathsPart = JSON.parse(formData.get("paths")?.toString() || "[]");
|
|
62
|
+
const responseFiles = [];
|
|
63
|
+
for (const [key, value] of formData.entries()) {
|
|
64
|
+
if (key.startsWith("file-")) {
|
|
65
|
+
const index = parseInt(key.replace("file-", ""));
|
|
66
|
+
const blob = value;
|
|
67
|
+
const arrayBuffer = await blob.arrayBuffer();
|
|
68
|
+
responseFiles.push({
|
|
69
|
+
path: pathsPart[index],
|
|
70
|
+
file: new SeamFile(new Uint8Array(arrayBuffer), blob.name, blob.type),
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
injectFiles(jsonPart, responseFiles);
|
|
75
|
+
return jsonPart.result;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// console.log(JSON.stringify(extractFiles(["John", new SeamFile(new Uint8Array([1, 2, 3, 4]))]), null, 4))
|