sliftutils 1.7.9 → 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/bin/storageserver.js +4 -0
- package/{teststorage → examplestorage}/browser.tsx +18 -22
- package/{teststorage/server.ts → examplestorage/exampleserver.ts} +4 -6
- package/index.d.ts +770 -84
- 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 -8
- package/misc/https/dns.ts +104 -106
- package/misc/https/hostServer.d.ts +0 -3
- package/misc/https/hostServer.ts +12 -8
- package/package.json +3 -2
- package/render-utils/dist/observer.tsx.cache +3 -2
- package/spec.txt +0 -55
- package/storage/ArchivesDisk.d.ts +67 -0
- package/storage/ArchivesDisk.ts +369 -0
- 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 +127 -1
- package/storage/IArchives.ts +201 -1
- package/storage/backblaze.d.ts +29 -2
- package/storage/backblaze.ts +214 -78
- 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 +34 -18
- package/storage/remoteStorage/ArchivesRemote.ts +85 -65
- package/storage/remoteStorage/ArchivesUrl.d.ts +48 -0
- package/storage/remoteStorage/ArchivesUrl.ts +86 -0
- package/storage/remoteStorage/accessPage.tsx +111 -28
- package/storage/remoteStorage/blobStore.d.ts +128 -25
- package/storage/remoteStorage/blobStore.ts +757 -290
- package/storage/remoteStorage/cliArgs.d.ts +1 -0
- package/storage/remoteStorage/cliArgs.ts +9 -0
- package/storage/remoteStorage/createArchives.d.ts +85 -0
- package/storage/remoteStorage/createArchives.ts +612 -0
- 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/grantAccess.js +4 -0
- package/storage/remoteStorage/grantAccessCli.d.ts +1 -0
- package/storage/remoteStorage/grantAccessCli.ts +27 -0
- package/storage/remoteStorage/remoteConfig.d.ts +29 -0
- package/storage/remoteStorage/remoteConfig.ts +194 -0
- 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 +30 -27
- package/storage/remoteStorage/storageController.ts +297 -159
- package/storage/remoteStorage/storageServer.d.ts +6 -0
- package/storage/remoteStorage/storageServer.ts +88 -94
- package/storage/remoteStorage/storageServerCli.d.ts +1 -0
- package/storage/remoteStorage/storageServerCli.ts +38 -0
- package/storage/remoteStorage/storageServerState.d.ts +43 -0
- package/storage/remoteStorage/storageServerState.ts +540 -0
- package/testsite/server.ts +0 -2
- package/yarn.lock +11 -6
package/index.d.ts
CHANGED
|
@@ -136,25 +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 (an API token, or a path to a file containing one), instead of relying on ./cloudflare.json */
|
|
154
|
-
export declare function setCloudflareCredentials(config: {
|
|
155
|
-
key?: string;
|
|
156
|
-
path?: string;
|
|
157
|
-
}): void;
|
|
213
|
+
export declare function addRecord(type: string, key: string, value: string, proxied?: "proxied", staleAfter?: number): Promise<void>;
|
|
158
214
|
|
|
159
215
|
}
|
|
160
216
|
|
|
@@ -163,9 +219,6 @@ declare module "sliftutils/misc/https/hostServer" {
|
|
|
163
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). */
|
|
164
220
|
domain: string;
|
|
165
221
|
port: number;
|
|
166
|
-
/** Cloudflare API token (or a path to a file containing one). If neither is given, ./cloudflare.json is used. */
|
|
167
|
-
cloudflareApiToken?: string;
|
|
168
|
-
cloudflareApiTokenPath?: string;
|
|
169
222
|
/** Creates an unproxied A record pointing domain at this machine (publicIp, or our detected external IP) */
|
|
170
223
|
setDNSRecord?: boolean;
|
|
171
224
|
publicIp?: string;
|
|
@@ -796,6 +849,77 @@ declare module "sliftutils/render-utils/observer" {
|
|
|
796
849
|
|
|
797
850
|
}
|
|
798
851
|
|
|
852
|
+
declare module "sliftutils/storage/ArchivesDisk" {
|
|
853
|
+
/// <reference types="node" />
|
|
854
|
+
/// <reference types="node" />
|
|
855
|
+
import { IArchives, ArchiveFileInfo, ArchivesConfig } from "./IArchives";
|
|
856
|
+
export declare class ArchivesDisk implements IArchives {
|
|
857
|
+
private folder;
|
|
858
|
+
constructor(folder: string);
|
|
859
|
+
private filesDir;
|
|
860
|
+
private uploadsDir;
|
|
861
|
+
private handles;
|
|
862
|
+
private largeUploads;
|
|
863
|
+
private nextLargeUploadId;
|
|
864
|
+
init: {
|
|
865
|
+
(): Promise<void>;
|
|
866
|
+
reset(): void;
|
|
867
|
+
set(newValue: Promise<void>): void;
|
|
868
|
+
};
|
|
869
|
+
getDebugName(): string;
|
|
870
|
+
getConfig(): Promise<ArchivesConfig>;
|
|
871
|
+
hasWriteAccess(): Promise<boolean>;
|
|
872
|
+
private filePath;
|
|
873
|
+
set(key: string, data: Buffer, config?: {
|
|
874
|
+
lastModified?: number;
|
|
875
|
+
}): Promise<void>;
|
|
876
|
+
del(key: string): Promise<void>;
|
|
877
|
+
get(key: string, config?: {
|
|
878
|
+
range?: {
|
|
879
|
+
start: number;
|
|
880
|
+
end: number;
|
|
881
|
+
};
|
|
882
|
+
}): Promise<Buffer | undefined>;
|
|
883
|
+
get2(key: string, config?: {
|
|
884
|
+
range?: {
|
|
885
|
+
start: number;
|
|
886
|
+
end: number;
|
|
887
|
+
};
|
|
888
|
+
}): Promise<{
|
|
889
|
+
data: Buffer;
|
|
890
|
+
writeTime: number;
|
|
891
|
+
size: number;
|
|
892
|
+
} | undefined>;
|
|
893
|
+
getInfo(key: string): Promise<{
|
|
894
|
+
writeTime: number;
|
|
895
|
+
size: number;
|
|
896
|
+
} | undefined>;
|
|
897
|
+
find(prefix: string, config?: {
|
|
898
|
+
shallow?: boolean;
|
|
899
|
+
type: "files" | "folders";
|
|
900
|
+
}): Promise<string[]>;
|
|
901
|
+
findInfo(prefix: string, config?: {
|
|
902
|
+
shallow?: boolean;
|
|
903
|
+
type?: "files" | "folders";
|
|
904
|
+
}): Promise<ArchiveFileInfo[]>;
|
|
905
|
+
private collectFiles;
|
|
906
|
+
setLargeFile(config: {
|
|
907
|
+
path: string;
|
|
908
|
+
getNextData(): Promise<Buffer | undefined>;
|
|
909
|
+
}): Promise<void>;
|
|
910
|
+
startLargeUpload(): Promise<string>;
|
|
911
|
+
appendLargeUpload(id: string, data: Buffer): Promise<void>;
|
|
912
|
+
finishLargeUpload(id: string, key: string): Promise<void>;
|
|
913
|
+
cancelLargeUpload(id: string): Promise<void>;
|
|
914
|
+
getURL(path: string): Promise<string>;
|
|
915
|
+
}
|
|
916
|
+
export declare function applyFindInfoShape(files: ArchiveFileInfo[], prefix: string, config?: {
|
|
917
|
+
shallow?: boolean;
|
|
918
|
+
type?: "files" | "folders";
|
|
919
|
+
}): ArchiveFileInfo[];
|
|
920
|
+
|
|
921
|
+
}
|
|
922
|
+
|
|
799
923
|
declare module "sliftutils/storage/BulkDatabase2/BulkDatabase2" {
|
|
800
924
|
import { BulkDatabaseBase, ReactiveDeps, BulkDatabase2Config, BulkFileInfoListing, MergeAttemptResult } from "./BulkDatabaseBase";
|
|
801
925
|
export { BulkDatabaseBase, noopReactiveDeps, bulkDatabase2Timing } from "./BulkDatabaseBase";
|
|
@@ -1972,26 +2096,143 @@ declare module "sliftutils/storage/FileFolderAPI" {
|
|
|
1972
2096
|
declare module "sliftutils/storage/IArchives" {
|
|
1973
2097
|
/// <reference types="node" />
|
|
1974
2098
|
/// <reference types="node" />
|
|
2099
|
+
export declare const MAX_LAST_MODIFIED_FUTURE: number;
|
|
2100
|
+
export declare const IMMUTABLE_CACHE_TIME: number;
|
|
2101
|
+
export declare function assertValidLastModified(lastModified: number): void;
|
|
2102
|
+
export type RemoteConfig = {
|
|
2103
|
+
version?: number;
|
|
2104
|
+
sources: RemoteConfigBase[];
|
|
2105
|
+
};
|
|
2106
|
+
/**
|
|
2107
|
+
string arguments will be a url, looking like:
|
|
2108
|
+
https://storage2.vidgridweb.com:4445/file/exampleaccount/examplebucket/storage/storagerouting.json
|
|
2109
|
+
https://f002.backblazeb2.com/file/querysubtest-com-public-immutable/storage/storagerouting.json
|
|
2110
|
+
- These map to { url }, with the type inferred from the url
|
|
2111
|
+
- Hosted urls are /file/<account>/<bucketName>/..., backblaze urls are /file/<bucketName>/...
|
|
2112
|
+
|
|
2113
|
+
NOTE: If we do not have right access to these, then it becomes a read-only IArchives, where we solely read using the url form (which might throw due to not having access as well). UNLESS Our configuration explicitly has public: false, in which case, we don't even hit the URL and we throw on access.
|
|
2114
|
+
|
|
2115
|
+
NOTE: If we're in the browser, we should allow downloading the files via the URL form (if it's a public bucket), however, we won't allow writing, because their servers do not allow secure browser writes.
|
|
2116
|
+
*/
|
|
2117
|
+
export type RemoteConfigBase = string | HostedConfig | BackblazeConfig;
|
|
2118
|
+
export type CommonConfig = {
|
|
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];
|
|
2127
|
+
};
|
|
2128
|
+
export type HostedConfig = CommonConfig & {
|
|
2129
|
+
type: "remote";
|
|
2130
|
+
url: string;
|
|
2131
|
+
accountName?: string;
|
|
2132
|
+
public?: boolean;
|
|
2133
|
+
fast?: boolean;
|
|
2134
|
+
writeDelay?: number;
|
|
2135
|
+
rawDisk?: boolean;
|
|
2136
|
+
immutable?: boolean;
|
|
2137
|
+
};
|
|
2138
|
+
export type BackblazeConfig = CommonConfig & {
|
|
2139
|
+
type: "backblaze";
|
|
2140
|
+
url: string;
|
|
2141
|
+
public?: boolean;
|
|
2142
|
+
immutable?: boolean;
|
|
2143
|
+
};
|
|
2144
|
+
export declare const FULL_VALID_WINDOW: [number, number];
|
|
1975
2145
|
export type ArchiveFileInfo = {
|
|
1976
2146
|
path: string;
|
|
1977
2147
|
createTime: number;
|
|
1978
2148
|
size: number;
|
|
1979
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
|
+
};
|
|
2159
|
+
export type ArchivesConfig = {
|
|
2160
|
+
supportsChangesAfter?: boolean;
|
|
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[];
|
|
2173
|
+
};
|
|
2174
|
+
export type ArchivesSource = {
|
|
2175
|
+
source: IArchives;
|
|
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;
|
|
2186
|
+
export type ArchivesSyncSourceStatus = {
|
|
2187
|
+
debugName: string;
|
|
2188
|
+
validWindow: [number, number];
|
|
2189
|
+
route?: [number, number];
|
|
2190
|
+
noFullSync?: boolean;
|
|
2191
|
+
supportsChangesAfter: boolean;
|
|
2192
|
+
initialScanComplete: boolean;
|
|
2193
|
+
scannedCount: number;
|
|
2194
|
+
};
|
|
2195
|
+
export type ArchivesSyncStatus = {
|
|
2196
|
+
allScansComplete: boolean;
|
|
2197
|
+
indexSize: number;
|
|
2198
|
+
sources: ArchivesSyncSourceStatus[];
|
|
2199
|
+
};
|
|
1980
2200
|
export interface IArchives {
|
|
1981
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>;
|
|
1982
2205
|
get(fileName: string, config?: {
|
|
1983
2206
|
range?: {
|
|
1984
2207
|
start: number;
|
|
1985
2208
|
end: number;
|
|
1986
2209
|
};
|
|
1987
2210
|
}): Promise<Buffer | undefined>;
|
|
1988
|
-
|
|
2211
|
+
get2(fileName: string, config?: {
|
|
2212
|
+
range?: {
|
|
2213
|
+
start: number;
|
|
2214
|
+
end: number;
|
|
2215
|
+
};
|
|
2216
|
+
}): Promise<{
|
|
2217
|
+
data: Buffer;
|
|
2218
|
+
writeTime: number;
|
|
2219
|
+
size: number;
|
|
2220
|
+
} | undefined>;
|
|
2221
|
+
/**
|
|
2222
|
+
* lastModified stamps the write with that last-write time instead of now. If it is OLDER than
|
|
2223
|
+
* the file's current last-write time the write no-ops (so delayed / synchronized writes can
|
|
2224
|
+
* never clobber newer data). Times more than 15 minutes in the future are rejected.
|
|
2225
|
+
*/
|
|
2226
|
+
set(fileName: string, data: Buffer, config?: {
|
|
2227
|
+
lastModified?: number;
|
|
2228
|
+
}): Promise<void>;
|
|
1989
2229
|
del(fileName: string): Promise<void>;
|
|
1990
2230
|
/** Streams a file too large to hold in memory. getNextData returns undefined when done. */
|
|
1991
2231
|
setLargeFile(config: {
|
|
1992
2232
|
path: string;
|
|
1993
2233
|
getNextData(): Promise<Buffer | undefined>;
|
|
1994
2234
|
}): Promise<void>;
|
|
2235
|
+
/** writeTime is the last-write time — see ArchiveFileInfo.createTime, which is the same value. */
|
|
1995
2236
|
getInfo(fileName: string): Promise<{
|
|
1996
2237
|
writeTime: number;
|
|
1997
2238
|
size: number;
|
|
@@ -2006,6 +2247,15 @@ declare module "sliftutils/storage/IArchives" {
|
|
|
2006
2247
|
}): Promise<ArchiveFileInfo[]>;
|
|
2007
2248
|
/** Only works for public buckets (private buckets are API-access only). */
|
|
2008
2249
|
getURL(path: string): Promise<string>;
|
|
2250
|
+
/** The bucket's configuration, which tells whether the optional functions are supported. */
|
|
2251
|
+
getConfig(): Promise<ArchivesConfig>;
|
|
2252
|
+
/**
|
|
2253
|
+
* All files changed after the given time. Only exists when getConfig().supportsChangesAfter;
|
|
2254
|
+
* backed by an index, so it is fast (unlike a full findInfo scan). Deletions are not reported.
|
|
2255
|
+
*/
|
|
2256
|
+
getChangesAfter?(time: number): Promise<ArchiveFileInfo[]>;
|
|
2257
|
+
/** Synchronization introspection, for backends that synchronize from sources (see BlobStore). */
|
|
2258
|
+
getSyncStatus?(): Promise<ArchivesSyncStatus>;
|
|
2009
2259
|
}
|
|
2010
2260
|
|
|
2011
2261
|
}
|
|
@@ -2266,7 +2516,7 @@ declare module "sliftutils/storage/TransactionStorage" {
|
|
|
2266
2516
|
declare module "sliftutils/storage/backblaze" {
|
|
2267
2517
|
/// <reference types="node" />
|
|
2268
2518
|
/// <reference types="node" />
|
|
2269
|
-
import { IArchives } from "./IArchives";
|
|
2519
|
+
import { IArchives, ArchivesConfig } from "./IArchives";
|
|
2270
2520
|
export declare class ArchivesBackblaze implements IArchives {
|
|
2271
2521
|
private config;
|
|
2272
2522
|
constructor(config: {
|
|
@@ -2274,6 +2524,7 @@ declare module "sliftutils/storage/backblaze" {
|
|
|
2274
2524
|
public?: boolean;
|
|
2275
2525
|
immutable?: boolean;
|
|
2276
2526
|
cacheTime?: number;
|
|
2527
|
+
allowedOrigins?: string[];
|
|
2277
2528
|
});
|
|
2278
2529
|
private bucketName;
|
|
2279
2530
|
private bucketId;
|
|
@@ -2282,6 +2533,7 @@ declare module "sliftutils/storage/backblaze" {
|
|
|
2282
2533
|
private log;
|
|
2283
2534
|
getDebugName(): string;
|
|
2284
2535
|
private getBucketAPI;
|
|
2536
|
+
private currentReset;
|
|
2285
2537
|
private last503Reset;
|
|
2286
2538
|
private apiRetryLogic;
|
|
2287
2539
|
get(fileName: string, config?: {
|
|
@@ -2291,7 +2543,21 @@ declare module "sliftutils/storage/backblaze" {
|
|
|
2291
2543
|
};
|
|
2292
2544
|
retryCount?: number;
|
|
2293
2545
|
}): Promise<Buffer | undefined>;
|
|
2294
|
-
|
|
2546
|
+
get2(fileName: string, config?: {
|
|
2547
|
+
range?: {
|
|
2548
|
+
start: number;
|
|
2549
|
+
end: number;
|
|
2550
|
+
};
|
|
2551
|
+
}): Promise<{
|
|
2552
|
+
data: Buffer;
|
|
2553
|
+
writeTime: number;
|
|
2554
|
+
size: number;
|
|
2555
|
+
} | undefined>;
|
|
2556
|
+
getConfig(): Promise<ArchivesConfig>;
|
|
2557
|
+
hasWriteAccess(): Promise<boolean>;
|
|
2558
|
+
set(fileName: string, data: Buffer, config?: {
|
|
2559
|
+
lastModified?: number;
|
|
2560
|
+
}): Promise<void>;
|
|
2295
2561
|
del(fileName: string): Promise<void>;
|
|
2296
2562
|
setLargeFile(config: {
|
|
2297
2563
|
path: string;
|
|
@@ -2314,6 +2580,17 @@ declare module "sliftutils/storage/backblaze" {
|
|
|
2314
2580
|
size: number;
|
|
2315
2581
|
}[]>;
|
|
2316
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>;
|
|
2317
2594
|
getURL(path: string): Promise<string>;
|
|
2318
2595
|
getDownloadAuthorization(config: {
|
|
2319
2596
|
fileNamePrefix?: string;
|
|
@@ -2574,23 +2851,16 @@ declare module "sliftutils/storage/remoteFileStorage" {
|
|
|
2574
2851
|
declare module "sliftutils/storage/remoteStorage/ArchivesRemote" {
|
|
2575
2852
|
/// <reference types="node" />
|
|
2576
2853
|
/// <reference types="node" />
|
|
2577
|
-
import { IArchives, ArchiveFileInfo } from "../IArchives";
|
|
2854
|
+
import { IArchives, ArchiveFileInfo, ArchivesConfig, ArchivesSyncStatus } from "../IArchives";
|
|
2578
2855
|
export type ArchivesRemoteConfig = {
|
|
2579
|
-
|
|
2580
|
-
|
|
2581
|
-
|
|
2582
|
-
bucketName: string;
|
|
2583
|
-
public?: boolean;
|
|
2584
|
-
fast?: boolean;
|
|
2585
|
-
writeDelay?: number;
|
|
2856
|
+
url: string;
|
|
2857
|
+
accountName?: string;
|
|
2858
|
+
waitForAccess?: boolean;
|
|
2586
2859
|
};
|
|
2587
|
-
export declare function
|
|
2860
|
+
export declare function parseStorageUrl(url: string): {
|
|
2588
2861
|
address: string;
|
|
2589
2862
|
port: number;
|
|
2590
|
-
|
|
2591
|
-
bucketName: string;
|
|
2592
|
-
path: string;
|
|
2593
|
-
}): string;
|
|
2863
|
+
};
|
|
2594
2864
|
export declare function authenticateStorage(config: {
|
|
2595
2865
|
address: string;
|
|
2596
2866
|
port: number;
|
|
@@ -2602,16 +2872,24 @@ declare module "sliftutils/storage/remoteStorage/ArchivesRemote" {
|
|
|
2602
2872
|
export declare class ArchivesRemote implements IArchives {
|
|
2603
2873
|
private config;
|
|
2604
2874
|
constructor(config: ArchivesRemoteConfig);
|
|
2875
|
+
private parsed;
|
|
2876
|
+
private account;
|
|
2877
|
+
private bucketName;
|
|
2605
2878
|
private nodeId;
|
|
2606
2879
|
private controller;
|
|
2607
|
-
private setupDone;
|
|
2608
2880
|
private lastDeniedLog;
|
|
2609
2881
|
getDebugName(): string;
|
|
2882
|
+
isConnected(): boolean;
|
|
2883
|
+
ping(): Promise<void>;
|
|
2610
2884
|
private authenticate;
|
|
2611
2885
|
private callAuthed;
|
|
2612
|
-
waitingForAccess(): Promise<
|
|
2613
|
-
|
|
2614
|
-
|
|
2886
|
+
waitingForAccess(): Promise<{
|
|
2887
|
+
link: string;
|
|
2888
|
+
machineId: string;
|
|
2889
|
+
ip: string;
|
|
2890
|
+
} | undefined>;
|
|
2891
|
+
hasWriteAccess(): Promise<boolean>;
|
|
2892
|
+
private registerAccessRequest;
|
|
2615
2893
|
private call;
|
|
2616
2894
|
get(fileName: string, config?: {
|
|
2617
2895
|
range?: {
|
|
@@ -2619,7 +2897,19 @@ declare module "sliftutils/storage/remoteStorage/ArchivesRemote" {
|
|
|
2619
2897
|
end: number;
|
|
2620
2898
|
};
|
|
2621
2899
|
}): Promise<Buffer | undefined>;
|
|
2622
|
-
|
|
2900
|
+
get2(fileName: string, config?: {
|
|
2901
|
+
range?: {
|
|
2902
|
+
start: number;
|
|
2903
|
+
end: number;
|
|
2904
|
+
};
|
|
2905
|
+
}): Promise<{
|
|
2906
|
+
data: Buffer;
|
|
2907
|
+
writeTime: number;
|
|
2908
|
+
size: number;
|
|
2909
|
+
} | undefined>;
|
|
2910
|
+
set(fileName: string, data: Buffer, config?: {
|
|
2911
|
+
lastModified?: number;
|
|
2912
|
+
}): Promise<void>;
|
|
2623
2913
|
del(fileName: string): Promise<void>;
|
|
2624
2914
|
getInfo(fileName: string): Promise<{
|
|
2625
2915
|
writeTime: number;
|
|
@@ -2633,6 +2923,9 @@ declare module "sliftutils/storage/remoteStorage/ArchivesRemote" {
|
|
|
2633
2923
|
shallow?: boolean;
|
|
2634
2924
|
type: "files" | "folders";
|
|
2635
2925
|
}): Promise<string[]>;
|
|
2926
|
+
getChangesAfter(time: number): Promise<ArchiveFileInfo[]>;
|
|
2927
|
+
getConfig(): Promise<ArchivesConfig>;
|
|
2928
|
+
getSyncStatus(): Promise<ArchivesSyncStatus>;
|
|
2636
2929
|
setLargeFile(config: {
|
|
2637
2930
|
path: string;
|
|
2638
2931
|
getNextData(): Promise<Buffer | undefined>;
|
|
@@ -2642,6 +2935,58 @@ declare module "sliftutils/storage/remoteStorage/ArchivesRemote" {
|
|
|
2642
2935
|
|
|
2643
2936
|
}
|
|
2644
2937
|
|
|
2938
|
+
declare module "sliftutils/storage/remoteStorage/ArchivesUrl" {
|
|
2939
|
+
/// <reference types="node" />
|
|
2940
|
+
/// <reference types="node" />
|
|
2941
|
+
import { IArchives, ArchiveFileInfo, ArchivesConfig } from "../IArchives";
|
|
2942
|
+
export declare class ArchivesUrl implements IArchives {
|
|
2943
|
+
private base;
|
|
2944
|
+
constructor(base: string);
|
|
2945
|
+
getDebugName(): string;
|
|
2946
|
+
private readOnlyError;
|
|
2947
|
+
get(fileName: string, config?: {
|
|
2948
|
+
range?: {
|
|
2949
|
+
start: number;
|
|
2950
|
+
end: number;
|
|
2951
|
+
};
|
|
2952
|
+
}): Promise<Buffer | undefined>;
|
|
2953
|
+
get2(fileName: string, config?: {
|
|
2954
|
+
range?: {
|
|
2955
|
+
start: number;
|
|
2956
|
+
end: number;
|
|
2957
|
+
};
|
|
2958
|
+
}): Promise<{
|
|
2959
|
+
data: Buffer;
|
|
2960
|
+
writeTime: number;
|
|
2961
|
+
size: number;
|
|
2962
|
+
} | undefined>;
|
|
2963
|
+
getInfo(fileName: string): Promise<{
|
|
2964
|
+
writeTime: number;
|
|
2965
|
+
size: number;
|
|
2966
|
+
} | undefined>;
|
|
2967
|
+
set(fileName: string, data: Buffer, config?: {
|
|
2968
|
+
lastModified?: number;
|
|
2969
|
+
}): Promise<void>;
|
|
2970
|
+
del(fileName: string): Promise<void>;
|
|
2971
|
+
setLargeFile(config: {
|
|
2972
|
+
path: string;
|
|
2973
|
+
getNextData(): Promise<Buffer | undefined>;
|
|
2974
|
+
}): Promise<void>;
|
|
2975
|
+
find(prefix: string, config?: {
|
|
2976
|
+
shallow?: boolean;
|
|
2977
|
+
type: "files" | "folders";
|
|
2978
|
+
}): Promise<string[]>;
|
|
2979
|
+
findInfo(prefix: string, config?: {
|
|
2980
|
+
shallow?: boolean;
|
|
2981
|
+
type: "files" | "folders";
|
|
2982
|
+
}): Promise<ArchiveFileInfo[]>;
|
|
2983
|
+
getURL(path: string): Promise<string>;
|
|
2984
|
+
getConfig(): Promise<ArchivesConfig>;
|
|
2985
|
+
hasWriteAccess(): Promise<boolean>;
|
|
2986
|
+
}
|
|
2987
|
+
|
|
2988
|
+
}
|
|
2989
|
+
|
|
2645
2990
|
declare module "sliftutils/storage/remoteStorage/accessPage" {
|
|
2646
2991
|
export {};
|
|
2647
2992
|
|
|
@@ -2650,45 +2995,143 @@ declare module "sliftutils/storage/remoteStorage/accessPage" {
|
|
|
2650
2995
|
declare module "sliftutils/storage/remoteStorage/blobStore" {
|
|
2651
2996
|
/// <reference types="node" />
|
|
2652
2997
|
/// <reference types="node" />
|
|
2653
|
-
import { ArchiveFileInfo } from "../IArchives";
|
|
2998
|
+
import { ArchiveFileInfo, ArchivesSource, ArchivesSyncStatus, SyncActivity } from "../IArchives";
|
|
2654
2999
|
export declare const DEFAULT_FAST_WRITE_DELAY: number;
|
|
2655
3000
|
export type WriteConfig = {
|
|
2656
3001
|
fast?: boolean;
|
|
2657
3002
|
writeDelay?: number;
|
|
3003
|
+
lastModified?: number;
|
|
3004
|
+
};
|
|
3005
|
+
export type IBucketStore = {
|
|
3006
|
+
get(fileName: string, config?: {
|
|
3007
|
+
range?: {
|
|
3008
|
+
start: number;
|
|
3009
|
+
end: number;
|
|
3010
|
+
};
|
|
3011
|
+
}): Promise<Buffer | undefined>;
|
|
3012
|
+
get2(fileName: string, config?: {
|
|
3013
|
+
range?: {
|
|
3014
|
+
start: number;
|
|
3015
|
+
end: number;
|
|
3016
|
+
};
|
|
3017
|
+
}): Promise<{
|
|
3018
|
+
data: Buffer;
|
|
3019
|
+
writeTime: number;
|
|
3020
|
+
size: number;
|
|
3021
|
+
} | undefined>;
|
|
3022
|
+
set(fileName: string, data: Buffer, config?: WriteConfig): Promise<void>;
|
|
3023
|
+
del(fileName: string, config?: WriteConfig): Promise<void>;
|
|
3024
|
+
getInfo(fileName: string): Promise<{
|
|
3025
|
+
writeTime: number;
|
|
3026
|
+
size: number;
|
|
3027
|
+
} | undefined>;
|
|
3028
|
+
findInfo(prefix: string, config?: {
|
|
3029
|
+
shallow?: boolean;
|
|
3030
|
+
type?: "files" | "folders";
|
|
3031
|
+
}): Promise<ArchiveFileInfo[]>;
|
|
3032
|
+
getChangesAfter?(time: number): Promise<ArchiveFileInfo[]>;
|
|
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
|
+
}>;
|
|
3045
|
+
startLargeUpload(): Promise<string>;
|
|
3046
|
+
appendLargeUpload(id: string, data: Buffer): Promise<void>;
|
|
3047
|
+
finishLargeUpload(id: string, key: string): Promise<void>;
|
|
3048
|
+
cancelLargeUpload(id: string): Promise<void>;
|
|
2658
3049
|
};
|
|
2659
|
-
export declare class BlobStore {
|
|
3050
|
+
export declare class BlobStore implements IBucketStore {
|
|
2660
3051
|
private folder;
|
|
2661
|
-
|
|
2662
|
-
private
|
|
2663
|
-
|
|
2664
|
-
|
|
2665
|
-
|
|
2666
|
-
|
|
2667
|
-
private
|
|
2668
|
-
private currentBlobNumber;
|
|
2669
|
-
private currentBlobOffset;
|
|
2670
|
-
private currentBlobFd;
|
|
3052
|
+
private sources;
|
|
3053
|
+
private config?;
|
|
3054
|
+
constructor(folder: string, sources: ArchivesSource[], config?: {
|
|
3055
|
+
onIndexChanged?: ((key: string) => void) | undefined;
|
|
3056
|
+
readerDiskLimit?: number | undefined;
|
|
3057
|
+
} | undefined);
|
|
3058
|
+
private stopped;
|
|
2671
3059
|
private index;
|
|
2672
|
-
private
|
|
2673
|
-
private
|
|
3060
|
+
private mem;
|
|
3061
|
+
private indexFileCount;
|
|
3062
|
+
private indexByteCount;
|
|
3063
|
+
private sourceFileCounts;
|
|
3064
|
+
private sourceByteCounts;
|
|
3065
|
+
private syncActivities;
|
|
3066
|
+
private dirty;
|
|
3067
|
+
private overlay;
|
|
3068
|
+
private sourceStates;
|
|
2674
3069
|
init: {
|
|
2675
3070
|
(): Promise<void>;
|
|
2676
3071
|
reset(): void;
|
|
2677
3072
|
set(newValue: Promise<void>): void;
|
|
2678
3073
|
};
|
|
2679
|
-
|
|
2680
|
-
private
|
|
2681
|
-
private
|
|
2682
|
-
private closeBlobHandle;
|
|
2683
|
-
private addDeadBytes;
|
|
2684
|
-
private appendData;
|
|
3074
|
+
dispose(): Promise<void>;
|
|
3075
|
+
private loadIndex;
|
|
3076
|
+
private countEntry;
|
|
2685
3077
|
private setIndexEntry;
|
|
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
|
+
}>;
|
|
3104
|
+
private flushIndex;
|
|
3105
|
+
private runSourceSync;
|
|
3106
|
+
private scanSource;
|
|
3107
|
+
private reconcileSource;
|
|
3108
|
+
private applyScanned;
|
|
3109
|
+
private pollChanges;
|
|
3110
|
+
private copySourceFiles;
|
|
3111
|
+
private waitForRequiredScans;
|
|
3112
|
+
private checkMissingKey;
|
|
3113
|
+
private getIndexEntry;
|
|
3114
|
+
get(key: string, config?: {
|
|
3115
|
+
range?: {
|
|
3116
|
+
start: number;
|
|
3117
|
+
end: number;
|
|
3118
|
+
};
|
|
3119
|
+
}): Promise<Buffer | undefined>;
|
|
3120
|
+
get2(key: string, config?: {
|
|
3121
|
+
range?: {
|
|
3122
|
+
start: number;
|
|
3123
|
+
end: number;
|
|
3124
|
+
};
|
|
3125
|
+
}): Promise<{
|
|
3126
|
+
data: Buffer;
|
|
3127
|
+
writeTime: number;
|
|
3128
|
+
size: number;
|
|
3129
|
+
} | undefined>;
|
|
3130
|
+
private cacheRead;
|
|
2686
3131
|
set(key: string, data: Buffer, config?: WriteConfig): Promise<void>;
|
|
2687
3132
|
del(key: string, config?: WriteConfig): Promise<void>;
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
end: number;
|
|
2691
|
-
}): Promise<Buffer | undefined>;
|
|
3133
|
+
private getWritableSources;
|
|
3134
|
+
private writeToSources;
|
|
2692
3135
|
getInfo(key: string): Promise<{
|
|
2693
3136
|
writeTime: number;
|
|
2694
3137
|
size: number;
|
|
@@ -2697,12 +3140,194 @@ declare module "sliftutils/storage/remoteStorage/blobStore" {
|
|
|
2697
3140
|
shallow?: boolean;
|
|
2698
3141
|
type?: "files" | "folders";
|
|
2699
3142
|
}): Promise<ArchiveFileInfo[]>;
|
|
3143
|
+
getChangesAfter(time: number): Promise<ArchiveFileInfo[]>;
|
|
3144
|
+
getSyncStatus(): Promise<ArchivesSyncStatus>;
|
|
3145
|
+
private getDiskSource;
|
|
2700
3146
|
startLargeUpload(): Promise<string>;
|
|
2701
3147
|
appendLargeUpload(id: string, data: Buffer): Promise<void>;
|
|
2702
3148
|
finishLargeUpload(id: string, key: string): Promise<void>;
|
|
2703
3149
|
cancelLargeUpload(id: string): Promise<void>;
|
|
2704
3150
|
private flushOverlay;
|
|
2705
|
-
private
|
|
3151
|
+
private evicting;
|
|
3152
|
+
private enforceDiskLimit;
|
|
3153
|
+
private cleanupTombstones;
|
|
3154
|
+
}
|
|
3155
|
+
|
|
3156
|
+
}
|
|
3157
|
+
|
|
3158
|
+
declare module "sliftutils/storage/remoteStorage/cliArgs" {
|
|
3159
|
+
export declare function getArg(name: string): string | undefined;
|
|
3160
|
+
|
|
3161
|
+
}
|
|
3162
|
+
|
|
3163
|
+
declare module "sliftutils/storage/remoteStorage/createArchives" {
|
|
3164
|
+
/// <reference types="node" />
|
|
3165
|
+
/// <reference types="node" />
|
|
3166
|
+
import { IArchives, RemoteConfig, RemoteConfigBase, HostedConfig, BackblazeConfig, ArchiveFileInfo, ArchivesConfig, ArchivesSyncStatus } from "../IArchives";
|
|
3167
|
+
export declare function createApiArchives(source: HostedConfig | BackblazeConfig): IArchives;
|
|
3168
|
+
export declare class ArchivesChain implements IArchives {
|
|
3169
|
+
private configured;
|
|
3170
|
+
private activeConfig;
|
|
3171
|
+
private statePromise;
|
|
3172
|
+
private initRetryDelay;
|
|
3173
|
+
private initRetryTimer;
|
|
3174
|
+
private pollTimer;
|
|
3175
|
+
private disposed;
|
|
3176
|
+
constructor(config: RemoteConfig | RemoteConfigBase);
|
|
3177
|
+
getDebugName(): string;
|
|
3178
|
+
private getState;
|
|
3179
|
+
private init;
|
|
3180
|
+
private buildSources;
|
|
3181
|
+
private startConfigPoll;
|
|
3182
|
+
private checkForNewConfig;
|
|
3183
|
+
private run;
|
|
3184
|
+
private runWrite;
|
|
3185
|
+
private request;
|
|
3186
|
+
waitingForAccess(): Promise<{
|
|
3187
|
+
link: string;
|
|
3188
|
+
machineId: string;
|
|
3189
|
+
ip: string;
|
|
3190
|
+
} | undefined>;
|
|
3191
|
+
get(fileName: string, config?: {
|
|
3192
|
+
range?: {
|
|
3193
|
+
start: number;
|
|
3194
|
+
end: number;
|
|
3195
|
+
};
|
|
3196
|
+
}): Promise<Buffer | undefined>;
|
|
3197
|
+
get2(fileName: string, config?: {
|
|
3198
|
+
range?: {
|
|
3199
|
+
start: number;
|
|
3200
|
+
end: number;
|
|
3201
|
+
};
|
|
3202
|
+
}): Promise<{
|
|
3203
|
+
data: Buffer;
|
|
3204
|
+
writeTime: number;
|
|
3205
|
+
size: number;
|
|
3206
|
+
} | undefined>;
|
|
3207
|
+
getInfo(fileName: string): Promise<{
|
|
3208
|
+
writeTime: number;
|
|
3209
|
+
size: number;
|
|
3210
|
+
} | undefined>;
|
|
3211
|
+
private selectCoveringSources;
|
|
3212
|
+
private runOnApi;
|
|
3213
|
+
find(prefix: string, config?: {
|
|
3214
|
+
shallow?: boolean;
|
|
3215
|
+
type: "files" | "folders";
|
|
3216
|
+
}): Promise<string[]>;
|
|
3217
|
+
findInfo(prefix: string, config?: {
|
|
3218
|
+
shallow?: boolean;
|
|
3219
|
+
type: "files" | "folders";
|
|
3220
|
+
}): Promise<ArchiveFileInfo[]>;
|
|
3221
|
+
getChangesAfter(time: number): Promise<ArchiveFileInfo[]>;
|
|
3222
|
+
getSyncStatus(): Promise<ArchivesSyncStatus>;
|
|
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;
|
|
3228
|
+
set(fileName: string, data: Buffer, config?: {
|
|
3229
|
+
lastModified?: number;
|
|
3230
|
+
}): Promise<void>;
|
|
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>;
|
|
3241
|
+
setLargeFile(config: {
|
|
3242
|
+
path: string;
|
|
3243
|
+
getNextData(): Promise<Buffer | undefined>;
|
|
3244
|
+
}): Promise<void>;
|
|
3245
|
+
getURL(path: string): Promise<string>;
|
|
3246
|
+
dispose(): void;
|
|
3247
|
+
}
|
|
3248
|
+
export declare function createArchives(config: RemoteConfig | RemoteConfigBase): ArchivesChain;
|
|
3249
|
+
|
|
3250
|
+
}
|
|
3251
|
+
|
|
3252
|
+
declare module "sliftutils/storage/remoteStorage/grantAccessCli" {
|
|
3253
|
+
export {};
|
|
3254
|
+
|
|
3255
|
+
}
|
|
3256
|
+
|
|
3257
|
+
declare module "sliftutils/storage/remoteStorage/remoteConfig" {
|
|
3258
|
+
/// <reference types="node" />
|
|
3259
|
+
/// <reference types="node" />
|
|
3260
|
+
import { RemoteConfig, RemoteConfigBase, HostedConfig, BackblazeConfig } from "../IArchives";
|
|
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;
|
|
3270
|
+
export declare function getConfigVersion(config: RemoteConfig): number;
|
|
3271
|
+
/** Strips the routing-file suffix, leaving the bucket's public base URL (file paths append to it). */
|
|
3272
|
+
export declare function getBucketBaseUrl(url: string): string;
|
|
3273
|
+
export declare function buildFileUrl(baseUrl: string, filePath: string): string;
|
|
3274
|
+
export declare function parseHostedUrl(url: string): {
|
|
3275
|
+
address: string;
|
|
3276
|
+
port: number;
|
|
3277
|
+
account: string;
|
|
3278
|
+
bucketName: string;
|
|
3279
|
+
};
|
|
3280
|
+
export declare function parseBackblazeUrl(url: string): {
|
|
3281
|
+
bucketName: string;
|
|
3282
|
+
};
|
|
3283
|
+
export declare function normalizeSource(source: RemoteConfigBase): HostedConfig | BackblazeConfig;
|
|
3284
|
+
export declare function normalizeRemoteConfig(config: RemoteConfig | RemoteConfigBase): RemoteConfig;
|
|
3285
|
+
export declare function parseRoutingData(data: Buffer): RemoteConfig;
|
|
3286
|
+
export declare function serializeRemoteConfig(config: RemoteConfig): Buffer;
|
|
3287
|
+
|
|
3288
|
+
}
|
|
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;
|
|
2706
3331
|
}
|
|
2707
3332
|
|
|
2708
3333
|
}
|
|
@@ -2710,9 +3335,7 @@ declare module "sliftutils/storage/remoteStorage/blobStore" {
|
|
|
2710
3335
|
declare module "sliftutils/storage/remoteStorage/storageController" {
|
|
2711
3336
|
/// <reference types="node" />
|
|
2712
3337
|
/// <reference types="node" />
|
|
2713
|
-
import { ArchiveFileInfo } from "../IArchives";
|
|
2714
|
-
import type { BlobStore } from "./blobStore";
|
|
2715
|
-
import type { IStorage } from "../IStorage";
|
|
3338
|
+
import { ArchiveFileInfo, ArchivesConfig, ArchivesSyncStatus } from "../IArchives";
|
|
2716
3339
|
export declare const REMOTE_STORAGE_CLASS_GUID = "RemoteStorageController-b7e42a91";
|
|
2717
3340
|
export declare const STORAGE_AUTH_PURPOSE = "remoteStorage-auth-1";
|
|
2718
3341
|
export declare const STORAGE_NOT_AUTHENTICATED = "REMOTE_STORAGE_NOT_AUTHENTICATED_cf2f7b1e";
|
|
@@ -2735,34 +3358,15 @@ declare module "sliftutils/storage/remoteStorage/storageController" {
|
|
|
2735
3358
|
ip: string;
|
|
2736
3359
|
time: number;
|
|
2737
3360
|
};
|
|
2738
|
-
export type BucketConfig = {
|
|
2739
|
-
public?: boolean;
|
|
2740
|
-
fast?: boolean;
|
|
2741
|
-
writeDelay?: number;
|
|
2742
|
-
};
|
|
2743
3361
|
export type AccessState = {
|
|
2744
3362
|
machineId: string;
|
|
2745
3363
|
ip: string;
|
|
2746
3364
|
hasAccess: boolean;
|
|
2747
|
-
listAccessCommand: string;
|
|
2748
3365
|
grantAccessCommand?: string;
|
|
2749
|
-
|
|
2750
|
-
trusted: boolean;
|
|
2751
|
-
})[];
|
|
2752
|
-
};
|
|
2753
|
-
export type StorageServerState = {
|
|
2754
|
-
domain: string;
|
|
2755
|
-
port: number;
|
|
2756
|
-
rootDomain: string;
|
|
2757
|
-
sshTarget: string;
|
|
2758
|
-
serverCommand: string;
|
|
2759
|
-
blobStore: BlobStore;
|
|
2760
|
-
trust: IStorage<TrustRecord>;
|
|
2761
|
-
requests: IStorage<AccessRequest[]>;
|
|
2762
|
-
buckets: IStorage<BucketConfig>;
|
|
3366
|
+
trustedMachines?: TrustRecord[];
|
|
2763
3367
|
};
|
|
2764
|
-
export declare function setStorageServerState(state: StorageServerState): void;
|
|
2765
3368
|
export declare const RemoteStorageController: import("socket-function/SocketFunctionTypes").SocketRegistered<{
|
|
3369
|
+
ping: () => Promise<void>;
|
|
2766
3370
|
authenticate: (token: AuthToken) => Promise<{
|
|
2767
3371
|
machineId: string;
|
|
2768
3372
|
ip: string;
|
|
@@ -2774,14 +3378,23 @@ declare module "sliftutils/storage/remoteStorage/storageController" {
|
|
|
2774
3378
|
grantAccessCommand: string;
|
|
2775
3379
|
}>;
|
|
2776
3380
|
getAccessState: (account: string) => Promise<AccessState>;
|
|
3381
|
+
listRequestsForIP: (account: string, ip: string) => Promise<AccessRequest[]>;
|
|
3382
|
+
grantAccess: (requestId: string) => Promise<TrustRecord>;
|
|
2777
3383
|
adminListRequests: (ip: string) => Promise<AccessRequest[]>;
|
|
2778
3384
|
adminGrantAccess: (requestId: string) => Promise<TrustRecord>;
|
|
2779
|
-
ensureBucket: (account: string, bucketName: string, config: BucketConfig) => Promise<void>;
|
|
2780
3385
|
get: (account: string, bucketName: string, path: string, range?: {
|
|
2781
3386
|
start: number;
|
|
2782
3387
|
end: number;
|
|
2783
3388
|
}) => Promise<Buffer | undefined>;
|
|
2784
|
-
|
|
3389
|
+
get2: (account: string, bucketName: string, path: string, range?: {
|
|
3390
|
+
start: number;
|
|
3391
|
+
end: number;
|
|
3392
|
+
}) => Promise<{
|
|
3393
|
+
data: Buffer;
|
|
3394
|
+
writeTime: number;
|
|
3395
|
+
size: number;
|
|
3396
|
+
} | undefined>;
|
|
3397
|
+
set: (account: string, bucketName: string, path: string, data: Buffer, lastModified?: number) => Promise<void>;
|
|
2785
3398
|
del: (account: string, bucketName: string, path: string) => Promise<void>;
|
|
2786
3399
|
getInfo: (account: string, bucketName: string, path: string) => Promise<{
|
|
2787
3400
|
writeTime: number;
|
|
@@ -2791,17 +3404,90 @@ declare module "sliftutils/storage/remoteStorage/storageController" {
|
|
|
2791
3404
|
shallow?: boolean;
|
|
2792
3405
|
type?: "files" | "folders";
|
|
2793
3406
|
}) => Promise<ArchiveFileInfo[]>;
|
|
3407
|
+
getChangesAfter: (account: string, bucketName: string, time: number) => Promise<ArchiveFileInfo[]>;
|
|
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>;
|
|
3418
|
+
getSyncStatus: (account: string, bucketName: string) => Promise<ArchivesSyncStatus>;
|
|
2794
3419
|
startLargeFile: (account: string, bucketName: string, path: string) => Promise<string>;
|
|
2795
3420
|
uploadPart: (uploadId: string, data: Buffer) => Promise<void>;
|
|
2796
3421
|
finishLargeFile: (uploadId: string) => Promise<void>;
|
|
2797
3422
|
cancelLargeFile: (uploadId: string) => Promise<void>;
|
|
2798
|
-
|
|
3423
|
+
httpEntry: (config?: {
|
|
3424
|
+
requireCalls?: string[];
|
|
3425
|
+
cacheTime?: number;
|
|
3426
|
+
}) => Promise<Buffer>;
|
|
2799
3427
|
}>;
|
|
2800
3428
|
|
|
2801
3429
|
}
|
|
2802
3430
|
|
|
2803
3431
|
declare module "sliftutils/storage/remoteStorage/storageServer" {
|
|
2804
3432
|
import "./accessPage";
|
|
3433
|
+
export type HostStorageServerConfig = {
|
|
3434
|
+
url: string;
|
|
3435
|
+
folder: string;
|
|
3436
|
+
lowSpaceThresholdBytes?: number;
|
|
3437
|
+
};
|
|
3438
|
+
export declare function hostStorageServer(config: HostStorageServerConfig): Promise<void>;
|
|
3439
|
+
|
|
3440
|
+
}
|
|
3441
|
+
|
|
3442
|
+
declare module "sliftutils/storage/remoteStorage/storageServerCli" {
|
|
3443
|
+
export {};
|
|
3444
|
+
|
|
3445
|
+
}
|
|
3446
|
+
|
|
3447
|
+
declare module "sliftutils/storage/remoteStorage/storageServerState" {
|
|
3448
|
+
/// <reference types="node" />
|
|
3449
|
+
/// <reference types="node" />
|
|
3450
|
+
import { IBucketStore } from "./blobStore";
|
|
3451
|
+
import { RemoteConfig, HostedConfig, IArchives } from "../IArchives";
|
|
3452
|
+
import type { IStorage } from "../IStorage";
|
|
3453
|
+
import type { AccessRequest, TrustRecord } from "./storageController";
|
|
3454
|
+
export type StorageServerConfig = {
|
|
3455
|
+
domain: string;
|
|
3456
|
+
port: number;
|
|
3457
|
+
rootDomain: string;
|
|
3458
|
+
sshTarget: string;
|
|
3459
|
+
serverCommand: string;
|
|
3460
|
+
folder: string;
|
|
3461
|
+
};
|
|
3462
|
+
export declare function setStorageServerConfig(value: StorageServerConfig): void;
|
|
3463
|
+
export declare function getStorageServerConfig(): StorageServerConfig;
|
|
3464
|
+
export declare function getStorageServerConfigOptional(): StorageServerConfig | undefined;
|
|
3465
|
+
export declare function setWritesRejectedReason(reason: string | undefined): void;
|
|
3466
|
+
export declare function getWritesRejectedReason(): string | undefined;
|
|
3467
|
+
export declare function assertWritesAllowed(): void;
|
|
3468
|
+
export declare function getTrust(): Promise<IStorage<TrustRecord>>;
|
|
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>;
|
|
3475
|
+
export type LoadedBucket = {
|
|
3476
|
+
account: string;
|
|
3477
|
+
bucketName: string;
|
|
3478
|
+
routing: RemoteConfig;
|
|
3479
|
+
routingJSON: string;
|
|
3480
|
+
selfEntries: HostedConfig[];
|
|
3481
|
+
self: HostedConfig | undefined;
|
|
3482
|
+
store: IBucketStore;
|
|
3483
|
+
};
|
|
3484
|
+
export declare function getLoadedBucket(account: string, bucketName: string): Promise<LoadedBucket | undefined>;
|
|
3485
|
+
export declare function assertMutable(bucket: LoadedBucket, filePath: string, writeTime: number): Promise<void>;
|
|
3486
|
+
export declare function writeBucketFile(account: string, bucketName: string, filePath: string, data: Buffer, config?: {
|
|
3487
|
+
lastModified?: number;
|
|
3488
|
+
}): Promise<void>;
|
|
3489
|
+
export declare function deleteBucketFile(account: string, bucketName: string, filePath: string): Promise<void>;
|
|
3490
|
+
export declare function getLocalArchives(account: string, bucketName: string): IArchives;
|
|
2805
3491
|
|
|
2806
3492
|
}
|
|
2807
3493
|
|