sliftutils 1.7.10 → 1.7.11
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/examplestorage/exampleserver.ts +0 -2
- package/index.d.ts +290 -54
- package/misc/dist/environment.ts.cache +3 -3
- package/misc/dist/getSecret.ts.cache +139 -0
- package/misc/dist/strings.ts.cache +13 -0
- package/misc/dist/zip.ts.cache +9 -0
- package/misc/getSecret.ts +38 -16
- package/misc/https/cloudflareHelpers.d.ts +19 -0
- package/misc/https/cloudflareHelpers.ts +69 -0
- package/misc/https/dist/certs.ts.cache +115 -179
- package/misc/https/dist/cloudflareHelpers.ts.cache +68 -0
- package/misc/https/dist/dns.ts.cache +112 -100
- package/misc/https/dist/hostServer.ts.cache +130 -0
- package/misc/https/dist/httpsCerts.ts.cache +24 -5
- package/misc/https/dist/persistentLocalStorage.ts.cache +3 -2
- package/misc/https/dns.d.ts +41 -12
- package/misc/https/dns.ts +104 -101
- package/misc/https/hostServer.d.ts +0 -6
- package/misc/https/hostServer.ts +9 -5
- package/package.json +2 -2
- package/render-utils/dist/observer.tsx.cache +3 -2
- package/spec.txt +0 -90
- package/storage/ArchivesDisk.d.ts +2 -0
- package/storage/ArchivesDisk.ts +7 -3
- package/storage/BulkDatabase2/dist/BulkDatabaseBase.ts.cache +1242 -0
- package/storage/BulkDatabase2/dist/BulkDatabaseFormat.ts.cache +513 -0
- package/storage/BulkDatabase2/dist/BulkDatabaseMerge.ts.cache +352 -0
- package/storage/BulkDatabase2/dist/BulkDatabaseReader.ts.cache +306 -0
- package/storage/BulkDatabase2/dist/LoadedIndex.ts.cache +435 -0
- package/storage/BulkDatabase2/dist/WriteOverlay.ts.cache +58 -0
- package/storage/BulkDatabase2/dist/blockCache.ts.cache +179 -0
- package/storage/BulkDatabase2/dist/mergeLock.ts.cache +149 -0
- package/storage/BulkDatabase2/dist/mergeMarkers.ts.cache +101 -0
- package/storage/BulkDatabase2/dist/streamLog.ts.cache +227 -0
- package/storage/BulkDatabase2/dist/syncClient.ts.cache +104 -0
- package/storage/IArchives.d.ts +47 -15
- package/storage/IArchives.ts +86 -31
- package/storage/backblaze.d.ts +15 -0
- package/storage/backblaze.ts +199 -79
- package/storage/dist/ArchivesDisk.ts.cache +373 -0
- package/storage/dist/FileFolderAPI.tsx.cache +508 -65
- package/storage/dist/IArchives.ts.cache +44 -0
- package/storage/dist/IndexedDBFileFolderAPI.ts.cache +8 -2
- package/storage/dist/JSONStorage.ts.cache +6 -2
- package/storage/dist/PendingManager.tsx.cache +1 -1
- package/storage/dist/TransactionStorage.ts.cache +231 -92
- package/storage/dist/backblaze.ts.cache +797 -0
- package/storage/dist/fileSystemPointer.ts.cache +36 -3
- package/storage/dist/remoteFileStorage.ts.cache +495 -0
- package/storage/remoteStorage/ArchivesRemote.d.ts +5 -1
- package/storage/remoteStorage/ArchivesRemote.ts +28 -8
- package/storage/remoteStorage/ArchivesUrl.d.ts +2 -0
- package/storage/remoteStorage/ArchivesUrl.ts +16 -4
- package/storage/remoteStorage/blobStore.d.ts +52 -3
- package/storage/remoteStorage/blobStore.ts +414 -101
- package/storage/remoteStorage/createArchives.d.ts +31 -10
- package/storage/remoteStorage/createArchives.ts +470 -253
- package/storage/remoteStorage/dist/ArchivesRemote.ts.cache +197 -0
- package/storage/remoteStorage/dist/ArchivesUrl.ts.cache +85 -0
- package/storage/remoteStorage/dist/accessPage.tsx.cache +222 -0
- package/storage/remoteStorage/dist/blobStore.ts.cache +837 -0
- package/storage/remoteStorage/dist/cliArgs.ts.cache +16 -0
- package/storage/remoteStorage/dist/createArchives.ts.cache +610 -0
- package/storage/remoteStorage/dist/remoteConfig.ts.cache +206 -0
- package/storage/remoteStorage/dist/sourceWrapper.ts.cache +223 -0
- package/storage/remoteStorage/dist/storageController.ts.cache +500 -0
- package/storage/remoteStorage/dist/storageServer.ts.cache +106 -0
- package/storage/remoteStorage/dist/storageServerCli.ts.cache +39 -0
- package/storage/remoteStorage/dist/storageServerState.ts.cache +518 -0
- package/storage/remoteStorage/remoteConfig.d.ts +8 -0
- package/storage/remoteStorage/remoteConfig.ts +105 -5
- package/storage/remoteStorage/sourceWrapper.d.ts +41 -0
- package/storage/remoteStorage/sourceWrapper.ts +223 -0
- package/storage/remoteStorage/spec.md +31 -0
- package/storage/remoteStorage/storageController.d.ts +11 -0
- package/storage/remoteStorage/storageController.ts +109 -40
- package/storage/remoteStorage/storageServer.d.ts +0 -5
- package/storage/remoteStorage/storageServer.ts +17 -10
- package/storage/remoteStorage/storageServerCli.ts +0 -3
- package/storage/remoteStorage/storageServerState.d.ts +7 -1
- package/storage/remoteStorage/storageServerState.ts +230 -48
- package/testsite/server.ts +0 -2
- package/yarn.lock +11 -6
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
process.env.NODE_ENV = "production";
|
|
2
|
-
import os from "os";
|
|
3
2
|
import path from "path";
|
|
4
3
|
import { SocketFunction } from "socket-function/SocketFunction";
|
|
5
4
|
import { RequireController } from "socket-function/require/RequireController";
|
|
@@ -31,7 +30,6 @@ async function main() {
|
|
|
31
30
|
await hostServer({
|
|
32
31
|
domain: DOMAIN,
|
|
33
32
|
port: PORT,
|
|
34
|
-
cloudflareApiToken: { path: os.homedir() + "/vidgridweb.com.key" },
|
|
35
33
|
setDNSRecord: true,
|
|
36
34
|
});
|
|
37
35
|
console.log(`Storage example site running at https://${DOMAIN}:${PORT}`);
|
package/index.d.ts
CHANGED
|
@@ -136,29 +136,81 @@ declare module "sliftutils/misc/https/certs" {
|
|
|
136
136
|
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
+
declare module "sliftutils/misc/https/cloudflareHelpers" {
|
|
140
|
+
/// <reference types="node" />
|
|
141
|
+
/// <reference types="node" />
|
|
142
|
+
export type CloudflareCreds = {
|
|
143
|
+
key: string;
|
|
144
|
+
/** Set for legacy global API keys, which auth via X-Auth-Email/X-Auth-Key. Absent for API tokens, which auth via Authorization: Bearer. */
|
|
145
|
+
email?: string;
|
|
146
|
+
};
|
|
147
|
+
export declare const getCloudflareCreds: {
|
|
148
|
+
(): Promise<CloudflareCreds>;
|
|
149
|
+
reset(): void;
|
|
150
|
+
set(newValue: Promise<CloudflareCreds>): void;
|
|
151
|
+
};
|
|
152
|
+
export declare function cloudflareGETCall<T>(path: string, params?: {
|
|
153
|
+
[key: string]: string;
|
|
154
|
+
}): Promise<T>;
|
|
155
|
+
export declare function cloudflarePOSTCall<T>(path: string, params: {
|
|
156
|
+
[key: string]: unknown;
|
|
157
|
+
}): Promise<T>;
|
|
158
|
+
export declare function cloudflareCall<T>(path: string, payload: Buffer, method: string): Promise<T>;
|
|
159
|
+
|
|
160
|
+
}
|
|
161
|
+
|
|
139
162
|
declare module "sliftutils/misc/https/dns" {
|
|
163
|
+
/** Parses our tag back out; 0 (i.e. always stale) when it's absent or unparseable. */
|
|
164
|
+
export declare function freshnessTime(comment?: string): number;
|
|
165
|
+
export declare const hasDNSWritePermissions: {
|
|
166
|
+
(): Promise<boolean>;
|
|
167
|
+
reset(): void;
|
|
168
|
+
set(newValue: Promise<boolean>): void;
|
|
169
|
+
};
|
|
170
|
+
export declare const getZoneId: {
|
|
171
|
+
(key: string): Promise<string>;
|
|
172
|
+
clear(key: string): void;
|
|
173
|
+
clearAll(): void;
|
|
174
|
+
forceSet(key: string, value: Promise<string>): void;
|
|
175
|
+
getAllKeys(): string[];
|
|
176
|
+
get(key: string): Promise<string> | undefined;
|
|
177
|
+
};
|
|
140
178
|
export declare function getRecordsRaw(type: string, key: string): Promise<{
|
|
141
179
|
id: string;
|
|
142
180
|
type: string;
|
|
143
181
|
name: string;
|
|
144
182
|
content: string;
|
|
145
183
|
proxied: boolean;
|
|
184
|
+
modified_on: string;
|
|
185
|
+
comment?: string | undefined;
|
|
146
186
|
}[]>;
|
|
187
|
+
/** Cloudflare's batch endpoint applies deletes, then patches, then posts in a single database
|
|
188
|
+
* transaction. We route edits (patches) through here because the standalone PATCH/PUT verbs
|
|
189
|
+
* aren't usable in our setup, and because it lets "remove others + assert target" happen
|
|
190
|
+
* without a window where the name resolves to nothing. */
|
|
191
|
+
export declare function batchRecords(zoneId: string, batch: {
|
|
192
|
+
deletes?: {
|
|
193
|
+
id: string;
|
|
194
|
+
}[];
|
|
195
|
+
patches?: {
|
|
196
|
+
id: string;
|
|
197
|
+
comment?: string;
|
|
198
|
+
}[];
|
|
199
|
+
posts?: {
|
|
200
|
+
type: string;
|
|
201
|
+
name: string;
|
|
202
|
+
content: string;
|
|
203
|
+
ttl: number;
|
|
204
|
+
proxied: boolean;
|
|
205
|
+
comment?: string;
|
|
206
|
+
}[];
|
|
207
|
+
}): Promise<void>;
|
|
147
208
|
export declare function getRecords(type: string, key: string): Promise<string[]>;
|
|
148
209
|
export declare function deleteRecord(type: string, key: string, value: string): Promise<void>;
|
|
149
|
-
/** Removes all existing records (unless the record is already present) */
|
|
150
|
-
export declare function setRecord(type: string, key: string, value: string, proxied?: "proxied"): Promise<void>;
|
|
210
|
+
/** Removes all existing records (unless the record is already present and fresh) */
|
|
211
|
+
export declare function setRecord(type: string, key: string, value: string, proxied?: "proxied", staleAfter?: number): Promise<void>;
|
|
151
212
|
/** Keeps existing records */
|
|
152
|
-
export declare function addRecord(type: string, key: string, value: string, proxied?: "proxied"): Promise<void>;
|
|
153
|
-
/** Provide Cloudflare credentials directly instead of relying on ./cloudflare.json. Exactly one of
|
|
154
|
-
* key (the API token itself) or path (a file to read it from) — TypeScript rejects both/neither. */
|
|
155
|
-
export declare function setCloudflareCredentials(config: {
|
|
156
|
-
value: {
|
|
157
|
-
key: string;
|
|
158
|
-
} | {
|
|
159
|
-
path: string;
|
|
160
|
-
};
|
|
161
|
-
}): void;
|
|
213
|
+
export declare function addRecord(type: string, key: string, value: string, proxied?: "proxied", staleAfter?: number): Promise<void>;
|
|
162
214
|
|
|
163
215
|
}
|
|
164
216
|
|
|
@@ -167,12 +219,6 @@ declare module "sliftutils/misc/https/hostServer" {
|
|
|
167
219
|
/** Full domain to host on (e.g. "testsite.example.com"). The HTTPS cert is created for this domain and *.domain, so using a subdomain never touches the root domain (beyond its _acme-challenge TXT record). */
|
|
168
220
|
domain: string;
|
|
169
221
|
port: number;
|
|
170
|
-
/** Cloudflare API token: either the token string ({ key }) or a path to a file containing it ({ path }). Required — pass { path: "./cloudflare.json" } explicitly for the on-disk file. */
|
|
171
|
-
cloudflareApiToken: {
|
|
172
|
-
key: string;
|
|
173
|
-
} | {
|
|
174
|
-
path: string;
|
|
175
|
-
};
|
|
176
222
|
/** Creates an unproxied A record pointing domain at this machine (publicIp, or our detected external IP) */
|
|
177
223
|
setDNSRecord?: boolean;
|
|
178
224
|
publicIp?: string;
|
|
@@ -822,6 +868,7 @@ declare module "sliftutils/storage/ArchivesDisk" {
|
|
|
822
868
|
};
|
|
823
869
|
getDebugName(): string;
|
|
824
870
|
getConfig(): Promise<ArchivesConfig>;
|
|
871
|
+
hasWriteAccess(): Promise<boolean>;
|
|
825
872
|
private filePath;
|
|
826
873
|
set(key: string, data: Buffer, config?: {
|
|
827
874
|
lastModified?: number;
|
|
@@ -841,6 +888,7 @@ declare module "sliftutils/storage/ArchivesDisk" {
|
|
|
841
888
|
}): Promise<{
|
|
842
889
|
data: Buffer;
|
|
843
890
|
writeTime: number;
|
|
891
|
+
size: number;
|
|
844
892
|
} | undefined>;
|
|
845
893
|
getInfo(key: string): Promise<{
|
|
846
894
|
writeTime: number;
|
|
@@ -2049,6 +2097,7 @@ declare module "sliftutils/storage/IArchives" {
|
|
|
2049
2097
|
/// <reference types="node" />
|
|
2050
2098
|
/// <reference types="node" />
|
|
2051
2099
|
export declare const MAX_LAST_MODIFIED_FUTURE: number;
|
|
2100
|
+
export declare const IMMUTABLE_CACHE_TIME: number;
|
|
2052
2101
|
export declare function assertValidLastModified(lastModified: number): void;
|
|
2053
2102
|
export type RemoteConfig = {
|
|
2054
2103
|
version?: number;
|
|
@@ -2067,8 +2116,14 @@ declare module "sliftutils/storage/IArchives" {
|
|
|
2067
2116
|
*/
|
|
2068
2117
|
export type RemoteConfigBase = string | HostedConfig | BackblazeConfig;
|
|
2069
2118
|
export type CommonConfig = {
|
|
2070
|
-
/**
|
|
2071
|
-
|
|
2119
|
+
/** By default a server hosting this bucket eagerly copies this source's full contents onto its own disk (on top of the lazy read-through caching). Set this to be a front end for a very large database without copying the full database - reads still down-cache individual files on demand. */
|
|
2120
|
+
noFullSync?: boolean;
|
|
2121
|
+
/** Bytes of read-cache this server's disk may hold; least-recently-used files are deleted from disk to stay under it (only ever when another source verifiably holds the file - the only copy is never deleted). Requires noFullSync (a full copy can't be bounded). */
|
|
2122
|
+
readerDiskLimit?: number;
|
|
2123
|
+
/** The write times ([startMs, endMs]) this source is valid for (see ArchivesSource.validWindow for the synchronization semantics). Required on object configs: configuration changes must be SCHEDULED (a new source becomes valid at a future time while the old one's window ends), not flipped instantly. Plain URL-string sources default to FULL_VALID_WINDOW - once you're writing object configs, you're doing something complicated enough to think about when things change. */
|
|
2124
|
+
validWindow: [number, number];
|
|
2125
|
+
/** Sharding: the fraction of the key space this source handles, as [start, end) over [0, 1) (keys are routed by getRoute in remoteConfig.ts). Defaults to FULL_ROUTE (unsharded). At every point in time the sources' routes must fully cover [0, 1), or some keys could never be read. */
|
|
2126
|
+
route?: [number, number];
|
|
2072
2127
|
};
|
|
2073
2128
|
export type HostedConfig = CommonConfig & {
|
|
2074
2129
|
type: "remote";
|
|
@@ -2083,34 +2138,56 @@ declare module "sliftutils/storage/IArchives" {
|
|
|
2083
2138
|
export type BackblazeConfig = CommonConfig & {
|
|
2084
2139
|
type: "backblaze";
|
|
2085
2140
|
url: string;
|
|
2086
|
-
bucketName: string;
|
|
2087
2141
|
public?: boolean;
|
|
2088
2142
|
immutable?: boolean;
|
|
2089
2143
|
};
|
|
2090
|
-
export declare const
|
|
2091
|
-
export declare const DEFAULT_SYNC_OPTIONS: SyncOptions;
|
|
2144
|
+
export declare const FULL_VALID_WINDOW: [number, number];
|
|
2092
2145
|
export type ArchiveFileInfo = {
|
|
2093
2146
|
path: string;
|
|
2094
2147
|
createTime: number;
|
|
2095
2148
|
size: number;
|
|
2096
2149
|
};
|
|
2150
|
+
export type SyncActivity = {
|
|
2151
|
+
type: "metadataScan" | "fullSync";
|
|
2152
|
+
sourceDebugName: string;
|
|
2153
|
+
startTime: number;
|
|
2154
|
+
doneFiles?: number;
|
|
2155
|
+
totalFiles?: number;
|
|
2156
|
+
doneBytes?: number;
|
|
2157
|
+
totalBytes?: number;
|
|
2158
|
+
};
|
|
2097
2159
|
export type ArchivesConfig = {
|
|
2098
2160
|
supportsChangesAfter?: boolean;
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2161
|
+
remoteConfig?: RemoteConfig;
|
|
2162
|
+
index?: {
|
|
2163
|
+
fileCount: number;
|
|
2164
|
+
byteCount: number;
|
|
2165
|
+
};
|
|
2166
|
+
indexSources?: {
|
|
2167
|
+
debugName: string;
|
|
2168
|
+
fileCount: number;
|
|
2169
|
+
byteCount: number;
|
|
2170
|
+
}[];
|
|
2171
|
+
readerDiskLimit?: number;
|
|
2172
|
+
syncing?: SyncActivity[];
|
|
2106
2173
|
};
|
|
2107
2174
|
export type ArchivesSource = {
|
|
2108
2175
|
source: IArchives;
|
|
2109
|
-
|
|
2110
|
-
|
|
2176
|
+
validWindow: [number, number];
|
|
2177
|
+
route?: [number, number];
|
|
2178
|
+
noFullSync?: boolean;
|
|
2179
|
+
};
|
|
2180
|
+
export declare const WRITE_PAST_WINDOW_GRACE: number;
|
|
2181
|
+
export declare const STORAGE_WRONG_VALID_WINDOW = "REMOTE_STORAGE_WRONG_VALID_WINDOW_a7c1f04e";
|
|
2182
|
+
export declare const STORAGE_WRONG_ROUTE = "REMOTE_STORAGE_WRONG_ROUTE_c94d2e17";
|
|
2183
|
+
export declare const FULL_ROUTE: [number, number];
|
|
2184
|
+
export declare const VARIABLE_SHARD = "VARIABLE_SHARD_f0234jfah08fgyhfgyssdds83nmp";
|
|
2185
|
+
export declare function windowAcceptsWrites(validWindow: [number, number] | undefined): boolean;
|
|
2111
2186
|
export type ArchivesSyncSourceStatus = {
|
|
2112
2187
|
debugName: string;
|
|
2113
|
-
|
|
2188
|
+
validWindow: [number, number];
|
|
2189
|
+
route?: [number, number];
|
|
2190
|
+
noFullSync?: boolean;
|
|
2114
2191
|
supportsChangesAfter: boolean;
|
|
2115
2192
|
initialScanComplete: boolean;
|
|
2116
2193
|
scannedCount: number;
|
|
@@ -2122,13 +2199,15 @@ declare module "sliftutils/storage/IArchives" {
|
|
|
2122
2199
|
};
|
|
2123
2200
|
export interface IArchives {
|
|
2124
2201
|
getDebugName(): string;
|
|
2202
|
+
/** Whether writes would be accepted (credentials exist, the account trusts this machine, etc).
|
|
2203
|
+
* Checked without writing anything. */
|
|
2204
|
+
hasWriteAccess(): Promise<boolean>;
|
|
2125
2205
|
get(fileName: string, config?: {
|
|
2126
2206
|
range?: {
|
|
2127
2207
|
start: number;
|
|
2128
2208
|
end: number;
|
|
2129
2209
|
};
|
|
2130
2210
|
}): Promise<Buffer | undefined>;
|
|
2131
|
-
/** Like get, but also returns the last-write time of the file. get just calls get2. */
|
|
2132
2211
|
get2(fileName: string, config?: {
|
|
2133
2212
|
range?: {
|
|
2134
2213
|
start: number;
|
|
@@ -2137,6 +2216,7 @@ declare module "sliftutils/storage/IArchives" {
|
|
|
2137
2216
|
}): Promise<{
|
|
2138
2217
|
data: Buffer;
|
|
2139
2218
|
writeTime: number;
|
|
2219
|
+
size: number;
|
|
2140
2220
|
} | undefined>;
|
|
2141
2221
|
/**
|
|
2142
2222
|
* lastModified stamps the write with that last-write time instead of now. If it is OLDER than
|
|
@@ -2444,6 +2524,7 @@ declare module "sliftutils/storage/backblaze" {
|
|
|
2444
2524
|
public?: boolean;
|
|
2445
2525
|
immutable?: boolean;
|
|
2446
2526
|
cacheTime?: number;
|
|
2527
|
+
allowedOrigins?: string[];
|
|
2447
2528
|
});
|
|
2448
2529
|
private bucketName;
|
|
2449
2530
|
private bucketId;
|
|
@@ -2452,6 +2533,7 @@ declare module "sliftutils/storage/backblaze" {
|
|
|
2452
2533
|
private log;
|
|
2453
2534
|
getDebugName(): string;
|
|
2454
2535
|
private getBucketAPI;
|
|
2536
|
+
private currentReset;
|
|
2455
2537
|
private last503Reset;
|
|
2456
2538
|
private apiRetryLogic;
|
|
2457
2539
|
get(fileName: string, config?: {
|
|
@@ -2469,8 +2551,10 @@ declare module "sliftutils/storage/backblaze" {
|
|
|
2469
2551
|
}): Promise<{
|
|
2470
2552
|
data: Buffer;
|
|
2471
2553
|
writeTime: number;
|
|
2554
|
+
size: number;
|
|
2472
2555
|
} | undefined>;
|
|
2473
2556
|
getConfig(): Promise<ArchivesConfig>;
|
|
2557
|
+
hasWriteAccess(): Promise<boolean>;
|
|
2474
2558
|
set(fileName: string, data: Buffer, config?: {
|
|
2475
2559
|
lastModified?: number;
|
|
2476
2560
|
}): Promise<void>;
|
|
@@ -2496,6 +2580,17 @@ declare module "sliftutils/storage/backblaze" {
|
|
|
2496
2580
|
size: number;
|
|
2497
2581
|
}[]>;
|
|
2498
2582
|
assertPathValid(path: string): Promise<void>;
|
|
2583
|
+
move(config: {
|
|
2584
|
+
path: string;
|
|
2585
|
+
target: IArchives;
|
|
2586
|
+
targetPath: string;
|
|
2587
|
+
copyInstead?: boolean;
|
|
2588
|
+
}): Promise<void>;
|
|
2589
|
+
copy(config: {
|
|
2590
|
+
path: string;
|
|
2591
|
+
target: IArchives;
|
|
2592
|
+
targetPath: string;
|
|
2593
|
+
}): Promise<void>;
|
|
2499
2594
|
getURL(path: string): Promise<string>;
|
|
2500
2595
|
getDownloadAuthorization(config: {
|
|
2501
2596
|
fileNamePrefix?: string;
|
|
@@ -2784,6 +2879,8 @@ declare module "sliftutils/storage/remoteStorage/ArchivesRemote" {
|
|
|
2784
2879
|
private controller;
|
|
2785
2880
|
private lastDeniedLog;
|
|
2786
2881
|
getDebugName(): string;
|
|
2882
|
+
isConnected(): boolean;
|
|
2883
|
+
ping(): Promise<void>;
|
|
2787
2884
|
private authenticate;
|
|
2788
2885
|
private callAuthed;
|
|
2789
2886
|
waitingForAccess(): Promise<{
|
|
@@ -2791,7 +2888,8 @@ declare module "sliftutils/storage/remoteStorage/ArchivesRemote" {
|
|
|
2791
2888
|
machineId: string;
|
|
2792
2889
|
ip: string;
|
|
2793
2890
|
} | undefined>;
|
|
2794
|
-
|
|
2891
|
+
hasWriteAccess(): Promise<boolean>;
|
|
2892
|
+
private registerAccessRequest;
|
|
2795
2893
|
private call;
|
|
2796
2894
|
get(fileName: string, config?: {
|
|
2797
2895
|
range?: {
|
|
@@ -2807,6 +2905,7 @@ declare module "sliftutils/storage/remoteStorage/ArchivesRemote" {
|
|
|
2807
2905
|
}): Promise<{
|
|
2808
2906
|
data: Buffer;
|
|
2809
2907
|
writeTime: number;
|
|
2908
|
+
size: number;
|
|
2810
2909
|
} | undefined>;
|
|
2811
2910
|
set(fileName: string, data: Buffer, config?: {
|
|
2812
2911
|
lastModified?: number;
|
|
@@ -2859,6 +2958,7 @@ declare module "sliftutils/storage/remoteStorage/ArchivesUrl" {
|
|
|
2859
2958
|
}): Promise<{
|
|
2860
2959
|
data: Buffer;
|
|
2861
2960
|
writeTime: number;
|
|
2961
|
+
size: number;
|
|
2862
2962
|
} | undefined>;
|
|
2863
2963
|
getInfo(fileName: string): Promise<{
|
|
2864
2964
|
writeTime: number;
|
|
@@ -2882,6 +2982,7 @@ declare module "sliftutils/storage/remoteStorage/ArchivesUrl" {
|
|
|
2882
2982
|
}): Promise<ArchiveFileInfo[]>;
|
|
2883
2983
|
getURL(path: string): Promise<string>;
|
|
2884
2984
|
getConfig(): Promise<ArchivesConfig>;
|
|
2985
|
+
hasWriteAccess(): Promise<boolean>;
|
|
2885
2986
|
}
|
|
2886
2987
|
|
|
2887
2988
|
}
|
|
@@ -2894,7 +2995,7 @@ declare module "sliftutils/storage/remoteStorage/accessPage" {
|
|
|
2894
2995
|
declare module "sliftutils/storage/remoteStorage/blobStore" {
|
|
2895
2996
|
/// <reference types="node" />
|
|
2896
2997
|
/// <reference types="node" />
|
|
2897
|
-
import { ArchiveFileInfo, ArchivesSource, ArchivesSyncStatus } from "../IArchives";
|
|
2998
|
+
import { ArchiveFileInfo, ArchivesSource, ArchivesSyncStatus, SyncActivity } from "../IArchives";
|
|
2898
2999
|
export declare const DEFAULT_FAST_WRITE_DELAY: number;
|
|
2899
3000
|
export type WriteConfig = {
|
|
2900
3001
|
fast?: boolean;
|
|
@@ -2916,6 +3017,7 @@ declare module "sliftutils/storage/remoteStorage/blobStore" {
|
|
|
2916
3017
|
}): Promise<{
|
|
2917
3018
|
data: Buffer;
|
|
2918
3019
|
writeTime: number;
|
|
3020
|
+
size: number;
|
|
2919
3021
|
} | undefined>;
|
|
2920
3022
|
set(fileName: string, data: Buffer, config?: WriteConfig): Promise<void>;
|
|
2921
3023
|
del(fileName: string, config?: WriteConfig): Promise<void>;
|
|
@@ -2929,6 +3031,17 @@ declare module "sliftutils/storage/remoteStorage/blobStore" {
|
|
|
2929
3031
|
}): Promise<ArchiveFileInfo[]>;
|
|
2930
3032
|
getChangesAfter?(time: number): Promise<ArchiveFileInfo[]>;
|
|
2931
3033
|
getSyncStatus?(): Promise<ArchivesSyncStatus>;
|
|
3034
|
+
getSyncProgress?(): {
|
|
3035
|
+
index: {
|
|
3036
|
+
fileCount: number;
|
|
3037
|
+
byteCount: number;
|
|
3038
|
+
};
|
|
3039
|
+
syncing: SyncActivity[];
|
|
3040
|
+
};
|
|
3041
|
+
computeIndexTotals?(): Promise<{
|
|
3042
|
+
fileCount: number;
|
|
3043
|
+
byteCount: number;
|
|
3044
|
+
}>;
|
|
2932
3045
|
startLargeUpload(): Promise<string>;
|
|
2933
3046
|
appendLargeUpload(id: string, data: Buffer): Promise<void>;
|
|
2934
3047
|
finishLargeUpload(id: string, key: string): Promise<void>;
|
|
@@ -2940,10 +3053,16 @@ declare module "sliftutils/storage/remoteStorage/blobStore" {
|
|
|
2940
3053
|
private config?;
|
|
2941
3054
|
constructor(folder: string, sources: ArchivesSource[], config?: {
|
|
2942
3055
|
onIndexChanged?: ((key: string) => void) | undefined;
|
|
3056
|
+
readerDiskLimit?: number | undefined;
|
|
2943
3057
|
} | undefined);
|
|
2944
3058
|
private stopped;
|
|
2945
3059
|
private index;
|
|
2946
3060
|
private mem;
|
|
3061
|
+
private indexFileCount;
|
|
3062
|
+
private indexByteCount;
|
|
3063
|
+
private sourceFileCounts;
|
|
3064
|
+
private sourceByteCounts;
|
|
3065
|
+
private syncActivities;
|
|
2947
3066
|
private dirty;
|
|
2948
3067
|
private overlay;
|
|
2949
3068
|
private sourceStates;
|
|
@@ -2954,11 +3073,38 @@ declare module "sliftutils/storage/remoteStorage/blobStore" {
|
|
|
2954
3073
|
};
|
|
2955
3074
|
dispose(): Promise<void>;
|
|
2956
3075
|
private loadIndex;
|
|
3076
|
+
private countEntry;
|
|
2957
3077
|
private setIndexEntry;
|
|
2958
3078
|
private deleteIndexEntry;
|
|
3079
|
+
/** The cheap always-current totals plus any in-progress background synchronization. */
|
|
3080
|
+
getSyncProgress(): {
|
|
3081
|
+
index: {
|
|
3082
|
+
fileCount: number;
|
|
3083
|
+
byteCount: number;
|
|
3084
|
+
};
|
|
3085
|
+
sources: {
|
|
3086
|
+
debugName: string;
|
|
3087
|
+
fileCount: number;
|
|
3088
|
+
byteCount: number;
|
|
3089
|
+
}[];
|
|
3090
|
+
readerDiskLimit?: number;
|
|
3091
|
+
syncing: SyncActivity[];
|
|
3092
|
+
};
|
|
3093
|
+
/** Walks the whole index for exact totals - more expensive than getSyncProgress, but immune to
|
|
3094
|
+
* any drift in the maintained counters (and loads the index first, so it's never cold zeros). */
|
|
3095
|
+
computeIndexTotals(): Promise<{
|
|
3096
|
+
fileCount: number;
|
|
3097
|
+
byteCount: number;
|
|
3098
|
+
sources: {
|
|
3099
|
+
debugName: string;
|
|
3100
|
+
fileCount: number;
|
|
3101
|
+
byteCount: number;
|
|
3102
|
+
}[];
|
|
3103
|
+
}>;
|
|
2959
3104
|
private flushIndex;
|
|
2960
3105
|
private runSourceSync;
|
|
2961
3106
|
private scanSource;
|
|
3107
|
+
private reconcileSource;
|
|
2962
3108
|
private applyScanned;
|
|
2963
3109
|
private pollChanges;
|
|
2964
3110
|
private copySourceFiles;
|
|
@@ -2979,12 +3125,13 @@ declare module "sliftutils/storage/remoteStorage/blobStore" {
|
|
|
2979
3125
|
}): Promise<{
|
|
2980
3126
|
data: Buffer;
|
|
2981
3127
|
writeTime: number;
|
|
3128
|
+
size: number;
|
|
2982
3129
|
} | undefined>;
|
|
2983
3130
|
private cacheRead;
|
|
2984
3131
|
set(key: string, data: Buffer, config?: WriteConfig): Promise<void>;
|
|
2985
|
-
private writeToSources;
|
|
2986
3132
|
del(key: string, config?: WriteConfig): Promise<void>;
|
|
2987
|
-
private
|
|
3133
|
+
private getWritableSources;
|
|
3134
|
+
private writeToSources;
|
|
2988
3135
|
getInfo(key: string): Promise<{
|
|
2989
3136
|
writeTime: number;
|
|
2990
3137
|
size: number;
|
|
@@ -3001,6 +3148,9 @@ declare module "sliftutils/storage/remoteStorage/blobStore" {
|
|
|
3001
3148
|
finishLargeUpload(id: string, key: string): Promise<void>;
|
|
3002
3149
|
cancelLargeUpload(id: string): Promise<void>;
|
|
3003
3150
|
private flushOverlay;
|
|
3151
|
+
private evicting;
|
|
3152
|
+
private enforceDiskLimit;
|
|
3153
|
+
private cleanupTombstones;
|
|
3004
3154
|
}
|
|
3005
3155
|
|
|
3006
3156
|
}
|
|
@@ -3016,19 +3166,23 @@ declare module "sliftutils/storage/remoteStorage/createArchives" {
|
|
|
3016
3166
|
import { IArchives, RemoteConfig, RemoteConfigBase, HostedConfig, BackblazeConfig, ArchiveFileInfo, ArchivesConfig, ArchivesSyncStatus } from "../IArchives";
|
|
3017
3167
|
export declare function createApiArchives(source: HostedConfig | BackblazeConfig): IArchives;
|
|
3018
3168
|
export declare class ArchivesChain implements IArchives {
|
|
3019
|
-
private
|
|
3020
|
-
private
|
|
3021
|
-
private
|
|
3169
|
+
private configured;
|
|
3170
|
+
private activeConfig;
|
|
3171
|
+
private statePromise;
|
|
3172
|
+
private initRetryDelay;
|
|
3173
|
+
private initRetryTimer;
|
|
3174
|
+
private pollTimer;
|
|
3175
|
+
private disposed;
|
|
3022
3176
|
constructor(config: RemoteConfig | RemoteConfigBase);
|
|
3023
3177
|
getDebugName(): string;
|
|
3024
|
-
private
|
|
3025
|
-
private getSources;
|
|
3178
|
+
private getState;
|
|
3026
3179
|
private init;
|
|
3027
|
-
private
|
|
3028
|
-
private
|
|
3029
|
-
private
|
|
3030
|
-
private
|
|
3031
|
-
private
|
|
3180
|
+
private buildSources;
|
|
3181
|
+
private startConfigPoll;
|
|
3182
|
+
private checkForNewConfig;
|
|
3183
|
+
private run;
|
|
3184
|
+
private runWrite;
|
|
3185
|
+
private request;
|
|
3032
3186
|
waitingForAccess(): Promise<{
|
|
3033
3187
|
link: string;
|
|
3034
3188
|
machineId: string;
|
|
@@ -3048,11 +3202,14 @@ declare module "sliftutils/storage/remoteStorage/createArchives" {
|
|
|
3048
3202
|
}): Promise<{
|
|
3049
3203
|
data: Buffer;
|
|
3050
3204
|
writeTime: number;
|
|
3205
|
+
size: number;
|
|
3051
3206
|
} | undefined>;
|
|
3052
3207
|
getInfo(fileName: string): Promise<{
|
|
3053
3208
|
writeTime: number;
|
|
3054
3209
|
size: number;
|
|
3055
3210
|
} | undefined>;
|
|
3211
|
+
private selectCoveringSources;
|
|
3212
|
+
private runOnApi;
|
|
3056
3213
|
find(prefix: string, config?: {
|
|
3057
3214
|
shallow?: boolean;
|
|
3058
3215
|
type: "files" | "folders";
|
|
@@ -3064,15 +3221,29 @@ declare module "sliftutils/storage/remoteStorage/createArchives" {
|
|
|
3064
3221
|
getChangesAfter(time: number): Promise<ArchiveFileInfo[]>;
|
|
3065
3222
|
getSyncStatus(): Promise<ArchivesSyncStatus>;
|
|
3066
3223
|
getConfig(): Promise<ArchivesConfig>;
|
|
3224
|
+
/** True only when EVERY write-receiving source would accept our writes (partial write access
|
|
3225
|
+
* desynchronizes sources, so it counts as no access). */
|
|
3226
|
+
hasWriteAccess(): Promise<boolean>;
|
|
3227
|
+
private assertNotBareVariableShard;
|
|
3067
3228
|
set(fileName: string, data: Buffer, config?: {
|
|
3068
3229
|
lastModified?: number;
|
|
3069
3230
|
}): Promise<void>;
|
|
3070
3231
|
del(fileName: string): Promise<void>;
|
|
3232
|
+
/** Writes a key containing the VARIABLE_SHARD sentinel: picks the lowest-latency up write
|
|
3233
|
+
* shard, materializes the key with a random value inside that shard's route, writes it, and
|
|
3234
|
+
* returns the FULL key actually written (the caller needs it to ever read the value back).
|
|
3235
|
+
* Unlike normal writes this CAN move to another shard when the preferred one is down (error +
|
|
3236
|
+
* socket down, same rule as reads) - each shard receives a different key, so write
|
|
3237
|
+
* consistency is preserved. */
|
|
3238
|
+
setVariableShard(key: string, data: Buffer, config?: {
|
|
3239
|
+
lastModified?: number;
|
|
3240
|
+
}): Promise<string>;
|
|
3071
3241
|
setLargeFile(config: {
|
|
3072
3242
|
path: string;
|
|
3073
3243
|
getNextData(): Promise<Buffer | undefined>;
|
|
3074
3244
|
}): Promise<void>;
|
|
3075
3245
|
getURL(path: string): Promise<string>;
|
|
3246
|
+
dispose(): void;
|
|
3076
3247
|
}
|
|
3077
3248
|
export declare function createArchives(config: RemoteConfig | RemoteConfigBase): ArchivesChain;
|
|
3078
3249
|
|
|
@@ -3088,6 +3259,14 @@ declare module "sliftutils/storage/remoteStorage/remoteConfig" {
|
|
|
3088
3259
|
/// <reference types="node" />
|
|
3089
3260
|
import { RemoteConfig, RemoteConfigBase, HostedConfig, BackblazeConfig } from "../IArchives";
|
|
3090
3261
|
export declare const ROUTING_FILE = "storage/storagerouting.json";
|
|
3262
|
+
/** The variable-shard route override embedded in the key ("<sentinel>_<value>", see VARIABLE_SHARD), or undefined when the key has no sentinel or the sentinel has no value yet. */
|
|
3263
|
+
export declare function parseVariableRoute(key: string): number | undefined;
|
|
3264
|
+
/** Where a key routes in [0, 1). A materialized variable-shard suffix completely overrides the hash. */
|
|
3265
|
+
export declare function getRoute(key: string): number;
|
|
3266
|
+
export declare function routeContains(route: [number, number] | undefined, value: number): boolean;
|
|
3267
|
+
export declare function routesOverlap(a: [number, number] | undefined, b: [number, number] | undefined): boolean;
|
|
3268
|
+
/** The overlap of two route ranges, or undefined when they don't overlap. */
|
|
3269
|
+
export declare function routeIntersection(a: [number, number] | undefined, b: [number, number] | undefined): [number, number] | undefined;
|
|
3091
3270
|
export declare function getConfigVersion(config: RemoteConfig): number;
|
|
3092
3271
|
/** Strips the routing-file suffix, leaving the bucket's public base URL (file paths append to it). */
|
|
3093
3272
|
export declare function getBucketBaseUrl(url: string): string;
|
|
@@ -3108,6 +3287,51 @@ declare module "sliftutils/storage/remoteStorage/remoteConfig" {
|
|
|
3108
3287
|
|
|
3109
3288
|
}
|
|
3110
3289
|
|
|
3290
|
+
declare module "sliftutils/storage/remoteStorage/sourceWrapper" {
|
|
3291
|
+
import { IArchives, HostedConfig, BackblazeConfig } from "../IArchives";
|
|
3292
|
+
import { ArchivesUrl } from "./ArchivesUrl";
|
|
3293
|
+
export declare const RETRY_START_DELAY: number;
|
|
3294
|
+
export declare const RETRY_MAX_DELAY: number;
|
|
3295
|
+
export declare const RETRY_GROWTH = 1.5;
|
|
3296
|
+
export declare class SourceWrapper {
|
|
3297
|
+
config: HostedConfig | BackblazeConfig;
|
|
3298
|
+
private background;
|
|
3299
|
+
api?: IArchives;
|
|
3300
|
+
url?: ArchivesUrl;
|
|
3301
|
+
writeBlocked?: string;
|
|
3302
|
+
private remote?;
|
|
3303
|
+
private disposed;
|
|
3304
|
+
private reconnectRunning;
|
|
3305
|
+
private accessCache?;
|
|
3306
|
+
private constructor();
|
|
3307
|
+
static create(config: HostedConfig | BackblazeConfig, options?: {
|
|
3308
|
+
background?: boolean;
|
|
3309
|
+
}): Promise<SourceWrapper>;
|
|
3310
|
+
getDebugName(): string;
|
|
3311
|
+
isConnected(): boolean;
|
|
3312
|
+
/** Call after a request failed while isConnected() was false: starts (if not already running)
|
|
3313
|
+
* the background reconnect loop. Never blocks - the failed request still throws. */
|
|
3314
|
+
noteFailure(): void;
|
|
3315
|
+
private reconnectLoop;
|
|
3316
|
+
private checkAccess;
|
|
3317
|
+
read<T>(run: (archives: IArchives) => Promise<T>): Promise<T>;
|
|
3318
|
+
hasWriteAccess(): Promise<boolean>;
|
|
3319
|
+
private pings;
|
|
3320
|
+
private pingTimer;
|
|
3321
|
+
/** Starts measuring this source's latency (for variable-shard target preference). Only hosted
|
|
3322
|
+
* remotes are pinged; our own local server counts as 0, everything else as Infinity. */
|
|
3323
|
+
startPinging(): void;
|
|
3324
|
+
/** Median of the recent pings. Sources that can't be pinged sort last (Infinity), except our
|
|
3325
|
+
* own in-process server, which is the best possible target (0). */
|
|
3326
|
+
getLatency(): number;
|
|
3327
|
+
/** Writes always go through the API, so a permission error throws to the caller on every write
|
|
3328
|
+
* (and access granted in the meantime is picked up automatically). */
|
|
3329
|
+
write<T>(run: (archives: IArchives) => Promise<T>): Promise<T>;
|
|
3330
|
+
dispose(): void;
|
|
3331
|
+
}
|
|
3332
|
+
|
|
3333
|
+
}
|
|
3334
|
+
|
|
3111
3335
|
declare module "sliftutils/storage/remoteStorage/storageController" {
|
|
3112
3336
|
/// <reference types="node" />
|
|
3113
3337
|
/// <reference types="node" />
|
|
@@ -3142,6 +3366,7 @@ declare module "sliftutils/storage/remoteStorage/storageController" {
|
|
|
3142
3366
|
trustedMachines?: TrustRecord[];
|
|
3143
3367
|
};
|
|
3144
3368
|
export declare const RemoteStorageController: import("socket-function/SocketFunctionTypes").SocketRegistered<{
|
|
3369
|
+
ping: () => Promise<void>;
|
|
3145
3370
|
authenticate: (token: AuthToken) => Promise<{
|
|
3146
3371
|
machineId: string;
|
|
3147
3372
|
ip: string;
|
|
@@ -3167,6 +3392,7 @@ declare module "sliftutils/storage/remoteStorage/storageController" {
|
|
|
3167
3392
|
}) => Promise<{
|
|
3168
3393
|
data: Buffer;
|
|
3169
3394
|
writeTime: number;
|
|
3395
|
+
size: number;
|
|
3170
3396
|
} | undefined>;
|
|
3171
3397
|
set: (account: string, bucketName: string, path: string, data: Buffer, lastModified?: number) => Promise<void>;
|
|
3172
3398
|
del: (account: string, bucketName: string, path: string) => Promise<void>;
|
|
@@ -3180,6 +3406,15 @@ declare module "sliftutils/storage/remoteStorage/storageController" {
|
|
|
3180
3406
|
}) => Promise<ArchiveFileInfo[]>;
|
|
3181
3407
|
getChangesAfter: (account: string, bucketName: string, time: number) => Promise<ArchiveFileInfo[]>;
|
|
3182
3408
|
getArchivesConfig: (account: string, bucketName: string) => Promise<ArchivesConfig>;
|
|
3409
|
+
getIndexInfo: (account: string, bucketName: string) => Promise<{
|
|
3410
|
+
fileCount: number;
|
|
3411
|
+
byteCount: number;
|
|
3412
|
+
sources: {
|
|
3413
|
+
debugName: string;
|
|
3414
|
+
fileCount: number;
|
|
3415
|
+
byteCount: number;
|
|
3416
|
+
}[];
|
|
3417
|
+
} | undefined>;
|
|
3183
3418
|
getSyncStatus: (account: string, bucketName: string) => Promise<ArchivesSyncStatus>;
|
|
3184
3419
|
startLargeFile: (account: string, bucketName: string, path: string) => Promise<string>;
|
|
3185
3420
|
uploadPart: (uploadId: string, data: Buffer) => Promise<void>;
|
|
@@ -3198,11 +3433,6 @@ declare module "sliftutils/storage/remoteStorage/storageServer" {
|
|
|
3198
3433
|
export type HostStorageServerConfig = {
|
|
3199
3434
|
url: string;
|
|
3200
3435
|
folder: string;
|
|
3201
|
-
cloudflareApiToken?: {
|
|
3202
|
-
key: string;
|
|
3203
|
-
} | {
|
|
3204
|
-
path: string;
|
|
3205
|
-
};
|
|
3206
3436
|
lowSpaceThresholdBytes?: number;
|
|
3207
3437
|
};
|
|
3208
3438
|
export declare function hostStorageServer(config: HostStorageServerConfig): Promise<void>;
|
|
@@ -3237,16 +3467,22 @@ declare module "sliftutils/storage/remoteStorage/storageServerState" {
|
|
|
3237
3467
|
export declare function assertWritesAllowed(): void;
|
|
3238
3468
|
export declare function getTrust(): Promise<IStorage<TrustRecord>>;
|
|
3239
3469
|
export declare function getRequests(): Promise<IStorage<AccessRequest[]>>;
|
|
3470
|
+
/** Makes machineIds the complete trust list for the account: machines not in the list lose access, machines already trusted keep their existing record, and missing ones are added. */
|
|
3471
|
+
export declare function setTrustedMachines(config: {
|
|
3472
|
+
account: string;
|
|
3473
|
+
machineIds: string[];
|
|
3474
|
+
}): Promise<void>;
|
|
3240
3475
|
export type LoadedBucket = {
|
|
3241
3476
|
account: string;
|
|
3242
3477
|
bucketName: string;
|
|
3243
3478
|
routing: RemoteConfig;
|
|
3244
3479
|
routingJSON: string;
|
|
3480
|
+
selfEntries: HostedConfig[];
|
|
3245
3481
|
self: HostedConfig | undefined;
|
|
3246
3482
|
store: IBucketStore;
|
|
3247
3483
|
};
|
|
3248
3484
|
export declare function getLoadedBucket(account: string, bucketName: string): Promise<LoadedBucket | undefined>;
|
|
3249
|
-
export declare function assertMutable(bucket: LoadedBucket, filePath: string): Promise<void>;
|
|
3485
|
+
export declare function assertMutable(bucket: LoadedBucket, filePath: string, writeTime: number): Promise<void>;
|
|
3250
3486
|
export declare function writeBucketFile(account: string, bucketName: string, filePath: string, data: Buffer, config?: {
|
|
3251
3487
|
lastModified?: number;
|
|
3252
3488
|
}): Promise<void>;
|