global: MASSIVE snapshot

This commit is contained in:
nym21
2026-01-02 19:08:20 +01:00
parent ac6175688d
commit 3e9b1cc2b2
462 changed files with 34975 additions and 20072 deletions
+4794 -3765
View File
File diff suppressed because it is too large Load Diff
+33
View File
@@ -0,0 +1,33 @@
{
"name": "@bitcoinresearchkit/client",
"version": "0.1.0-alpha.1",
"description": "BRK JavaScript client",
"type": "module",
"main": "index.js",
"exports": {
".": "./index.js"
},
"files": [
"index.js",
"generated"
],
"keywords": [
"brk",
"bitcoin",
"blockchain",
"research"
],
"license": "MIT",
"repository": {
"type": "git",
"url": "git+https://github.com/bitcoinresearchkit/brk.git",
"directory": "modules/brk-client"
},
"homepage": "https://github.com/bitcoinresearchkit/brk/tree/main/modules/brk-client",
"bugs": {
"url": "https://github.com/bitcoinresearchkit/brk/issues"
},
"engines": {
"node": ">=18"
}
}
-128
View File
@@ -1,128 +0,0 @@
/**
* @import { Signal, Signals } from "../brk-signals/index";
* @import { MetricNode } from "../brk-client/index";
*/
/**
* @template T
* @typedef {Object} Resource
* @property {Signal<T | null>} data
* @property {Signal<boolean>} loading
* @property {Signal<Error | null>} error
* @property {(...args: any[]) => Promise<T | null>} fetch
*/
/**
* @template T
* @typedef {Object} RangeState
* @property {Signal<T[] | null>} data
* @property {Signal<boolean>} loading
*/
/**
* @template T
* @typedef {Object} MetricResource
* @property {string} path
* @property {(from?: number, to?: number) => RangeState<T>} range
* @property {(from?: number, to?: number) => Promise<T[] | null>} fetch
*/
/**
* @typedef {ReturnType<typeof createResources>} Resources
*/
/**
* @param {Signals} signals
*/
export function createResources(signals) {
const owner = signals.getOwner();
/**
* Create a generic reactive resource wrapper for any async fetcher
* @template T
* @template {any[]} Args
* @param {(...args: Args) => Promise<T>} fetcher
* @returns {Resource<T>}
*/
function createResource(fetcher) {
return signals.runWithOwner(owner, () => {
const data = signals.createSignal(/** @type {T | null} */ (null));
const loading = signals.createSignal(false);
const error = signals.createSignal(/** @type {Error | null} */ (null));
return {
data,
loading,
error,
/**
* @param {Args} args
*/
async fetch(...args) {
loading.set(true);
error.set(null);
try {
const result = await fetcher(...args);
data.set(result);
return result;
} catch (e) {
error.set(e instanceof Error ? e : new Error(String(e)));
return null;
} finally {
loading.set(false);
}
},
};
});
}
/**
* Create a reactive resource wrapper for a MetricNode with multi-range support
* @template T
* @param {MetricNode<T>} node
* @returns {MetricResource<T>}
*/
function useMetricNode(node) {
return signals.runWithOwner(owner, () => {
/** @type {Map<string, RangeState<T>>} */
const ranges = new Map();
/**
* Get or create range state
* @param {number} [from=-10000]
* @param {number} [to]
*/
function range(from = -10000, to) {
const key = `${from}-${to ?? ""}`;
if (!ranges.has(key)) {
ranges.set(key, {
data: signals.createSignal(/** @type {T[] | null} */ (null)),
loading: signals.createSignal(false),
});
}
return /** @type {RangeState<T>} */ (ranges.get(key));
}
return {
path: node._path,
range,
/**
* Fetch data for a range
* @param {number} [from=-10000]
* @param {number} [to]
*/
async fetch(from = -10000, to) {
const r = range(from, to);
r.loading.set(true);
try {
const result = await node.getRange(from, to, r.data.set);
return result;
} finally {
r.loading.set(false);
}
},
};
});
}
return { createResource, useMetricNode };
}
-10
View File
@@ -1,10 +0,0 @@
{
"compilerOptions": {
"checkJs": true,
"strict": true,
"target": "ESNext",
"module": "ESNext",
"skipLibCheck": true
},
"exclude": ["dist"]
}
-13
View File
@@ -1,13 +0,0 @@
{
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"strict": true,
"target": "ESNext",
"module": "ESNext",
"outDir": "/tmp/brk",
"lib": ["DOM", "DOM.Iterable", "ESNext", "WebWorker"],
"skipLibCheck": true
},
"exclude": ["dist"]
}
-221
View File
@@ -1,221 +0,0 @@
/**
* @import { SignalOptions } from "../solidjs-signals/0.6.3/dist/types/core/core"
* @import { getOwner as GetOwner, onCleanup as OnCleanup } from "../solidjs-signals/0.6.3/dist/types/core/owner"
* @import { createSignal as CreateSignal, createEffect as CreateEffect, createMemo as CreateMemo, createRoot as CreateRoot, runWithOwner as RunWithOwner, Setter } from "../solidjs-signals/0.6.3/dist/types/signals";
*/
// test
// wkopwfk
/**
* @template T
* @typedef {() => T} Accessor
*/
/**
* @template T
* @typedef {Accessor<T> & { set: Setter<T>; reset: VoidFunction }} Signal
*/
import {
createSignal,
createEffect,
getOwner,
createMemo,
createRoot,
runWithOwner,
onCleanup,
} from "../solidjs-signals/0.6.3/dist/prod.js";
let effectCount = 0;
const signals = {
createSolidSignal: /** @type {typeof CreateSignal} */ (createSignal),
createSolidEffect: /** @type {typeof CreateEffect} */ (createEffect),
createEffect: /** @type {typeof CreateEffect} */ (
// @ts-ignore
(compute, effect) => {
let dispose = /** @type {VoidFunction | null} */ (null);
if (getOwner() === null) {
throw Error("No owner");
}
function cleanup() {
if (dispose) {
dispose();
dispose = null;
// console.log("effectCount = ", --effectCount);
}
}
// @ts-ignore
createEffect(compute, (v, oldV) => {
// console.log("effectCount = ", ++effectCount);
cleanup();
signals.createRoot((_dispose) => {
dispose = _dispose;
return effect(v, oldV);
});
signals.onCleanup(cleanup);
});
signals.onCleanup(cleanup);
}
),
createMemo: /** @type {typeof CreateMemo} */ (createMemo),
createRoot: /** @type {typeof CreateRoot} */ (createRoot),
getOwner: /** @type {typeof GetOwner} */ (getOwner),
runWithOwner: /** @type {typeof RunWithOwner} */ (runWithOwner),
onCleanup: /** @type {typeof OnCleanup} */ (onCleanup),
/**
* @template T
* @param {T} initialValue
* @param {SignalOptions<T> & {save?: {keyPrefix: string | Accessor<string>; key: string; serialize: (v: T) => string; deserialize: (v: string) => T; serializeParam?: boolean; saveDefaultValue?: boolean}}} [options]
* @returns {Signal<T>}
*/
createSignal(initialValue, options) {
const [get, set] = this.createSolidSignal(
/** @type {any} */ (initialValue),
options,
);
// @ts-ignore
get.set = set;
// @ts-ignore
get.reset = () => set(initialValue);
if (options?.save) {
const save = options.save;
const paramKey = save.key;
const storageKey = this.createMemo(
() =>
`${
typeof save.keyPrefix === "string"
? save.keyPrefix
: save.keyPrefix()
}-${paramKey}`,
);
/** @type { ((this: Window, ev: PopStateEvent) => any) | undefined} */
let popstateCallback;
let serialized = /** @type {string | null} */ (null);
if (options.save.serializeParam !== false) {
serialized = new URLSearchParams(window.location.search).get(paramKey);
// popstateCallback =
// /** @type {(this: Window, ev: PopStateEvent) => any} */ (
// (_) => {
// serialized = new URLSearchParams(window.location.search).get(
// paramKey,
// );
// set(() =>
// serialized ? save.deserialize(serialized) : initialValue,
// );
// }
// );
// if (!popstateCallback) throw "Unreachable";
// window.addEventListener("popstate", popstateCallback);
// signals.onCleanup(() => {
// if (popstateCallback)
// window.removeEventListener("popstate", popstateCallback);
// });
}
if (serialized === null) {
try {
serialized = localStorage.getItem(storageKey());
} catch (_) {}
}
if (serialized) {
set(() => (serialized ? save.deserialize(serialized) : initialValue));
}
let firstRun1 = true;
this.createEffect(storageKey, (storageKey) => {
if (!firstRun1) {
try {
serialized = localStorage.getItem(storageKey);
set(() =>
serialized ? save.deserialize(serialized) : initialValue,
);
} catch (_) {}
}
firstRun1 = false;
});
let firstRun2 = true;
this.createEffect(get, (value) => {
if (!save) return;
if (!firstRun2) {
try {
if (
value !== undefined &&
value !== null &&
(initialValue === undefined ||
initialValue === null ||
save.saveDefaultValue ||
save.serialize(value) !== save.serialize(initialValue))
) {
localStorage.setItem(storageKey(), save.serialize(value));
} else {
localStorage.removeItem(storageKey());
}
} catch (_) {}
}
if (
value !== undefined &&
value !== null &&
(initialValue === undefined ||
initialValue === null ||
save.saveDefaultValue ||
save.serialize(value) !== save.serialize(initialValue))
) {
writeParam(paramKey, save.serialize(value));
} else {
removeParam(paramKey);
}
firstRun2 = false;
});
}
// @ts-ignore
return get;
},
};
/** @typedef {typeof signals} Signals */
/**
* @param {string} key
* @param {string | undefined} value
*/
function writeParam(key, value) {
const urlParams = new URLSearchParams(window.location.search);
if (value !== undefined) {
urlParams.set(key, String(value));
} else {
urlParams.delete(key);
}
try {
window.history.replaceState(
null,
"",
`${window.location.pathname}?${urlParams.toString()}`,
);
} catch (_) {}
}
/**
* @param {string} key
*/
function removeParam(key) {
writeParam(key, undefined);
}
export default signals;
-10
View File
@@ -1,10 +0,0 @@
{
"compilerOptions": {
"checkJs": true,
"strict": true,
"target": "ESNext",
"module": "ESNext",
"skipLibCheck": true
},
"exclude": ["dist"]
}
-13
View File
@@ -1,13 +0,0 @@
{
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"strict": true,
"target": "ESNext",
"module": "ESNext",
"outDir": "/tmp/brk",
"lib": ["DOM", "DOM.Iterable", "ESNext", "WebWorker"],
"skipLibCheck": true
},
"exclude": ["dist"]
}