@freedomofpress/webcat 0.0.0-stage → 3.0.0
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/Readme.md +45 -0
- package/data/block.json +101 -0
- package/data/list.json +80 -0
- package/dist/hooks/content.js +1 -0
- package/dist/lib/browser/chrome.d.ts +86 -0
- package/dist/lib/browser/chrome.js +138 -0
- package/dist/lib/browser/kvstore.d.ts +70 -0
- package/dist/lib/browser/kvstore.js +241 -0
- package/dist/lib/browser/permissions.d.ts +113 -0
- package/dist/lib/browser/permissions.js +182 -0
- package/dist/lib/browser/requests.d.ts +145 -0
- package/dist/lib/browser/requests.js +292 -0
- package/dist/lib/browser/scripting.d.ts +19 -0
- package/dist/lib/browser/scripting.js +92 -0
- package/dist/lib/browser/sync.d.ts +68 -0
- package/dist/lib/browser/sync.js +114 -0
- package/dist/lib/browser/utils.d.ts +5 -0
- package/dist/lib/browser/utils.js +11 -0
- package/dist/lib/config.d.ts +45 -0
- package/dist/lib/config.js +45 -0
- package/dist/lib/validator_set.d.ts +4 -0
- package/dist/lib/validator_set.js +20 -0
- package/dist/lib/webcat/cache.d.ts +200 -0
- package/dist/lib/webcat/cache.js +308 -0
- package/dist/lib/webcat/canonicalize.d.ts +1 -0
- package/dist/lib/webcat/canonicalize.js +58 -0
- package/dist/lib/webcat/db.d.ts +30 -0
- package/dist/lib/webcat/db.js +131 -0
- package/dist/lib/webcat/encoding.d.ts +8 -0
- package/dist/lib/webcat/encoding.js +57 -0
- package/dist/lib/webcat/handler.d.ts +26 -0
- package/dist/lib/webcat/handler.js +419 -0
- package/dist/lib/webcat/hookbuilder.d.ts +47 -0
- package/dist/lib/webcat/hookbuilder.js +170 -0
- package/dist/lib/webcat/interfaces/bundle.d.ts +46 -0
- package/dist/lib/webcat/interfaces/bundle.js +8 -0
- package/dist/lib/webcat/interfaces/database.d.ts +68 -0
- package/dist/lib/webcat/interfaces/database.js +1 -0
- package/dist/lib/webcat/interfaces/errors.d.ts +451 -0
- package/dist/lib/webcat/interfaces/errors.js +109 -0
- package/dist/lib/webcat/interfaces/log.d.ts +14 -0
- package/dist/lib/webcat/interfaces/log.js +10 -0
- package/dist/lib/webcat/interfaces/originstate.d.ts +40 -0
- package/dist/lib/webcat/interfaces/originstate.js +1 -0
- package/dist/lib/webcat/interfaces/requeststate.d.ts +10 -0
- package/dist/lib/webcat/interfaces/requeststate.js +1 -0
- package/dist/lib/webcat/logger.d.ts +64 -0
- package/dist/lib/webcat/logger.js +112 -0
- package/dist/lib/webcat/originstate.d.ts +45 -0
- package/dist/lib/webcat/originstate.js +302 -0
- package/dist/lib/webcat/parsers.d.ts +21 -0
- package/dist/lib/webcat/parsers.js +36 -0
- package/dist/lib/webcat/request.d.ts +11 -0
- package/dist/lib/webcat/request.js +78 -0
- package/dist/lib/webcat/resources.d.ts +3 -0
- package/dist/lib/webcat/resources.js +41 -0
- package/dist/lib/webcat/response.d.ts +39 -0
- package/dist/lib/webcat/response.js +394 -0
- package/dist/lib/webcat/ui.d.ts +70 -0
- package/dist/lib/webcat/ui.js +282 -0
- package/dist/lib/webcat/updater.d.ts +115 -0
- package/dist/lib/webcat/updater.js +296 -0
- package/dist/lib/webcat/utils.d.ts +8 -0
- package/dist/lib/webcat/utils.js +74 -0
- package/dist/lib/webcat/validators.d.ts +16 -0
- package/dist/lib/webcat/validators.js +457 -0
- package/dist/lib/webcat.d.ts +11 -0
- package/dist/lib/webcat.js +130 -0
- package/icons/dark/webcat-error.SVG +1 -0
- package/icons/dark/webcat-ok.SVG +1 -0
- package/icons/dark/webcat.SVG +1 -0
- package/icons/light/webcat-error.SVG +1 -0
- package/icons/light/webcat-ok.SVG +1 -0
- package/icons/light/webcat.SVG +1 -0
- package/package.json +72 -4
- package/pages/error.css +9 -0
- package/pages/error.html +70 -0
- package/pages/error.js +51 -0
- package/pages/popup.css +16 -0
- package/pages/popup.html +14 -0
- package/pages/popup.js +48 -0
- package/README.md +0 -3
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import validator_set from "./validator_set.js";
|
|
2
|
+
const defaults = {
|
|
3
|
+
/** {@inheritDoc WebcatConfig.namespace} */
|
|
4
|
+
namespace: "WEBCAT",
|
|
5
|
+
/** {@inheritDoc WebcatConfig.originCacheSize} */
|
|
6
|
+
originCacheSize: 32,
|
|
7
|
+
/** {@inheritDoc WebcatConfig.nonOriginCacheSize} */
|
|
8
|
+
nonOriginCacheSize: 8192,
|
|
9
|
+
/** {@inheritDoc WebcatConfig.bundlePath} */
|
|
10
|
+
bundlePath: "/.well-known/webcat/bundle.json",
|
|
11
|
+
/** {@inheritDoc WebcatConfig.bundlePrevPath} */
|
|
12
|
+
bundlePrevPath: "/.well-known/webcat/bundle-prev.json",
|
|
13
|
+
/** {@inheritDoc WebcatConfig.endpoint} */
|
|
14
|
+
endpoint: "https://webcat.freedom.press/",
|
|
15
|
+
/** {@inheritDoc WebcatConfig.localDataPath} */
|
|
16
|
+
localDataPath: "data",
|
|
17
|
+
/** {@inheritDoc WebcatConfig.validatorSet} */
|
|
18
|
+
validatorSet: validator_set,
|
|
19
|
+
chainId: "webcat-test-02",
|
|
20
|
+
// During alpha, update every hour. Wall-clock based so that sleep/suspend
|
|
21
|
+
// doesn't silently postpone updates.
|
|
22
|
+
/** {@inheritDoc WebcatConfig.updateInterval} */
|
|
23
|
+
updateInterval: 60 * 60 * 1e3,
|
|
24
|
+
// 1 hour
|
|
25
|
+
/** {@inheritDoc WebcatConfig.checkInterval} */
|
|
26
|
+
checkInterval: 5 * 60 * 1e3,
|
|
27
|
+
// poll every 5 minutes
|
|
28
|
+
/** {@inheritDoc WebcatConfig.fetchTimeout} */
|
|
29
|
+
fetchTimeout: 3e3,
|
|
30
|
+
// 3 second timeout for fetches
|
|
31
|
+
/** {@inheritDoc WebcatConfig.staticHookPath} */
|
|
32
|
+
staticHookPath: "dist/hooks/content.js",
|
|
33
|
+
/** {@inheritDoc WebcatConfig.iconPaths} */
|
|
34
|
+
iconPaths: (p) => `icons/${p.colorScheme}/${p.name}.SVG`,
|
|
35
|
+
/** {@inheritDoc WebcatConfig.pagePaths} */
|
|
36
|
+
pagePaths: (p) => `pages/${p.name}.html`
|
|
37
|
+
};
|
|
38
|
+
const test = Object.assign(Object.assign({}, defaults), {
|
|
39
|
+
originCacheSize: 2,
|
|
40
|
+
endpoint: "http://localhost:1234/"
|
|
41
|
+
});
|
|
42
|
+
export {
|
|
43
|
+
defaults,
|
|
44
|
+
test
|
|
45
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const validators = [{ "address": "48926DF1CC10DBBFAA78953F9BE38E59020DE01D", "pub_key": { "type": "tendermint/PubKeyEd25519", "value": "zEK+pyAEhhCaoHYhhT+rrorJoc9kZbfY+JkbMtF8u5Y=" }, "power": "1", "name": null }, { "address": "A39CFEBE6E8CA10B6101C46884A6EB8E62D04417", "pub_key": { "type": "tendermint/PubKeyEd25519", "value": "8dZUej72UriKCPIDvk01c6yLaAB2ssYIli3fT3jKwSM=" }, "power": "1", "name": null }, { "address": "B734AC6CC1F14AAC8315FE8DBB07402ED4E45D72", "pub_key": { "type": "tendermint/PubKeyEd25519", "value": "WBK6Af3uKtC+VTv8x48f2TPoNnsebSXSBTIsJku/nQw=" }, "power": "1", "name": null }];
|
|
2
|
+
const proposer = { "address": "B734AC6CC1F14AAC8315FE8DBB07402ED4E45D72", "pub_key": { "type": "tendermint/PubKeyEd25519", "value": "WBK6Af3uKtC+VTv8x48f2TPoNnsebSXSBTIsJku/nQw=" }, "power": "1", "name": null };
|
|
3
|
+
const total_voting_power = "3";
|
|
4
|
+
const count = "3";
|
|
5
|
+
const total = "3";
|
|
6
|
+
const validator_set = {
|
|
7
|
+
validators,
|
|
8
|
+
proposer,
|
|
9
|
+
total_voting_power,
|
|
10
|
+
count,
|
|
11
|
+
total
|
|
12
|
+
};
|
|
13
|
+
export {
|
|
14
|
+
count,
|
|
15
|
+
validator_set as default,
|
|
16
|
+
proposer,
|
|
17
|
+
total,
|
|
18
|
+
total_voting_power,
|
|
19
|
+
validators
|
|
20
|
+
};
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
import { KVStore } from "../browser/kvstore";
|
|
2
|
+
import { Lock, Mutex } from "../browser/sync";
|
|
3
|
+
declare const CacheKeySymbol: unique symbol;
|
|
4
|
+
/** @internal */
|
|
5
|
+
export type CacheKey<T> = string & {
|
|
6
|
+
[CacheKeySymbol]: T | undefined;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Constructs a cache key from a primary string key and a set of attributes,
|
|
10
|
+
* enabling arbitrary cache partitioning.
|
|
11
|
+
*
|
|
12
|
+
* @typeParam T - A string-indexed object type for cache attributes.
|
|
13
|
+
*/
|
|
14
|
+
export declare function CacheKey<T extends {
|
|
15
|
+
[index: string]: {
|
|
16
|
+
toString(): string;
|
|
17
|
+
};
|
|
18
|
+
}>(key: string, attrs: T): CacheKey<T>;
|
|
19
|
+
/**
|
|
20
|
+
* Checks whether a given {@link CacheKey} is in the specified partition.
|
|
21
|
+
*
|
|
22
|
+
* @typeParam P The type of the partition attribute object to check against.
|
|
23
|
+
* @typeParam T The type of the cache partition attributes of the key.
|
|
24
|
+
* @param key The key to check.
|
|
25
|
+
* @param partition The cache partition attributes.
|
|
26
|
+
* @returns true if the key has the specified attributes, i.e. is in the
|
|
27
|
+
* partition; false otherwise.
|
|
28
|
+
*/
|
|
29
|
+
export declare function isInPartition<P extends {
|
|
30
|
+
[index: string]: {
|
|
31
|
+
toString(): string;
|
|
32
|
+
};
|
|
33
|
+
}, T extends P>(key: CacheKey<T>, partition: P): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* A fixed-size in-memory cache that automatically evicts the least recently
|
|
36
|
+
* used entry first when it reaches its size limit.
|
|
37
|
+
*
|
|
38
|
+
* @typeParam K The type of cache keys.
|
|
39
|
+
* @typeParam V The type of values store in this cache.
|
|
40
|
+
*/
|
|
41
|
+
export declare class LRUCache<K, V> {
|
|
42
|
+
#private;
|
|
43
|
+
/** @internal */
|
|
44
|
+
protected readonly mutex: Mutex;
|
|
45
|
+
/**
|
|
46
|
+
* @param limit The maximum number of entries held by the cache.
|
|
47
|
+
*/
|
|
48
|
+
constructor(limit: number);
|
|
49
|
+
/** @internal */
|
|
50
|
+
constructor(limit: number, mutex: Mutex);
|
|
51
|
+
/**
|
|
52
|
+
* Reads a cached value.
|
|
53
|
+
*
|
|
54
|
+
* @param key The key to read.
|
|
55
|
+
* @returns A Promise that resolves with the value read.
|
|
56
|
+
*/
|
|
57
|
+
get(key: K): Promise<V | undefined>;
|
|
58
|
+
/** @internal */
|
|
59
|
+
get(key: K, l?: Lock): Promise<V | undefined>;
|
|
60
|
+
/**
|
|
61
|
+
* Caches a value.
|
|
62
|
+
*
|
|
63
|
+
* @param key The key to use.
|
|
64
|
+
* @param value The value to cache.
|
|
65
|
+
*/
|
|
66
|
+
set(key: K, value: V): Promise<void>;
|
|
67
|
+
/** @internal */
|
|
68
|
+
set(key: K, value: V, l?: Lock): Promise<void>;
|
|
69
|
+
/**
|
|
70
|
+
* @returns A Promise that resolves to true if the given key exists in the cache.
|
|
71
|
+
*/
|
|
72
|
+
has(key: K): Promise<boolean>;
|
|
73
|
+
/** @internal */
|
|
74
|
+
has(key: K, l?: Lock): Promise<boolean>;
|
|
75
|
+
/**
|
|
76
|
+
* @returns A Promise that resolves to an array of the keys in the cache.
|
|
77
|
+
*/
|
|
78
|
+
keys(): Promise<K[]>;
|
|
79
|
+
/** @internal */
|
|
80
|
+
keys(l?: Lock): Promise<K[]>;
|
|
81
|
+
/**
|
|
82
|
+
* Clears a single value from the cache.
|
|
83
|
+
*
|
|
84
|
+
* @param key The key to clear.
|
|
85
|
+
*/
|
|
86
|
+
delete(key: K): Promise<void>;
|
|
87
|
+
/** @internal */
|
|
88
|
+
delete(key: K, l?: Lock): Promise<void>;
|
|
89
|
+
/**
|
|
90
|
+
* Clears all values from the cache.
|
|
91
|
+
*/
|
|
92
|
+
clear(): Promise<void>;
|
|
93
|
+
/** @internal */
|
|
94
|
+
clear(l?: Lock): Promise<void>;
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* An object that can be converted to a {@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object | Plain Old JavaScript Object}
|
|
98
|
+
* compatible with persistence APIs.
|
|
99
|
+
*/
|
|
100
|
+
export type Pojoifiable = {
|
|
101
|
+
/**
|
|
102
|
+
* @returns A POJO representation of the object.
|
|
103
|
+
*/
|
|
104
|
+
toPOJO(): object;
|
|
105
|
+
};
|
|
106
|
+
/**
|
|
107
|
+
* Complementary interface to {@link Pojoifiable}.
|
|
108
|
+
*/
|
|
109
|
+
export interface Depojoifier<V> {
|
|
110
|
+
/**
|
|
111
|
+
* @param pojo An object created via {@link Pojoifiable.toPOJO}.
|
|
112
|
+
* @returns A corresponding {@link Pojoifiable} object.
|
|
113
|
+
*/
|
|
114
|
+
fromPOJO(pojo: object): V;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Arguments for the {@link PersistentLRUCache} constructor:
|
|
118
|
+
* 1. limit: the maximum number of entries held by the cache
|
|
119
|
+
* 2. store: a {@link KVStore} instance to use for persistence
|
|
120
|
+
* 3. area: the name of the {@link browser.storage.StorageArea | storage area}
|
|
121
|
+
* to use
|
|
122
|
+
* 4. (optional) depojoifier: a {@link Depojoifier} for converting persisted
|
|
123
|
+
* POJOs to V; required if and only if V extends {@link Pojoifiable}.
|
|
124
|
+
*
|
|
125
|
+
* @typeParam V The type of values stored in the cache.
|
|
126
|
+
* @expand
|
|
127
|
+
*/
|
|
128
|
+
export type PersistentLRUCacheArgs<V> = V extends Pojoifiable ? [number, KVStore, "session" | "local", Depojoifier<V>] : [number, KVStore, "session" | "local"];
|
|
129
|
+
/**
|
|
130
|
+
* A persistent {@link LRUCache}. Supported value types are limited by the
|
|
131
|
+
* storage API. In addition to JSON-ifiable values, i.e. Plain Old JavaScript
|
|
132
|
+
* Objects (POJOs), accepted by the storage API, arbitrary objects that
|
|
133
|
+
* implement the {@link Pojoifiable} interface can be cached. The conversion
|
|
134
|
+
* from {@link Pojoifiable} (and back via the {@link Depojoifier} interface) is
|
|
135
|
+
* handled automatically.
|
|
136
|
+
*
|
|
137
|
+
* @typeParam K The type of cache keys.
|
|
138
|
+
* @typeParam V The type of values store in this cache.
|
|
139
|
+
*/
|
|
140
|
+
export declare class PersistentLRUCache<K extends string, V extends Pojoifiable | unknown> extends LRUCache<K, V> {
|
|
141
|
+
#private;
|
|
142
|
+
/** @param args */
|
|
143
|
+
constructor(...[limit, store, area, depojoifier]: PersistentLRUCacheArgs<V>);
|
|
144
|
+
get(key: K): Promise<V | undefined>;
|
|
145
|
+
/** @internal */
|
|
146
|
+
get(key: K, l?: Lock): Promise<V | undefined>;
|
|
147
|
+
set(key: K, value: V): Promise<void>;
|
|
148
|
+
/** @internal */
|
|
149
|
+
set(key: K, value: V, l?: Lock): Promise<void>;
|
|
150
|
+
has(key: K): Promise<boolean>;
|
|
151
|
+
/** @internal */
|
|
152
|
+
has(key: K, l?: Lock): Promise<boolean>;
|
|
153
|
+
keys(): Promise<K[]>;
|
|
154
|
+
/** @internal */
|
|
155
|
+
keys(l?: Lock): Promise<K[]>;
|
|
156
|
+
delete(key: K): Promise<void>;
|
|
157
|
+
/** @internal */
|
|
158
|
+
delete(key: K, l?: Lock): Promise<void>;
|
|
159
|
+
clear(): Promise<void>;
|
|
160
|
+
/** @internal */
|
|
161
|
+
clear(l?: Lock): Promise<void>;
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* An unkeyed fixed-size in-memory cache that automatically evicts the least
|
|
165
|
+
* recently used entry first when it reaches its size limit.
|
|
166
|
+
*
|
|
167
|
+
* @typeParam T The type of values to store in this cache.
|
|
168
|
+
*/
|
|
169
|
+
export declare class LRUSet<T> {
|
|
170
|
+
#private;
|
|
171
|
+
/**
|
|
172
|
+
* @param limit The maximum number of entries held by the cache.
|
|
173
|
+
*/
|
|
174
|
+
constructor(limit: number);
|
|
175
|
+
/**
|
|
176
|
+
* @returns A Promise that resolves to true if the given value exists in the cache.
|
|
177
|
+
*/
|
|
178
|
+
has(value: T): Promise<boolean>;
|
|
179
|
+
/**
|
|
180
|
+
* Caches a value.
|
|
181
|
+
*
|
|
182
|
+
* @param value The value to cache.
|
|
183
|
+
*/
|
|
184
|
+
add(value: T): Promise<void>;
|
|
185
|
+
/**
|
|
186
|
+
* @returns A Promise that resolves to an array of the values in the cache.
|
|
187
|
+
*/
|
|
188
|
+
values(): Promise<T[]>;
|
|
189
|
+
/**
|
|
190
|
+
* Clears a single value from the cache.
|
|
191
|
+
*
|
|
192
|
+
* @param value The value to clear.
|
|
193
|
+
*/
|
|
194
|
+
delete(value: T): Promise<void>;
|
|
195
|
+
/**
|
|
196
|
+
* Clears all values from the cache.
|
|
197
|
+
*/
|
|
198
|
+
clear(): Promise<void>;
|
|
199
|
+
}
|
|
200
|
+
export {};
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
2
|
+
var __reflectGet = Reflect.get;
|
|
3
|
+
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
|
|
4
|
+
var __typeError = (msg) => {
|
|
5
|
+
throw TypeError(msg);
|
|
6
|
+
};
|
|
7
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
8
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
9
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
10
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
11
|
+
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
12
|
+
var __superGet = (cls, obj, key) => __reflectGet(__getProtoOf(cls), key, obj);
|
|
13
|
+
var __using = (stack, value, async) => {
|
|
14
|
+
if (value != null) {
|
|
15
|
+
if (typeof value !== "object" && typeof value !== "function") __typeError("Object expected");
|
|
16
|
+
var dispose, inner;
|
|
17
|
+
if (async) dispose = value[__knownSymbol("asyncDispose")];
|
|
18
|
+
if (dispose === void 0) {
|
|
19
|
+
dispose = value[__knownSymbol("dispose")];
|
|
20
|
+
if (async) inner = dispose;
|
|
21
|
+
}
|
|
22
|
+
if (typeof dispose !== "function") __typeError("Object not disposable");
|
|
23
|
+
if (inner) dispose = function() {
|
|
24
|
+
try {
|
|
25
|
+
inner.call(this);
|
|
26
|
+
} catch (e) {
|
|
27
|
+
return Promise.reject(e);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
stack.push([async, dispose, value]);
|
|
31
|
+
} else if (async) {
|
|
32
|
+
stack.push([async]);
|
|
33
|
+
}
|
|
34
|
+
return value;
|
|
35
|
+
};
|
|
36
|
+
var __callDispose = (stack, error, hasError) => {
|
|
37
|
+
var E = typeof SuppressedError === "function" ? SuppressedError : function(e, s, m, _) {
|
|
38
|
+
return _ = Error(m), _.name = "SuppressedError", _.error = e, _.suppressed = s, _;
|
|
39
|
+
};
|
|
40
|
+
var fail = (e) => error = hasError ? new E(e, error, "An error was suppressed during disposal") : (hasError = true, e);
|
|
41
|
+
var next = (it) => {
|
|
42
|
+
while (it = stack.pop()) {
|
|
43
|
+
try {
|
|
44
|
+
var result = it[1] && it[1].call(it[2]);
|
|
45
|
+
if (it[0]) return Promise.resolve(result).then(next, (e) => (fail(e), next()));
|
|
46
|
+
} catch (e) {
|
|
47
|
+
fail(e);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
if (hasError) throw error;
|
|
51
|
+
};
|
|
52
|
+
return next();
|
|
53
|
+
};
|
|
54
|
+
var _cache, _limit, _store, _area, _depojoifier, _ready, _PersistentLRUCache_instances, load_fn, _cache2, _limit2;
|
|
55
|
+
import { Mutex } from "../browser/sync.js";
|
|
56
|
+
function CacheKey(key, attrs) {
|
|
57
|
+
return encodeURIComponent(key) + (attrs ? "?" + Object.keys(attrs).sort().map(
|
|
58
|
+
(name) => `${encodeURIComponent(name)}=${encodeURIComponent(attrs[name].toString())}`
|
|
59
|
+
) : "");
|
|
60
|
+
}
|
|
61
|
+
function isInPartition(key, partition) {
|
|
62
|
+
const [_, q] = key.split("?");
|
|
63
|
+
if (q) {
|
|
64
|
+
const attrs = {};
|
|
65
|
+
q.split(",").forEach((attr) => {
|
|
66
|
+
const [name, value] = attr.split("=");
|
|
67
|
+
attrs[name] = value;
|
|
68
|
+
});
|
|
69
|
+
return Object.keys(partition).every(
|
|
70
|
+
(name) => partition[name].toString() === attrs[name]
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
return Object.keys(partition).length === 0;
|
|
74
|
+
}
|
|
75
|
+
class LRUCache {
|
|
76
|
+
constructor(limit, mutex) {
|
|
77
|
+
__privateAdd(this, _cache);
|
|
78
|
+
__privateAdd(this, _limit);
|
|
79
|
+
this.mutex = mutex || new Mutex();
|
|
80
|
+
__privateSet(this, _limit, limit);
|
|
81
|
+
__privateSet(this, _cache, /* @__PURE__ */ new Map());
|
|
82
|
+
}
|
|
83
|
+
async get(key, l) {
|
|
84
|
+
var _stack = [];
|
|
85
|
+
try {
|
|
86
|
+
const lock = __using(_stack, await this.mutex.acquire(l));
|
|
87
|
+
if (!__privateGet(this, _cache).has(key)) return void 0;
|
|
88
|
+
const value = __privateGet(this, _cache).get(key);
|
|
89
|
+
await this.set(key, value, lock);
|
|
90
|
+
return value;
|
|
91
|
+
} catch (_) {
|
|
92
|
+
var _error = _, _hasError = true;
|
|
93
|
+
} finally {
|
|
94
|
+
__callDispose(_stack, _error, _hasError);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
async set(key, value, l) {
|
|
98
|
+
var _stack = [];
|
|
99
|
+
try {
|
|
100
|
+
const lock = __using(_stack, await this.mutex.acquire(l));
|
|
101
|
+
if (__privateGet(this, _cache).has(key)) {
|
|
102
|
+
await this.delete(key, lock);
|
|
103
|
+
} else if (__privateGet(this, _cache).size >= __privateGet(this, _limit)) {
|
|
104
|
+
const oldestKey = __privateGet(this, _cache).keys().next().value;
|
|
105
|
+
if (oldestKey !== void 0) {
|
|
106
|
+
await this.delete(oldestKey, lock);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
__privateGet(this, _cache).set(key, value);
|
|
110
|
+
} catch (_) {
|
|
111
|
+
var _error = _, _hasError = true;
|
|
112
|
+
} finally {
|
|
113
|
+
__callDispose(_stack, _error, _hasError);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
async has(key, l) {
|
|
117
|
+
var _stack = [];
|
|
118
|
+
try {
|
|
119
|
+
const _lock = __using(_stack, await this.mutex.acquire(l));
|
|
120
|
+
return __privateGet(this, _cache).has(key);
|
|
121
|
+
} catch (_) {
|
|
122
|
+
var _error = _, _hasError = true;
|
|
123
|
+
} finally {
|
|
124
|
+
__callDispose(_stack, _error, _hasError);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async keys(l) {
|
|
128
|
+
var _stack = [];
|
|
129
|
+
try {
|
|
130
|
+
const _lock = __using(_stack, await this.mutex.acquire(l));
|
|
131
|
+
return Array.from(__privateGet(this, _cache).keys());
|
|
132
|
+
} catch (_) {
|
|
133
|
+
var _error = _, _hasError = true;
|
|
134
|
+
} finally {
|
|
135
|
+
__callDispose(_stack, _error, _hasError);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
async delete(key, l) {
|
|
139
|
+
var _stack = [];
|
|
140
|
+
try {
|
|
141
|
+
const _lock = __using(_stack, await this.mutex.acquire(l));
|
|
142
|
+
__privateGet(this, _cache).delete(key);
|
|
143
|
+
} catch (_) {
|
|
144
|
+
var _error = _, _hasError = true;
|
|
145
|
+
} finally {
|
|
146
|
+
__callDispose(_stack, _error, _hasError);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
async clear(l) {
|
|
150
|
+
var _stack = [];
|
|
151
|
+
try {
|
|
152
|
+
const _lock = __using(_stack, await this.mutex.acquire(l));
|
|
153
|
+
__privateGet(this, _cache).clear();
|
|
154
|
+
} catch (_) {
|
|
155
|
+
var _error = _, _hasError = true;
|
|
156
|
+
} finally {
|
|
157
|
+
__callDispose(_stack, _error, _hasError);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
_cache = new WeakMap();
|
|
162
|
+
_limit = new WeakMap();
|
|
163
|
+
const _PersistentLRUCache = class _PersistentLRUCache extends LRUCache {
|
|
164
|
+
/** @param args */
|
|
165
|
+
constructor(...[limit, store, area, depojoifier]) {
|
|
166
|
+
super(limit);
|
|
167
|
+
__privateAdd(this, _PersistentLRUCache_instances);
|
|
168
|
+
__privateAdd(this, _store);
|
|
169
|
+
__privateAdd(this, _area);
|
|
170
|
+
__privateAdd(this, _depojoifier);
|
|
171
|
+
__privateAdd(this, _ready);
|
|
172
|
+
__privateSet(this, _store, store);
|
|
173
|
+
__privateSet(this, _area, area);
|
|
174
|
+
__privateSet(this, _depojoifier, depojoifier);
|
|
175
|
+
__privateSet(this, _ready, __privateMethod(this, _PersistentLRUCache_instances, load_fn).call(this));
|
|
176
|
+
}
|
|
177
|
+
async get(key, l) {
|
|
178
|
+
await __privateGet(this, _ready);
|
|
179
|
+
return super.get(key, l);
|
|
180
|
+
}
|
|
181
|
+
async set(key, value, l) {
|
|
182
|
+
var _stack = [];
|
|
183
|
+
try {
|
|
184
|
+
await __privateGet(this, _ready);
|
|
185
|
+
const lock = __using(_stack, await this.mutex.acquire(l));
|
|
186
|
+
const pojo = value?.toPOJO?.() ?? value;
|
|
187
|
+
await super.set(key, value, lock);
|
|
188
|
+
await __privateGet(this, _store).set({ [key]: pojo }, __privateGet(this, _area));
|
|
189
|
+
} catch (_) {
|
|
190
|
+
var _error = _, _hasError = true;
|
|
191
|
+
} finally {
|
|
192
|
+
__callDispose(_stack, _error, _hasError);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
async has(key, l) {
|
|
196
|
+
await __privateGet(this, _ready);
|
|
197
|
+
return super.has(key, l);
|
|
198
|
+
}
|
|
199
|
+
async keys(l) {
|
|
200
|
+
await __privateGet(this, _ready);
|
|
201
|
+
return super.keys(l);
|
|
202
|
+
}
|
|
203
|
+
async delete(key, l) {
|
|
204
|
+
var _stack = [];
|
|
205
|
+
try {
|
|
206
|
+
await __privateGet(this, _ready);
|
|
207
|
+
const lock = __using(_stack, await this.mutex.acquire(l));
|
|
208
|
+
await __privateGet(this, _store).remove(key, __privateGet(this, _area));
|
|
209
|
+
return super.delete(key, lock);
|
|
210
|
+
} catch (_) {
|
|
211
|
+
var _error = _, _hasError = true;
|
|
212
|
+
} finally {
|
|
213
|
+
__callDispose(_stack, _error, _hasError);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
async clear(l) {
|
|
217
|
+
var _stack = [];
|
|
218
|
+
try {
|
|
219
|
+
await __privateGet(this, _ready);
|
|
220
|
+
const lock = __using(_stack, await this.mutex.acquire(l));
|
|
221
|
+
await __privateGet(this, _store).clear("", __privateGet(this, _area));
|
|
222
|
+
return super.clear(lock);
|
|
223
|
+
} catch (_) {
|
|
224
|
+
var _error = _, _hasError = true;
|
|
225
|
+
} finally {
|
|
226
|
+
__callDispose(_stack, _error, _hasError);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
_store = new WeakMap();
|
|
231
|
+
_area = new WeakMap();
|
|
232
|
+
_depojoifier = new WeakMap();
|
|
233
|
+
_ready = new WeakMap();
|
|
234
|
+
_PersistentLRUCache_instances = new WeakSet();
|
|
235
|
+
load_fn = async function() {
|
|
236
|
+
const keys = await __privateGet(this, _store).getKeys("", __privateGet(this, _area));
|
|
237
|
+
for (const key of keys) {
|
|
238
|
+
const pojo = await __privateGet(this, _store).get(key, __privateGet(this, _area));
|
|
239
|
+
const v = __privateGet(this, _depojoifier)?.fromPOJO(pojo) ?? pojo;
|
|
240
|
+
await __superGet(_PersistentLRUCache.prototype, this, "set").call(this, key, v);
|
|
241
|
+
}
|
|
242
|
+
};
|
|
243
|
+
let PersistentLRUCache = _PersistentLRUCache;
|
|
244
|
+
class LRUSet {
|
|
245
|
+
/**
|
|
246
|
+
* @param limit The maximum number of entries held by the cache.
|
|
247
|
+
*/
|
|
248
|
+
constructor(limit) {
|
|
249
|
+
__privateAdd(this, _cache2);
|
|
250
|
+
__privateAdd(this, _limit2);
|
|
251
|
+
__privateSet(this, _limit2, limit);
|
|
252
|
+
__privateSet(this, _cache2, /* @__PURE__ */ new Set());
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* @returns A Promise that resolves to true if the given value exists in the cache.
|
|
256
|
+
*/
|
|
257
|
+
async has(value) {
|
|
258
|
+
if (!__privateGet(this, _cache2).has(value)) return false;
|
|
259
|
+
__privateGet(this, _cache2).delete(value);
|
|
260
|
+
__privateGet(this, _cache2).add(value);
|
|
261
|
+
return true;
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Caches a value.
|
|
265
|
+
*
|
|
266
|
+
* @param value The value to cache.
|
|
267
|
+
*/
|
|
268
|
+
async add(value) {
|
|
269
|
+
if (__privateGet(this, _cache2).has(value)) {
|
|
270
|
+
__privateGet(this, _cache2).delete(value);
|
|
271
|
+
} else if (__privateGet(this, _cache2).size >= __privateGet(this, _limit2)) {
|
|
272
|
+
const oldestValue = __privateGet(this, _cache2).values().next().value;
|
|
273
|
+
if (oldestValue !== void 0) {
|
|
274
|
+
__privateGet(this, _cache2).delete(oldestValue);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
__privateGet(this, _cache2).add(value);
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* @returns A Promise that resolves to an array of the values in the cache.
|
|
281
|
+
*/
|
|
282
|
+
async values() {
|
|
283
|
+
return Array.from(__privateGet(this, _cache2).values());
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Clears a single value from the cache.
|
|
287
|
+
*
|
|
288
|
+
* @param value The value to clear.
|
|
289
|
+
*/
|
|
290
|
+
async delete(value) {
|
|
291
|
+
__privateGet(this, _cache2).delete(value);
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Clears all values from the cache.
|
|
295
|
+
*/
|
|
296
|
+
async clear() {
|
|
297
|
+
__privateGet(this, _cache2).clear();
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
_cache2 = new WeakMap();
|
|
301
|
+
_limit2 = new WeakMap();
|
|
302
|
+
export {
|
|
303
|
+
CacheKey,
|
|
304
|
+
LRUCache,
|
|
305
|
+
LRUSet,
|
|
306
|
+
PersistentLRUCache,
|
|
307
|
+
isInPartition
|
|
308
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function canonicalize(object: unknown): string | null;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
const COMMA = ",";
|
|
2
|
+
const COLON = ":";
|
|
3
|
+
const LEFT_SQUARE_BRACKET = "[";
|
|
4
|
+
const RIGHT_SQUARE_BRACKET = "]";
|
|
5
|
+
const LEFT_CURLY_BRACKET = "{";
|
|
6
|
+
const RIGHT_CURLY_BRACKET = "}";
|
|
7
|
+
function canonicalizeString(string) {
|
|
8
|
+
const escapedString = string.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
9
|
+
return '"' + escapedString + '"';
|
|
10
|
+
}
|
|
11
|
+
function canonicalize(object) {
|
|
12
|
+
const buffer = [];
|
|
13
|
+
if (typeof object === "string") {
|
|
14
|
+
buffer.push(canonicalizeString(object));
|
|
15
|
+
} else if (typeof object === "boolean") {
|
|
16
|
+
buffer.push(JSON.stringify(object));
|
|
17
|
+
} else if (Number.isInteger(object)) {
|
|
18
|
+
buffer.push(JSON.stringify(object));
|
|
19
|
+
} else if (object === null) {
|
|
20
|
+
buffer.push(JSON.stringify(object));
|
|
21
|
+
} else if (Array.isArray(object)) {
|
|
22
|
+
buffer.push(LEFT_SQUARE_BRACKET);
|
|
23
|
+
let first = true;
|
|
24
|
+
for (const element of object) {
|
|
25
|
+
if (!first) {
|
|
26
|
+
buffer.push(COMMA);
|
|
27
|
+
}
|
|
28
|
+
first = false;
|
|
29
|
+
const encoded = canonicalize(element);
|
|
30
|
+
if (encoded === null) return null;
|
|
31
|
+
buffer.push(encoded);
|
|
32
|
+
}
|
|
33
|
+
buffer.push(RIGHT_SQUARE_BRACKET);
|
|
34
|
+
} else if (typeof object === "object") {
|
|
35
|
+
buffer.push(LEFT_CURLY_BRACKET);
|
|
36
|
+
let first = true;
|
|
37
|
+
for (const property of Object.keys(object).sort()) {
|
|
38
|
+
if (!first) {
|
|
39
|
+
buffer.push(COMMA);
|
|
40
|
+
}
|
|
41
|
+
first = false;
|
|
42
|
+
buffer.push(canonicalizeString(property));
|
|
43
|
+
buffer.push(COLON);
|
|
44
|
+
const encoded = canonicalize(
|
|
45
|
+
object[property]
|
|
46
|
+
);
|
|
47
|
+
if (encoded === null) return null;
|
|
48
|
+
buffer.push(encoded);
|
|
49
|
+
}
|
|
50
|
+
buffer.push(RIGHT_CURLY_BRACKET);
|
|
51
|
+
} else {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
return buffer.join("");
|
|
55
|
+
}
|
|
56
|
+
export {
|
|
57
|
+
canonicalize
|
|
58
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { NamespacedKVStore } from "../browser/kvstore";
|
|
2
|
+
import { CacheKey, LRUSet, PersistentLRUCache } from "./cache";
|
|
3
|
+
import { BlockMeta, Database } from "./interfaces/database";
|
|
4
|
+
import { CachePartition } from "./interfaces/originstate";
|
|
5
|
+
import { OriginState } from "./originstate";
|
|
6
|
+
/** @internal @inline */
|
|
7
|
+
export type WebcatDatabaseConfig = {
|
|
8
|
+
/** A string prefix used for all persisted keys. */
|
|
9
|
+
namespace: string;
|
|
10
|
+
/** The number of {@link OriginState} objects to cache locally. */
|
|
11
|
+
originCacheSize: number;
|
|
12
|
+
/** The number of hostnames to store in-memory in the negative origin cache. */
|
|
13
|
+
nonOriginCacheSize: number;
|
|
14
|
+
};
|
|
15
|
+
/** A {@link Database} backed by a {@link NamespacedKVStore}. */
|
|
16
|
+
export declare class WebcatDatabase extends NamespacedKVStore implements Database {
|
|
17
|
+
readonly origins: PersistentLRUCache<CacheKey<CachePartition>, OriginState>;
|
|
18
|
+
readonly nonOrigins: LRUSet<CacheKey<CachePartition>>;
|
|
19
|
+
/** A subnamespace for storing enrollment hashes. */
|
|
20
|
+
readonly enrollments: NamespacedKVStore;
|
|
21
|
+
constructor(config: WebcatDatabaseConfig);
|
|
22
|
+
updateList(leaves: readonly (readonly [string, string])[], meta: BlockMeta): Promise<void>;
|
|
23
|
+
getBlockMeta(): Promise<BlockMeta | null>;
|
|
24
|
+
listAllFQDNs(): Promise<string[]>;
|
|
25
|
+
getFQDNEnrollment(fqdn: string, cachePartition: CachePartition): Promise<Uint8Array>;
|
|
26
|
+
setLastChecked(): Promise<void>;
|
|
27
|
+
getLastChecked(): Promise<number | null>;
|
|
28
|
+
setLastUpdated(): Promise<void>;
|
|
29
|
+
getLastUpdated(): Promise<number | null>;
|
|
30
|
+
}
|