fullstacked 0.11.3-1148 → 0.12.0-1169
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/index.js +2 -2
- package/package.json +1 -1
- package/lib/archive/archive.ts +0 -140
- package/lib/archive/index.ts +0 -4
- package/lib/base64.ts +0 -144
- package/lib/bridge/index.ts +0 -53
- package/lib/bridge/platform/android.ts +0 -18
- package/lib/bridge/platform/apple.ts +0 -46
- package/lib/bridge/platform/electron.ts +0 -14
- package/lib/bridge/platform/linux-gtk.ts +0 -48
- package/lib/bridge/platform/linux-qt.ts +0 -68
- package/lib/bridge/platform/node.ts +0 -32
- package/lib/bridge/platform/wasm.ts +0 -17
- package/lib/bridge/platform/windows.ts +0 -49
- package/lib/bridge/serialization.ts +0 -153
- package/lib/components/snackbar.css +0 -1
- package/lib/components/snackbar.ts +0 -60
- package/lib/connect/index.ts +0 -125
- package/lib/core_message/core_message.ts +0 -76
- package/lib/core_message/index.ts +0 -3
- package/lib/fetch/index.ts +0 -318
- package/lib/fs/fs.ts +0 -157
- package/lib/fs/index.ts +0 -3
- package/lib/fullstacked.d.ts +0 -208
- package/lib/platform/index.ts +0 -14
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
const te = new TextEncoder();
|
|
2
|
-
const td = new TextDecoder();
|
|
3
|
-
|
|
4
|
-
export enum DataType {
|
|
5
|
-
UNDEFINED = 0,
|
|
6
|
-
BOOLEAN = 1,
|
|
7
|
-
STRING = 2,
|
|
8
|
-
NUMBER = 3,
|
|
9
|
-
BUFFER = 4,
|
|
10
|
-
ERROR = 5
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
function serializeNumber(n) {
|
|
14
|
-
const view = new DataView(new ArrayBuffer(8));
|
|
15
|
-
view.setFloat64(0, n);
|
|
16
|
-
return new Uint8Array(view.buffer);
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
function deserializeNumber(bytes: Uint8Array) {
|
|
20
|
-
const buffer = new ArrayBuffer(8);
|
|
21
|
-
new Uint8Array(buffer).set(bytes);
|
|
22
|
-
return new DataView(buffer).getFloat64(0);
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
export function numberTo4Bytes(n: number) {
|
|
26
|
-
const uint8Array = new Uint8Array(4);
|
|
27
|
-
uint8Array[0] = (n & 0xff000000) >> 24;
|
|
28
|
-
uint8Array[1] = (n & 0x00ff0000) >> 16;
|
|
29
|
-
uint8Array[2] = (n & 0x0000ff00) >> 8;
|
|
30
|
-
uint8Array[3] = (n & 0x000000ff) >> 0;
|
|
31
|
-
return uint8Array;
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
export function bytesToNumber(bytes: Uint8Array) {
|
|
35
|
-
return (
|
|
36
|
-
((bytes[0] << 24) |
|
|
37
|
-
(bytes[1] << 16) |
|
|
38
|
-
(bytes[2] << 8) |
|
|
39
|
-
(bytes[3] << 0)) >>>
|
|
40
|
-
0
|
|
41
|
-
);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/*
|
|
45
|
-
|
|
46
|
-
1 byte for type
|
|
47
|
-
4 bytes for length
|
|
48
|
-
n bytes for data
|
|
49
|
-
|
|
50
|
-
*/
|
|
51
|
-
|
|
52
|
-
export function serializeArgs(args: any[]) {
|
|
53
|
-
const parts = args.map((arg) => {
|
|
54
|
-
let data: Uint8Array, type: DataType;
|
|
55
|
-
if (typeof arg === "undefined" || arg === null) {
|
|
56
|
-
type = DataType.UNDEFINED;
|
|
57
|
-
data = new Uint8Array(0);
|
|
58
|
-
} else if (ArrayBuffer.isView(arg)) {
|
|
59
|
-
type = DataType.BUFFER;
|
|
60
|
-
data = new Uint8Array(arg.buffer);
|
|
61
|
-
} else if (typeof arg === "boolean") {
|
|
62
|
-
type = DataType.BOOLEAN;
|
|
63
|
-
data = new Uint8Array([arg ? 1 : 0]);
|
|
64
|
-
} else if (typeof arg === "string") {
|
|
65
|
-
type = DataType.STRING;
|
|
66
|
-
data = te.encode(arg);
|
|
67
|
-
} else if (typeof arg === "number") {
|
|
68
|
-
type = DataType.NUMBER;
|
|
69
|
-
data = serializeNumber(arg);
|
|
70
|
-
} else {
|
|
71
|
-
console.error("Using unknown type with IPC call");
|
|
72
|
-
return null;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
return new Uint8Array([
|
|
76
|
-
type,
|
|
77
|
-
...numberTo4Bytes(data.byteLength),
|
|
78
|
-
...data
|
|
79
|
-
]);
|
|
80
|
-
});
|
|
81
|
-
|
|
82
|
-
const totalLength = parts.reduce(
|
|
83
|
-
(total, part) => total + part.byteLength,
|
|
84
|
-
0
|
|
85
|
-
);
|
|
86
|
-
const data = new Uint8Array(totalLength);
|
|
87
|
-
parts.forEach((part, i) => {
|
|
88
|
-
const offset = parts
|
|
89
|
-
.slice(0, i)
|
|
90
|
-
.reduce((total, b) => total + b.byteLength, 0);
|
|
91
|
-
data.set(part, offset);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
return data;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export function deserializeArgs(data: Uint8Array) {
|
|
98
|
-
const args = [];
|
|
99
|
-
|
|
100
|
-
let cursor = 0;
|
|
101
|
-
while (cursor < data.byteLength) {
|
|
102
|
-
const type = data[cursor] as DataType;
|
|
103
|
-
cursor += 1;
|
|
104
|
-
const length = bytesToNumber(data.slice(cursor, cursor + 4));
|
|
105
|
-
cursor += 4;
|
|
106
|
-
const arg = data.slice(cursor, cursor + length);
|
|
107
|
-
cursor += length;
|
|
108
|
-
|
|
109
|
-
switch (type) {
|
|
110
|
-
case DataType.UNDEFINED:
|
|
111
|
-
args.push(undefined);
|
|
112
|
-
break;
|
|
113
|
-
case DataType.BOOLEAN:
|
|
114
|
-
args.push(arg.at(0) ? true : false);
|
|
115
|
-
break;
|
|
116
|
-
case DataType.STRING:
|
|
117
|
-
args.push(td.decode(arg));
|
|
118
|
-
break;
|
|
119
|
-
case DataType.NUMBER:
|
|
120
|
-
args.push(deserializeNumber(arg));
|
|
121
|
-
break;
|
|
122
|
-
case DataType.BUFFER:
|
|
123
|
-
args.push(arg);
|
|
124
|
-
break;
|
|
125
|
-
case DataType.ERROR:
|
|
126
|
-
throw td.decode(arg);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
return args;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
export function convertObjectToArray(obj: object) {
|
|
134
|
-
return Object.entries(obj).flat();
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
export function convertArrayToObject(arr: any[]) {
|
|
138
|
-
let obj = {};
|
|
139
|
-
for (let i = 0; i < arr.length; i += 2) {
|
|
140
|
-
obj[arr[i]] = arr[i + 1];
|
|
141
|
-
}
|
|
142
|
-
return obj;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
export function getLowestKeyIdAvailable(map: Map<number, any>) {
|
|
146
|
-
const currentIds = Array.from(map.keys()).sort((a, b) => a - b);
|
|
147
|
-
let requestId = 0;
|
|
148
|
-
for (const id of currentIds) {
|
|
149
|
-
if (requestId !== id) break;
|
|
150
|
-
requestId++;
|
|
151
|
-
}
|
|
152
|
-
return requestId;
|
|
153
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.snack-bars-container{display:flex;flex-direction:column;gap:10px;position:fixed;bottom:0;left:0;z-index:100;padding:0 20px 20px;align-items:flex-start;width:100%;pointer-events:none;text-align:left;font-family:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Oxygen,Ubuntu,Cantarell,"Open Sans","Helvetica Neue",sans-serif;font-size:16px;max-width:450px}@media(max-width: 450px){.snack-bars-container{align-items:center}}.snack-bars-container .snack-bar{pointer-events:all;background-color:#404958;border-radius:5px;color:#fff;min-height:42px;max-width:100%;width:max-content;display:flex;align-items:center;justify-content:space-between;gap:10px;padding:5px 10px;box-shadow:0px 4px 10px rgba(21,23,27,.6)}.snack-bars-container .snack-bar>div:first-child{padding:5px 0;width:100%;overflow-wrap:break-word}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
This file must follow the figma design
|
|
3
|
-
https://www.figma.com/design/xb3JBRCvEWpbwGda03T5QQ/Mockups?node-id=415-3655
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { Button } from "@fullstacked/ui";
|
|
7
|
-
|
|
8
|
-
type SnackBarOpt = {
|
|
9
|
-
message: string;
|
|
10
|
-
autoDismissTimeout?: number;
|
|
11
|
-
button?: ReturnType<typeof Button>;
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
let snackBarsContainer: HTMLDivElement;
|
|
15
|
-
|
|
16
|
-
export function SnackBar(opts: SnackBarOpt) {
|
|
17
|
-
if (!snackBarsContainer) {
|
|
18
|
-
snackBarsContainer = document.createElement("div");
|
|
19
|
-
snackBarsContainer.classList.add("snack-bars-container");
|
|
20
|
-
document.body.append(snackBarsContainer);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
const container = document.createElement("div");
|
|
24
|
-
container.classList.add("snack-bar");
|
|
25
|
-
|
|
26
|
-
const text = document.createElement("div");
|
|
27
|
-
text.innerHTML = opts.message;
|
|
28
|
-
container.append(text);
|
|
29
|
-
|
|
30
|
-
if (opts.button) {
|
|
31
|
-
container.append(opts.button);
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
container.style.transform = "translateY(100%)";
|
|
35
|
-
container.style.transition = "300ms transform";
|
|
36
|
-
snackBarsContainer.append(container);
|
|
37
|
-
setTimeout(() => (container.style.transform = "translateY(0%)"));
|
|
38
|
-
|
|
39
|
-
let timeout: ReturnType<typeof setTimeout>;
|
|
40
|
-
const dismiss = () => {
|
|
41
|
-
clearTimeout(timeout);
|
|
42
|
-
|
|
43
|
-
const animDuration = 500;
|
|
44
|
-
container.style.transition = `${animDuration}ms opacity`;
|
|
45
|
-
container.style.opacity = "0";
|
|
46
|
-
setTimeout(() => {
|
|
47
|
-
container.remove();
|
|
48
|
-
if (snackBarsContainer?.children.length === 0) {
|
|
49
|
-
snackBarsContainer.remove();
|
|
50
|
-
snackBarsContainer = null;
|
|
51
|
-
}
|
|
52
|
-
}, animDuration);
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
if (opts.autoDismissTimeout) {
|
|
56
|
-
setTimeout(dismiss, opts.autoDismissTimeout);
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return { dismiss };
|
|
60
|
-
}
|
package/lib/connect/index.ts
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import { bridge } from "../bridge";
|
|
2
|
-
import {
|
|
3
|
-
deserializeArgs,
|
|
4
|
-
numberTo4Bytes,
|
|
5
|
-
serializeArgs
|
|
6
|
-
} from "../bridge/serialization";
|
|
7
|
-
import core_message from "../core_message";
|
|
8
|
-
import { toByteArray } from "../base64";
|
|
9
|
-
|
|
10
|
-
export type Data = string | number | boolean | Uint8Array;
|
|
11
|
-
|
|
12
|
-
type DataChannelCallback = (data: Data[]) => void;
|
|
13
|
-
|
|
14
|
-
type DataChannel = {
|
|
15
|
-
send(...args: Data[]): void;
|
|
16
|
-
on(callback: DataChannelCallback): void;
|
|
17
|
-
off(callback: DataChannelCallback): void;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
type DataChannelRawCallback = (data: Uint8Array) => void;
|
|
21
|
-
|
|
22
|
-
type DataChannelRaw = {
|
|
23
|
-
send(buffer: Uint8Array): void;
|
|
24
|
-
on(callback: DataChannelRawCallback): void;
|
|
25
|
-
off(callback: DataChannelRawCallback): void;
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
type Channel = {
|
|
29
|
-
raw: false;
|
|
30
|
-
listeners: Set<DataChannelCallback>;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
type ChannelRaw = {
|
|
34
|
-
raw: true;
|
|
35
|
-
listeners: Set<DataChannelRawCallback>;
|
|
36
|
-
};
|
|
37
|
-
|
|
38
|
-
const channels = new Map<string, Channel | ChannelRaw>();
|
|
39
|
-
|
|
40
|
-
// 20
|
|
41
|
-
export function connect(
|
|
42
|
-
name: string,
|
|
43
|
-
port: number,
|
|
44
|
-
host?: string,
|
|
45
|
-
raw?: false
|
|
46
|
-
): Promise<DataChannel>;
|
|
47
|
-
export function connect(
|
|
48
|
-
name: string,
|
|
49
|
-
port: number,
|
|
50
|
-
host: string,
|
|
51
|
-
raw: true
|
|
52
|
-
): Promise<DataChannelRaw>;
|
|
53
|
-
export function connect(
|
|
54
|
-
name: string,
|
|
55
|
-
port: number,
|
|
56
|
-
host = "localhost",
|
|
57
|
-
raw = false
|
|
58
|
-
) {
|
|
59
|
-
const payload = new Uint8Array([
|
|
60
|
-
20,
|
|
61
|
-
...serializeArgs([name, port, host, raw])
|
|
62
|
-
]);
|
|
63
|
-
|
|
64
|
-
const transformer = ([channelId]) => {
|
|
65
|
-
if (raw) {
|
|
66
|
-
const listeners = new Set<DataChannelRawCallback>();
|
|
67
|
-
|
|
68
|
-
const channel: ChannelRaw = {
|
|
69
|
-
raw: true,
|
|
70
|
-
listeners
|
|
71
|
-
};
|
|
72
|
-
|
|
73
|
-
channels.set(channelId, channel);
|
|
74
|
-
|
|
75
|
-
core_message.addListener("channel-" + channelId, (dataStr) => {
|
|
76
|
-
const data = toByteArray(dataStr);
|
|
77
|
-
listeners.forEach((cb) => cb(data));
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
return {
|
|
81
|
-
send: (data) => send(channelId, data),
|
|
82
|
-
on: (cb) => listeners.add(cb),
|
|
83
|
-
off: (cb) => listeners.add(cb)
|
|
84
|
-
} as DataChannelRaw;
|
|
85
|
-
} else {
|
|
86
|
-
const listeners = new Set<DataChannelCallback>();
|
|
87
|
-
|
|
88
|
-
const channel: Channel = {
|
|
89
|
-
raw: false,
|
|
90
|
-
listeners
|
|
91
|
-
};
|
|
92
|
-
|
|
93
|
-
core_message.addListener("channel-" + channelId, (dataStr) => {
|
|
94
|
-
const data = toByteArray(dataStr);
|
|
95
|
-
listeners.forEach((cb) => cb(deserializeArgs(data)));
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
channels.set(channelId, channel);
|
|
99
|
-
|
|
100
|
-
return {
|
|
101
|
-
send: (...data) => {
|
|
102
|
-
const body = serializeArgs(data);
|
|
103
|
-
send(
|
|
104
|
-
channelId,
|
|
105
|
-
new Uint8Array([
|
|
106
|
-
...numberTo4Bytes(body.byteLength),
|
|
107
|
-
...body
|
|
108
|
-
])
|
|
109
|
-
);
|
|
110
|
-
},
|
|
111
|
-
on: (cb) => listeners.add(cb),
|
|
112
|
-
off: (cb) => listeners.add(cb)
|
|
113
|
-
} as DataChannel;
|
|
114
|
-
}
|
|
115
|
-
};
|
|
116
|
-
|
|
117
|
-
return bridge(payload, transformer);
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// 21
|
|
121
|
-
function send(channelId: string, data: Uint8Array) {
|
|
122
|
-
const payload = new Uint8Array([21, ...serializeArgs([channelId, data])]);
|
|
123
|
-
|
|
124
|
-
return bridge(payload);
|
|
125
|
-
}
|
|
@@ -1,76 +0,0 @@
|
|
|
1
|
-
import { bridge } from "../bridge";
|
|
2
|
-
import { serializeArgs } from "../bridge/serialization";
|
|
3
|
-
import { SnackBar } from "../components/snackbar";
|
|
4
|
-
|
|
5
|
-
const coreMessageListeners = new Map<string, Set<(message: string) => void>>();
|
|
6
|
-
export const addListener = (
|
|
7
|
-
messageType: string,
|
|
8
|
-
cb: (message: string) => void
|
|
9
|
-
) => {
|
|
10
|
-
let listeners = coreMessageListeners.get(messageType);
|
|
11
|
-
if (!listeners) {
|
|
12
|
-
listeners = new Set<typeof cb>();
|
|
13
|
-
coreMessageListeners.set(messageType, listeners);
|
|
14
|
-
}
|
|
15
|
-
listeners.add(cb);
|
|
16
|
-
|
|
17
|
-
const pending = pendingMessages.get(messageType);
|
|
18
|
-
if (pending?.length) {
|
|
19
|
-
for (const m of pending) {
|
|
20
|
-
cb(m);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
};
|
|
24
|
-
export const removeListener = (
|
|
25
|
-
messageType: string,
|
|
26
|
-
cb: (message: string) => void
|
|
27
|
-
) => {
|
|
28
|
-
let listeners = coreMessageListeners.get(messageType);
|
|
29
|
-
listeners?.delete(cb);
|
|
30
|
-
if (listeners?.size === 0) {
|
|
31
|
-
coreMessageListeners.delete(messageType);
|
|
32
|
-
}
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
const pendingMessages = new Map<string, string[]>();
|
|
36
|
-
setInterval(() => pendingMessages.clear(), 10 * 1000); // 10s
|
|
37
|
-
|
|
38
|
-
globalThis.oncoremessage = (messageType: string, message: string) => {
|
|
39
|
-
const listeners = coreMessageListeners.get(messageType);
|
|
40
|
-
if (!listeners?.size) {
|
|
41
|
-
let pending = pendingMessages.get(messageType);
|
|
42
|
-
if (!pending) {
|
|
43
|
-
pending = [];
|
|
44
|
-
pendingMessages.set(messageType, pending);
|
|
45
|
-
}
|
|
46
|
-
pending.push(message);
|
|
47
|
-
} else {
|
|
48
|
-
listeners?.forEach((cb) => cb(message));
|
|
49
|
-
}
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
addListener("hello", console.log);
|
|
53
|
-
addListener("log", console.log);
|
|
54
|
-
addListener("alert", (message) => {
|
|
55
|
-
SnackBar({
|
|
56
|
-
message,
|
|
57
|
-
autoDismissTimeout: 4000
|
|
58
|
-
});
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
// 40
|
|
62
|
-
function setTitle(title: string) {
|
|
63
|
-
const payload = new Uint8Array([
|
|
64
|
-
40,
|
|
65
|
-
...serializeArgs([title])
|
|
66
|
-
]);
|
|
67
|
-
bridge(payload);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
let lastTitleSeen = null;
|
|
71
|
-
setInterval(() => {
|
|
72
|
-
if(lastTitleSeen !== document.title) {
|
|
73
|
-
setTitle(document.title);
|
|
74
|
-
}
|
|
75
|
-
lastTitleSeen = document.title;
|
|
76
|
-
}, 500)
|