fullstacked 0.12.0-1169 → 0.12.0-1175
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/lib/archive/archive.ts +140 -0
- package/lib/archive/index.ts +4 -0
- package/lib/base64.ts +144 -0
- package/lib/bridge/index.ts +53 -0
- package/lib/bridge/platform/android.ts +18 -0
- package/lib/bridge/platform/apple.ts +46 -0
- package/lib/bridge/platform/electron.ts +14 -0
- package/lib/bridge/platform/linux-gtk.ts +48 -0
- package/lib/bridge/platform/linux-qt.ts +68 -0
- package/lib/bridge/platform/node.ts +32 -0
- package/lib/bridge/platform/wasm.ts +17 -0
- package/lib/bridge/platform/windows.ts +49 -0
- package/lib/bridge/serialization.ts +153 -0
- package/lib/components/snackbar.css +1 -0
- package/lib/components/snackbar.ts +60 -0
- package/lib/connect/index.ts +125 -0
- package/lib/core_message/core_message.ts +76 -0
- package/lib/core_message/index.ts +3 -0
- package/lib/fetch/index.ts +318 -0
- package/lib/fs/fs.ts +157 -0
- package/lib/fs/index.ts +3 -0
- package/lib/fullstacked.d.ts +208 -0
- package/lib/platform/index.ts +14 -0
- package/package.json +1 -1
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
import { bridge } from "../bridge";
|
|
2
|
+
import { serializeArgs } from "../bridge/serialization";
|
|
3
|
+
|
|
4
|
+
type FileEntries<T extends string | Uint8Array> = {
|
|
5
|
+
[filePath: string]: {
|
|
6
|
+
isDir: boolean;
|
|
7
|
+
contents: T;
|
|
8
|
+
};
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
function unzipDataToFileEntries(data: any[]): FileEntries<Uint8Array> {
|
|
12
|
+
const entries: FileEntries<Uint8Array> = {};
|
|
13
|
+
for (let i = 0; i < data.length; i = i + 3) {
|
|
14
|
+
entries[data[i]] = {
|
|
15
|
+
isDir: data[i + 1],
|
|
16
|
+
contents: data[i + 2]
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
return entries;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function unzip(
|
|
23
|
+
entry: string | Uint8Array
|
|
24
|
+
): Promise<FileEntries<Uint8Array>>;
|
|
25
|
+
export function unzip(
|
|
26
|
+
entry: string | Uint8Array,
|
|
27
|
+
out: string
|
|
28
|
+
): Promise<boolean>;
|
|
29
|
+
export function unzip(entry: string | Uint8Array, out?: string) {
|
|
30
|
+
let method: number;
|
|
31
|
+
let args: any[];
|
|
32
|
+
let transformer: (args: any) => any;
|
|
33
|
+
|
|
34
|
+
// BIN_TO
|
|
35
|
+
if (entry instanceof Uint8Array) {
|
|
36
|
+
// _FILE => 30
|
|
37
|
+
if (typeof out === "string") {
|
|
38
|
+
method = 30;
|
|
39
|
+
args = [entry, out];
|
|
40
|
+
transformer = ([success]) => success;
|
|
41
|
+
}
|
|
42
|
+
// _BIN => 31
|
|
43
|
+
else {
|
|
44
|
+
method = 31;
|
|
45
|
+
args = [entry];
|
|
46
|
+
transformer = (unzipData) => unzipDataToFileEntries(unzipData);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
// FILE_TO
|
|
50
|
+
else {
|
|
51
|
+
// _FILE => 32
|
|
52
|
+
if (typeof out === "string") {
|
|
53
|
+
method = 32;
|
|
54
|
+
args = [entry, out];
|
|
55
|
+
transformer = ([success]) => success;
|
|
56
|
+
}
|
|
57
|
+
// _BIN => 33
|
|
58
|
+
else {
|
|
59
|
+
method = 33;
|
|
60
|
+
args = [entry];
|
|
61
|
+
transformer = (unzipData) => unzipDataToFileEntries(unzipData);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const payload = new Uint8Array([method, ...serializeArgs(args)]);
|
|
66
|
+
return bridge(payload, transformer);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const te = new TextEncoder();
|
|
70
|
+
|
|
71
|
+
function fileEntriesToZipData(
|
|
72
|
+
entries: FileEntries<string | Uint8Array>
|
|
73
|
+
): any[] {
|
|
74
|
+
return Object.entries(entries)
|
|
75
|
+
.map(([name, { isDir, contents }]) => [
|
|
76
|
+
name,
|
|
77
|
+
isDir,
|
|
78
|
+
contents instanceof Uint8Array ? contents : te.encode(contents)
|
|
79
|
+
])
|
|
80
|
+
.flat();
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function zip(
|
|
84
|
+
entry: FileEntries<string | Uint8Array>
|
|
85
|
+
): Promise<Uint8Array>;
|
|
86
|
+
export function zip(
|
|
87
|
+
entry: string,
|
|
88
|
+
out?: null | undefined,
|
|
89
|
+
skip?: string[]
|
|
90
|
+
): Promise<Uint8Array>;
|
|
91
|
+
export function zip(
|
|
92
|
+
entry: FileEntries<string | Uint8Array> | string,
|
|
93
|
+
out: string,
|
|
94
|
+
skip?: string[]
|
|
95
|
+
): Promise<boolean>;
|
|
96
|
+
export function zip(
|
|
97
|
+
entry: FileEntries<string | Uint8Array> | string,
|
|
98
|
+
out?: string,
|
|
99
|
+
skip?: string[]
|
|
100
|
+
) {
|
|
101
|
+
let method: number;
|
|
102
|
+
let args: any[];
|
|
103
|
+
let transformer: (args: any) => any;
|
|
104
|
+
|
|
105
|
+
// BIN_TO
|
|
106
|
+
if (typeof entry === "object") {
|
|
107
|
+
// _FILE => 34
|
|
108
|
+
if (typeof out === "string") {
|
|
109
|
+
method = 34;
|
|
110
|
+
args = fileEntriesToZipData(entry);
|
|
111
|
+
args.unshift(out);
|
|
112
|
+
transformer = ([success]) => success;
|
|
113
|
+
}
|
|
114
|
+
// _BIN => 35
|
|
115
|
+
else {
|
|
116
|
+
method = 35;
|
|
117
|
+
args = fileEntriesToZipData(entry);
|
|
118
|
+
transformer = ([zipData]) => zipData;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// FILE_TO
|
|
122
|
+
else {
|
|
123
|
+
// _FILE => 36
|
|
124
|
+
if (typeof out === "string") {
|
|
125
|
+
method = 36;
|
|
126
|
+
args = [entry, out, ...(skip || [])];
|
|
127
|
+
transformer = ([success]) => success;
|
|
128
|
+
}
|
|
129
|
+
// _BIN => 37
|
|
130
|
+
else {
|
|
131
|
+
method = 37;
|
|
132
|
+
args = [entry, ...(skip || [])];
|
|
133
|
+
transformer = ([zipData]) => zipData;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
const payload = new Uint8Array([method, ...serializeArgs(args)]);
|
|
138
|
+
|
|
139
|
+
return bridge(payload, transformer);
|
|
140
|
+
}
|
package/lib/base64.ts
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// source : https://github.com/beatgammit/base64-js/tree/master
|
|
2
|
+
const lookup = [];
|
|
3
|
+
const revLookup = [];
|
|
4
|
+
|
|
5
|
+
var code = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
|
6
|
+
for (let i = 0, len = code.length; i < len; ++i) {
|
|
7
|
+
lookup[i] = code[i];
|
|
8
|
+
revLookup[code.charCodeAt(i)] = i;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
// Support decoding URL-safe base64 strings, as Node.js does.
|
|
12
|
+
// See: https://en.wikipedia.org/wiki/Base64#URL_applications
|
|
13
|
+
revLookup["-".charCodeAt(0)] = 62;
|
|
14
|
+
revLookup["_".charCodeAt(0)] = 63;
|
|
15
|
+
|
|
16
|
+
function getLens(b64) {
|
|
17
|
+
var len = b64.length;
|
|
18
|
+
|
|
19
|
+
// if (len % 4 > 0) {
|
|
20
|
+
// throw new Error("Invalid string. Length must be a multiple of 4");
|
|
21
|
+
// }
|
|
22
|
+
|
|
23
|
+
// Trim off extra bytes after placeholder bytes are found
|
|
24
|
+
// See: https://github.com/beatgammit/base64-js/issues/42
|
|
25
|
+
var validLen = b64.indexOf("=");
|
|
26
|
+
if (validLen === -1) validLen = len;
|
|
27
|
+
|
|
28
|
+
var placeHoldersLen = validLen === len ? 0 : 4 - (validLen % 4);
|
|
29
|
+
|
|
30
|
+
return [validLen, placeHoldersLen];
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// base64 is 4/3 + up to two characters of the original data
|
|
34
|
+
function byteLength(b64) {
|
|
35
|
+
var lens = getLens(b64);
|
|
36
|
+
var validLen = lens[0];
|
|
37
|
+
var placeHoldersLen = lens[1];
|
|
38
|
+
return ((validLen + placeHoldersLen) * 3) / 4 - placeHoldersLen;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function _byteLength(b64, validLen, placeHoldersLen) {
|
|
42
|
+
return ((validLen + placeHoldersLen) * 3) / 4 - placeHoldersLen;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export function toByteArray(b64: string) {
|
|
46
|
+
let tmp: any;
|
|
47
|
+
const lens = getLens(b64);
|
|
48
|
+
const validLen = lens[0];
|
|
49
|
+
const placeHoldersLen = lens[1];
|
|
50
|
+
|
|
51
|
+
const arr = new Uint8Array(_byteLength(b64, validLen, placeHoldersLen));
|
|
52
|
+
|
|
53
|
+
let curByte = 0;
|
|
54
|
+
|
|
55
|
+
// if there are placeholders, only get up to the last complete 4 chars
|
|
56
|
+
const len = placeHoldersLen > 0 ? validLen - 4 : validLen;
|
|
57
|
+
|
|
58
|
+
let i: number;
|
|
59
|
+
for (i = 0; i < len; i += 4) {
|
|
60
|
+
tmp =
|
|
61
|
+
(revLookup[b64.charCodeAt(i)] << 18) |
|
|
62
|
+
(revLookup[b64.charCodeAt(i + 1)] << 12) |
|
|
63
|
+
(revLookup[b64.charCodeAt(i + 2)] << 6) |
|
|
64
|
+
revLookup[b64.charCodeAt(i + 3)];
|
|
65
|
+
arr[curByte++] = (tmp >> 16) & 0xff;
|
|
66
|
+
arr[curByte++] = (tmp >> 8) & 0xff;
|
|
67
|
+
arr[curByte++] = tmp & 0xff;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (placeHoldersLen === 2) {
|
|
71
|
+
tmp =
|
|
72
|
+
(revLookup[b64.charCodeAt(i)] << 2) |
|
|
73
|
+
(revLookup[b64.charCodeAt(i + 1)] >> 4);
|
|
74
|
+
arr[curByte++] = tmp & 0xff;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (placeHoldersLen === 1) {
|
|
78
|
+
tmp =
|
|
79
|
+
(revLookup[b64.charCodeAt(i)] << 10) |
|
|
80
|
+
(revLookup[b64.charCodeAt(i + 1)] << 4) |
|
|
81
|
+
(revLookup[b64.charCodeAt(i + 2)] >> 2);
|
|
82
|
+
arr[curByte++] = (tmp >> 8) & 0xff;
|
|
83
|
+
arr[curByte++] = tmp & 0xff;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return arr;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function tripletToBase64(num) {
|
|
90
|
+
return (
|
|
91
|
+
lookup[(num >> 18) & 0x3f] +
|
|
92
|
+
lookup[(num >> 12) & 0x3f] +
|
|
93
|
+
lookup[(num >> 6) & 0x3f] +
|
|
94
|
+
lookup[num & 0x3f]
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function encodeChunk(uint8, start, end) {
|
|
99
|
+
var tmp;
|
|
100
|
+
var output = [];
|
|
101
|
+
for (var i = start; i < end; i += 3) {
|
|
102
|
+
tmp =
|
|
103
|
+
((uint8[i] << 16) & 0xff0000) +
|
|
104
|
+
((uint8[i + 1] << 8) & 0xff00) +
|
|
105
|
+
(uint8[i + 2] & 0xff);
|
|
106
|
+
output.push(tripletToBase64(tmp));
|
|
107
|
+
}
|
|
108
|
+
return output.join("");
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function fromByteArray(uint8: Uint8Array) {
|
|
112
|
+
let tmp;
|
|
113
|
+
const len = uint8.length;
|
|
114
|
+
const extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes
|
|
115
|
+
const parts = [];
|
|
116
|
+
const maxChunkLength = 16383; // must be multiple of 3
|
|
117
|
+
|
|
118
|
+
// go through the array every three bytes, we'll deal with trailing stuff later
|
|
119
|
+
for (let i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) {
|
|
120
|
+
parts.push(
|
|
121
|
+
encodeChunk(
|
|
122
|
+
uint8,
|
|
123
|
+
i,
|
|
124
|
+
i + maxChunkLength > len2 ? len2 : i + maxChunkLength
|
|
125
|
+
)
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// pad the end with zeros, but make sure to not forget the extra bytes
|
|
130
|
+
if (extraBytes === 1) {
|
|
131
|
+
tmp = uint8[len - 1];
|
|
132
|
+
parts.push(lookup[tmp >> 2] + lookup[(tmp << 4) & 0x3f] + "==");
|
|
133
|
+
} else if (extraBytes === 2) {
|
|
134
|
+
tmp = (uint8[len - 2] << 8) + uint8[len - 1];
|
|
135
|
+
parts.push(
|
|
136
|
+
lookup[tmp >> 10] +
|
|
137
|
+
lookup[(tmp >> 4) & 0x3f] +
|
|
138
|
+
lookup[(tmp << 2) & 0x3f] +
|
|
139
|
+
"="
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return parts.join("");
|
|
144
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import "../core_message";
|
|
2
|
+
import platform, { Platform } from "../platform";
|
|
3
|
+
import { BridgeAndroid } from "./platform/android";
|
|
4
|
+
import { BridgeApple, initRespondApple } from "./platform/apple";
|
|
5
|
+
import { BridgeLinuxGTK, initRespondLinuxGTK } from "./platform/linux-gtk";
|
|
6
|
+
import { BridgeLinuxQT, initRespondLinuxQT } from "./platform/linux-qt";
|
|
7
|
+
import { BridgeElectron } from "./platform/electron";
|
|
8
|
+
import { BridgeNode, initCallbackNode } from "./platform/node";
|
|
9
|
+
import { BridgeWasm } from "./platform/wasm";
|
|
10
|
+
import { BridgeWindows, initRespondWindows } from "./platform/windows";
|
|
11
|
+
|
|
12
|
+
export type Bridge = (
|
|
13
|
+
payload: Uint8Array,
|
|
14
|
+
transformer?: (args: any) => any
|
|
15
|
+
) => Promise<any>;
|
|
16
|
+
|
|
17
|
+
export let bridge: Bridge;
|
|
18
|
+
switch (platform) {
|
|
19
|
+
case Platform.NODE:
|
|
20
|
+
bridge = BridgeNode;
|
|
21
|
+
initCallbackNode();
|
|
22
|
+
break;
|
|
23
|
+
case Platform.APPLE:
|
|
24
|
+
bridge = BridgeApple;
|
|
25
|
+
initRespondApple();
|
|
26
|
+
break;
|
|
27
|
+
case Platform.ANDROID:
|
|
28
|
+
bridge = BridgeAndroid;
|
|
29
|
+
break;
|
|
30
|
+
case Platform.WASM:
|
|
31
|
+
bridge = BridgeWasm;
|
|
32
|
+
break;
|
|
33
|
+
case Platform.WINDOWS:
|
|
34
|
+
bridge = BridgeWindows;
|
|
35
|
+
initRespondWindows();
|
|
36
|
+
break;
|
|
37
|
+
case Platform.LINUX_GTK:
|
|
38
|
+
bridge = BridgeLinuxGTK;
|
|
39
|
+
initRespondLinuxGTK();
|
|
40
|
+
break;
|
|
41
|
+
case Platform.LINUX_QT:
|
|
42
|
+
bridge = BridgeLinuxQT;
|
|
43
|
+
initRespondLinuxQT();
|
|
44
|
+
break;
|
|
45
|
+
case Platform.ELECTRON:
|
|
46
|
+
bridge = BridgeElectron;
|
|
47
|
+
break;
|
|
48
|
+
case Platform.DOCKER:
|
|
49
|
+
console.log("Bridge not yet implemented");
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
console.log("FullStacked");
|
|
53
|
+
bridge(new Uint8Array([0]));
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Bridge } from "..";
|
|
2
|
+
import { fromByteArray, toByteArray } from "../../base64";
|
|
3
|
+
import { deserializeArgs } from "../serialization";
|
|
4
|
+
|
|
5
|
+
export const BridgeAndroid: Bridge = async (
|
|
6
|
+
payload: Uint8Array,
|
|
7
|
+
transformer?: (responseArgs: any[]) => any
|
|
8
|
+
) => {
|
|
9
|
+
const base64 = fromByteArray(payload);
|
|
10
|
+
const response = toByteArray(globalThis.android.bridge(base64));
|
|
11
|
+
const args = deserializeArgs(response);
|
|
12
|
+
|
|
13
|
+
if (transformer) {
|
|
14
|
+
return transformer(args);
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return args;
|
|
18
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { Bridge } from "..";
|
|
2
|
+
import { fromByteArray, toByteArray } from "../../base64";
|
|
3
|
+
import {
|
|
4
|
+
bytesToNumber,
|
|
5
|
+
deserializeArgs,
|
|
6
|
+
getLowestKeyIdAvailable,
|
|
7
|
+
numberTo4Bytes
|
|
8
|
+
} from "../serialization";
|
|
9
|
+
|
|
10
|
+
const requests = new Map<number, (data: Uint8Array) => void>();
|
|
11
|
+
|
|
12
|
+
export const BridgeApple: Bridge = (
|
|
13
|
+
payload: Uint8Array,
|
|
14
|
+
transformer?: (responseArgs: any[]) => any
|
|
15
|
+
) => {
|
|
16
|
+
const requestId = getLowestKeyIdAvailable(requests);
|
|
17
|
+
|
|
18
|
+
const base64 = fromByteArray(
|
|
19
|
+
new Uint8Array([...numberTo4Bytes(requestId), ...payload])
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
requests.set(requestId, (data) => {
|
|
24
|
+
try {
|
|
25
|
+
const args = deserializeArgs(data);
|
|
26
|
+
if (transformer) {
|
|
27
|
+
return resolve(transformer(args));
|
|
28
|
+
}
|
|
29
|
+
resolve(args);
|
|
30
|
+
} catch (e) {
|
|
31
|
+
reject(e);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
globalThis.webkit.messageHandlers.bridge.postMessage(base64);
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export function initRespondApple() {
|
|
39
|
+
globalThis.respond = (base64: string) => {
|
|
40
|
+
const data = toByteArray(base64);
|
|
41
|
+
const id = bytesToNumber(data.slice(0, 4));
|
|
42
|
+
const resolver = requests.get(id);
|
|
43
|
+
resolver(data.slice(4));
|
|
44
|
+
requests.delete(id);
|
|
45
|
+
};
|
|
46
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Bridge } from "..";
|
|
2
|
+
import { deserializeArgs } from "../serialization";
|
|
3
|
+
|
|
4
|
+
export const BridgeElectron: Bridge = async (
|
|
5
|
+
payload: Uint8Array,
|
|
6
|
+
transformer?: (responseArgs: any[]) => any
|
|
7
|
+
) => {
|
|
8
|
+
const response = await (window as any).electronAPI.bridge(payload);
|
|
9
|
+
const args = deserializeArgs(response);
|
|
10
|
+
if (transformer) {
|
|
11
|
+
return transformer(args);
|
|
12
|
+
}
|
|
13
|
+
return args;
|
|
14
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { Bridge } from "..";
|
|
2
|
+
import { fromByteArray, toByteArray } from "../../base64";
|
|
3
|
+
import {
|
|
4
|
+
bytesToNumber,
|
|
5
|
+
deserializeArgs,
|
|
6
|
+
getLowestKeyIdAvailable,
|
|
7
|
+
numberTo4Bytes
|
|
8
|
+
} from "../serialization";
|
|
9
|
+
|
|
10
|
+
const requests = new Map<number, (data: Uint8Array) => void>();
|
|
11
|
+
|
|
12
|
+
export const BridgeLinuxGTK: Bridge = (
|
|
13
|
+
payload: Uint8Array,
|
|
14
|
+
transformer?: (responseArgs: any[]) => any
|
|
15
|
+
) => {
|
|
16
|
+
const requestId = getLowestKeyIdAvailable(requests);
|
|
17
|
+
|
|
18
|
+
const base64 = fromByteArray(
|
|
19
|
+
new Uint8Array([...numberTo4Bytes(requestId), ...payload])
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
requests.set(requestId, (data) => {
|
|
24
|
+
try {
|
|
25
|
+
const args = deserializeArgs(data);
|
|
26
|
+
if (transformer) {
|
|
27
|
+
return resolve(transformer(args));
|
|
28
|
+
}
|
|
29
|
+
resolve(args);
|
|
30
|
+
} catch (e) {
|
|
31
|
+
reject(e);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
34
|
+
globalThis.webkit.messageHandlers.bridge.postMessage(base64);
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export function initRespondLinuxGTK() {
|
|
39
|
+
globalThis.respond = (base64: string) => {
|
|
40
|
+
console.log(base64);
|
|
41
|
+
const data = toByteArray(base64);
|
|
42
|
+
const id = bytesToNumber(data.slice(0, 4));
|
|
43
|
+
console.log(id);
|
|
44
|
+
const resolver = requests.get(id);
|
|
45
|
+
resolver(data.slice(4));
|
|
46
|
+
requests.delete(id);
|
|
47
|
+
};
|
|
48
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { Bridge } from "..";
|
|
2
|
+
import { fromByteArray, toByteArray } from "../../base64";
|
|
3
|
+
import {
|
|
4
|
+
bytesToNumber,
|
|
5
|
+
deserializeArgs,
|
|
6
|
+
getLowestKeyIdAvailable,
|
|
7
|
+
numberTo4Bytes
|
|
8
|
+
} from "../serialization";
|
|
9
|
+
|
|
10
|
+
const pendingRequests: {
|
|
11
|
+
payload: Uint8Array;
|
|
12
|
+
transformer: (responseArgs: any[]) => any;
|
|
13
|
+
resolve: (args: any) => void;
|
|
14
|
+
}[] = [];
|
|
15
|
+
let channel: any;
|
|
16
|
+
|
|
17
|
+
async function respond(
|
|
18
|
+
payload: Uint8Array,
|
|
19
|
+
transformer?: (responseArgs: any[]) => any
|
|
20
|
+
) {
|
|
21
|
+
const payloadStr = fromByteArray(new Uint8Array([0, 0, 0, 0, ...payload]));
|
|
22
|
+
|
|
23
|
+
const response = await channel.objects.bridge.call(payloadStr);
|
|
24
|
+
const data = toByteArray(response);
|
|
25
|
+
const args = deserializeArgs(data.slice(4));
|
|
26
|
+
|
|
27
|
+
if (transformer) {
|
|
28
|
+
return transformer(args);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return args;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const BridgeLinuxQT: Bridge = (
|
|
35
|
+
payload: Uint8Array,
|
|
36
|
+
transformer?: (responseArgs: any[]) => any
|
|
37
|
+
) => {
|
|
38
|
+
if (!channel) {
|
|
39
|
+
return new Promise((resolve) => {
|
|
40
|
+
pendingRequests.push({
|
|
41
|
+
payload,
|
|
42
|
+
transformer,
|
|
43
|
+
resolve
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return respond(payload, transformer);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export async function initRespondLinuxQT() {
|
|
52
|
+
const script = document.createElement("script");
|
|
53
|
+
script.src = "qrc:///qtwebchannel/qwebchannel.js";
|
|
54
|
+
script.onload = () => {
|
|
55
|
+
new globalThis.QWebChannel(globalThis.qt.webChannelTransport, (c) => {
|
|
56
|
+
channel = c;
|
|
57
|
+
pendingRequests.forEach(({ payload, transformer, resolve }) => {
|
|
58
|
+
respond(payload, transformer).then(resolve);
|
|
59
|
+
});
|
|
60
|
+
channel.objects.bridge.core_message.connect(
|
|
61
|
+
function (type, message) {
|
|
62
|
+
globalThis.oncoremessage(type, message);
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
});
|
|
66
|
+
};
|
|
67
|
+
document.body.append(script);
|
|
68
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { Bridge } from "..";
|
|
2
|
+
import { deserializeArgs } from "../serialization";
|
|
3
|
+
|
|
4
|
+
const bridge = globalThis.fetch;
|
|
5
|
+
|
|
6
|
+
export const BridgeNode: Bridge = async (
|
|
7
|
+
payload: Uint8Array,
|
|
8
|
+
transformer?: (responseArgs: any[]) => any
|
|
9
|
+
) => {
|
|
10
|
+
const response = await bridge("/call", {
|
|
11
|
+
method: "POST",
|
|
12
|
+
body: payload
|
|
13
|
+
});
|
|
14
|
+
const data = new Uint8Array(await response.arrayBuffer());
|
|
15
|
+
const args = deserializeArgs(data);
|
|
16
|
+
|
|
17
|
+
if (transformer) {
|
|
18
|
+
return transformer(args);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return args;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export function initCallbackNode() {
|
|
25
|
+
const url = new URL(globalThis.location.href);
|
|
26
|
+
url.protocol = "ws:";
|
|
27
|
+
const ws = new WebSocket(url.toString());
|
|
28
|
+
ws.onmessage = (e) => {
|
|
29
|
+
const [type, message] = JSON.parse(e.data);
|
|
30
|
+
globalThis.oncoremessage(type, message);
|
|
31
|
+
};
|
|
32
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Bridge } from "..";
|
|
2
|
+
import { toByteArray } from "../../base64";
|
|
3
|
+
import { deserializeArgs } from "../serialization";
|
|
4
|
+
|
|
5
|
+
export const BridgeWasm: Bridge = async (
|
|
6
|
+
payload: Uint8Array,
|
|
7
|
+
transformer?: (responseArgs: any[]) => any
|
|
8
|
+
) => {
|
|
9
|
+
const response = await globalThis.lib.call(payload);
|
|
10
|
+
const args = deserializeArgs(toByteArray(response));
|
|
11
|
+
|
|
12
|
+
if (transformer) {
|
|
13
|
+
return transformer(args);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
return args;
|
|
17
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Bridge } from "..";
|
|
2
|
+
import { fromByteArray, toByteArray } from "../../base64";
|
|
3
|
+
import {
|
|
4
|
+
bytesToNumber,
|
|
5
|
+
deserializeArgs,
|
|
6
|
+
getLowestKeyIdAvailable,
|
|
7
|
+
numberTo4Bytes
|
|
8
|
+
} from "../serialization";
|
|
9
|
+
|
|
10
|
+
const requests = new Map<number, (data: Uint8Array) => void>();
|
|
11
|
+
|
|
12
|
+
export const BridgeWindows: Bridge = (
|
|
13
|
+
payload: Uint8Array,
|
|
14
|
+
transformer?: (responseArgs: any[]) => any
|
|
15
|
+
) => {
|
|
16
|
+
const requestId = getLowestKeyIdAvailable(requests);
|
|
17
|
+
|
|
18
|
+
requests.set(requestId, null);
|
|
19
|
+
|
|
20
|
+
const base64 = fromByteArray(
|
|
21
|
+
new Uint8Array([...numberTo4Bytes(requestId), ...payload])
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
requests.set(requestId, (data) => {
|
|
26
|
+
try {
|
|
27
|
+
const args = deserializeArgs(data);
|
|
28
|
+
if (transformer) {
|
|
29
|
+
return resolve(transformer(args));
|
|
30
|
+
}
|
|
31
|
+
resolve(args);
|
|
32
|
+
} catch (e) {
|
|
33
|
+
reject(e);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
globalThis.chrome.webview.postMessage(base64);
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export function initRespondWindows() {
|
|
42
|
+
globalThis.respond = (base64: string) => {
|
|
43
|
+
const data = toByteArray(base64);
|
|
44
|
+
const id = bytesToNumber(data.slice(0, 4));
|
|
45
|
+
const resolver = requests.get(id);
|
|
46
|
+
resolver(data.slice(4));
|
|
47
|
+
requests.delete(id);
|
|
48
|
+
};
|
|
49
|
+
}
|