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.
@@ -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
+ }
@@ -0,0 +1,4 @@
1
+ import * as archive from "./archive";
2
+
3
+ export default archive;
4
+ export * from "./archive";
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
+ }