chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:25:07 +08:00
commit a26e856398
1681 changed files with 296950 additions and 0 deletions
+106
View File
@@ -0,0 +1,106 @@
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
// ┃ This file is part of the Perspective library, distributed under the terms ┃
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
import { make_session } from "@perspective-dev/client";
import * as securities from "./securities.mjs";
import * as path from "node:path";
import { promises as fs } from "node:fs";
import http from "node:http";
import { WebSocketServer as HttpWebSocketServer } from "ws";
// Don't need this table since it won't be read from node itself, just need
// to create it so the WebSocket clients can find it.
const _TABLE = await securities.getTable();
const CONTENT_TYPES = {
".js": "text/javascript",
".mjs": "text/javascript",
".css": "text/css; charset=utf-8",
".json": "application/json",
".arrow": "arraybuffer",
".feather": "arraybuffer",
".wasm": "application/wasm",
};
// node buffer -> JS buffer
function buffer_to_arraybuffer(buffer) {
return new Int8Array(
buffer.buffer.slice(
buffer.byteOffset,
buffer.byteOffset + buffer.length,
),
);
}
const app = new HttpWebSocketServer({
noServer: true,
perMessageDeflate: true,
});
app.on("connection", async (ws) => {
console.log("Connecting websocket ...");
const session = await make_session(async (proto) => {
ws.send(buffer_to_arraybuffer(proto));
});
ws.on("message", (proto) => {
session.handle_request(buffer_to_arraybuffer(proto));
});
ws.on("close", () => {
session.close();
});
});
const web_server = http.createServer(
async function static_files(request, response) {
let url =
request.url
?.split(/[\?\#]/)[0]
.replace(/@[\^~]?\d+.[\d\*]*.[\d\*]*/, "") || "/";
if (url === "/") {
url = "/index.html";
}
const extname = path.extname(url);
const contentType = CONTENT_TYPES[extname] || "text/html";
try {
const content = await fs.readFile(`dist/${url}`);
if (typeof content !== "undefined") {
response.writeHead(200, { "Content-Type": contentType });
response.end(content, "utf-8");
console.error(`200 ${url}`);
return;
}
console.error(`404 ${url}`);
response.writeHead(404);
response.end("", "utf-8");
} catch (error) {
console.error(`500 ${url} ${error}`);
response.writeHead(500);
response.end("", "utf-8");
}
},
);
web_server.on("upgrade", (request, socket, head) => {
console.log("200 Websocket upgrade");
app.handleUpgrade(request, socket, head, (sock) =>
app.emit("connection", sock, request),
);
});
web_server.listen(8081, () => {
console.log(`Listening on ${web_server.address().port}`);
});
@@ -0,0 +1,153 @@
// ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
// ┃ ██████ ██████ ██████ █ █ █ █ █ █▄ ▀███ █ ┃
// ┃ ▄▄▄▄▄█ █▄▄▄▄▄ ▄▄▄▄▄█ ▀▀▀▀▀█▀▀▀▀▀ █ ▀▀▀▀▀█ ████████▌▐███ ███▄ ▀█ █ ▀▀▀▀▀ ┃
// ┃ █▀▀▀▀▀ █▀▀▀▀▀ █▀██▀▀ ▄▄▄▄▄ █ ▄▄▄▄▄█ ▄▄▄▄▄█ ████████▌▐███ █████▄ █ ▄▄▄▄▄ ┃
// ┃ █ ██████ █ ▀█▄ █ ██████ █ ███▌▐███ ███████▄ █ ┃
// ┣━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┫
// ┃ Copyright (c) 2017, the Perspective Authors. ┃
// ┃ ╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌ ┃
// ┃ This file is part of the Perspective library, distributed under the terms ┃
// ┃ of the [Apache License 2.0](https://www.apache.org/licenses/LICENSE-2.0). ┃
// ┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
import perspective from "@perspective-dev/client";
// Cache updates for faster update rates (but less data diversity)>
const CACHE_INPUT = false;
// If cached, how many updates to cache?
const CACHE_ENTRIES = 200;
// How many rows per update?
const UPDATE_SIZE = 50;
// Update every N milliseconds
const TICK_RATE = 20;
// Size limit of the server-side table
const TABLE_SIZE = 10000;
const SECURITIES = [
"AAPL.N",
"AMZN.N",
"QQQ.N",
"NVDA.N",
"TSLA.N",
"FB.N",
"MSFT.N",
"TLT.N",
"XIV.N",
"YY.N",
"CSCO.N",
"GOOGL.N",
"PCLN.N",
];
const CLIENTS = [
"Homer",
"Marge",
"Bart",
"Lisa",
"Maggie",
"Moe",
"Lenny",
"Carl",
"Krusty",
];
const __CACHE__ = [];
// perspective.initialize_profile_thread();
/*******************************************************************************
*
* Slow mode (new rows generated on the fly)
*/
function choose(choices) {
return choices[Math.floor(Math.random() * choices.length)];
}
function newRows(total_rows) {
const rows = [];
for (let x = 0; x < total_rows; x++) {
rows.push({
name: choose(SECURITIES),
client: choose(CLIENTS),
lastUpdate: new Date(),
chg: Math.random() * 20 - 10,
bid: Math.random() * 10 + 90,
ask: Math.random() * 10 + 100,
vol: Math.random() * 10 + 100,
});
}
return rows;
}
async function init_dynamic({ table_size, update_size, tick_rate }) {
// Create a `table`.
const table = await perspective.table(newRows(table_size), {
limit: table_size,
name: "securities",
});
// The `table` needs to be registered to a name with the Perspective
// `WebSocketServer` in order for the client to get a proxy handle to it.
// Loop and update the `table` oocasionally.
(function postRow() {
table.update(newRows(update_size));
setTimeout(postRow, tick_rate);
})();
return table;
}
/*******************************************************************************
*
* Fast mode (rows pre-generated, cached as Arrows)
*/
async function newArrow(total_rows) {
const table = await perspective.table(newRows(total_rows));
const vw = await table.view();
const arrow = await vw.to_arrow();
vw.delete();
table.delete();
return arrow;
}
async function populate_cache(cache_entries) {
for (let x = 0; x < cache_entries; x++) {
let arrow = await newArrow(100);
__CACHE__[x] = arrow;
}
}
async function init_cached({ table_size, tick_rate, cache_entries }) {
await populate_cache(cache_entries);
const table = await perspective.table(newRows(table_size), {
limit: table_size,
name: "securities",
});
(function postRow() {
const entry = __CACHE__[Math.floor(Math.random() * __CACHE__.length)];
table.update(entry);
setTimeout(postRow, tick_rate);
})();
return table;
}
export const getTable = (
config = {
cached: CACHE_INPUT,
tick_rate: TICK_RATE,
update_size: UPDATE_SIZE,
table_size: TABLE_SIZE,
cache_entries: CACHE_ENTRIES,
},
) => {
if (config.cached) {
return init_cached(config);
} else {
return init_dynamic(config);
}
};