sliftutils 1.7.10 → 1.7.12
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/.claude/settings.local.json +2 -1
- package/examplestorage/exampleserver.ts +0 -2
- package/index.d.ts +301 -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 +63 -3
- package/storage/remoteStorage/blobStore.ts +419 -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
package/storage/IArchives.ts
CHANGED
|
@@ -6,6 +6,10 @@ module.allowclient = true;
|
|
|
6
6
|
// A write may not be stamped more than this far in the future, or clock skew between machines
|
|
7
7
|
// would let a bad timestamp block writes for a long time.
|
|
8
8
|
export const MAX_LAST_MODIFIED_FUTURE = 15 * 60 * 1000;
|
|
9
|
+
|
|
10
|
+
// How long browsers may cache files from immutable buckets (the Cache-Control max-age), shared by
|
|
11
|
+
// every hosting path (backblaze bucket settings and our own storage server's HTTP route)
|
|
12
|
+
export const IMMUTABLE_CACHE_TIME = 86400 * 1000;
|
|
9
13
|
export function assertValidLastModified(lastModified: number): void {
|
|
10
14
|
let max = Date.now() + MAX_LAST_MODIFIED_FUTURE;
|
|
11
15
|
if (lastModified > max) {
|
|
@@ -34,14 +38,20 @@ export type RemoteConfig = {
|
|
|
34
38
|
export type RemoteConfigBase = string | HostedConfig | BackblazeConfig;
|
|
35
39
|
|
|
36
40
|
export type CommonConfig = {
|
|
37
|
-
/**
|
|
38
|
-
|
|
41
|
+
/** 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. */
|
|
42
|
+
noFullSync?: boolean;
|
|
43
|
+
/** 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). */
|
|
44
|
+
readerDiskLimit?: number;
|
|
45
|
+
/** 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. */
|
|
46
|
+
validWindow: [number, number];
|
|
47
|
+
/** 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. */
|
|
48
|
+
route?: [number, number];
|
|
39
49
|
};
|
|
40
50
|
|
|
41
51
|
export type HostedConfig = CommonConfig & {
|
|
42
52
|
type: "remote";
|
|
43
53
|
|
|
44
|
-
// Ex: https://
|
|
54
|
+
// Ex: https://99-250-124-91.querysubtest.com:5233/file/root/uniquebucketname/storage/storagerouting.json
|
|
45
55
|
// NOTE: The account and bucket name are obtained from the URL.
|
|
46
56
|
url: string;
|
|
47
57
|
|
|
@@ -67,7 +77,6 @@ export type BackblazeConfig = CommonConfig & {
|
|
|
67
77
|
// NOTE: The bucket name is obtained from the URL.
|
|
68
78
|
url: string;
|
|
69
79
|
// Public buckets are served over plain HTTPS GETs (getURL). Private buckets are API-access only.
|
|
70
|
-
bucketName: string;
|
|
71
80
|
public?: boolean;
|
|
72
81
|
// NOTE: This isn't enforced on the backblaze level, so this is just a client-side guarantee. This can change how we cache files.
|
|
73
82
|
// - Backblaze does support immutability. However, apparently, once we enable it on a bucket, we can't disable it, which is really bad, as it means if our code could ever enable it and we accidentally enable it on an important bucket, we essentially just bricked that bucket. So we should never write any code that ever tries to use backblaze to make things immutable.
|
|
@@ -77,14 +86,8 @@ export type BackblazeConfig = CommonConfig & {
|
|
|
77
86
|
};
|
|
78
87
|
|
|
79
88
|
|
|
80
|
-
export const
|
|
81
|
-
|
|
82
|
-
required: true,
|
|
83
|
-
validWindow: [0, Number.MAX_SAFE_INTEGER],
|
|
84
|
-
};
|
|
85
|
-
export const DEFAULT_SYNC_OPTIONS: SyncOptions = {
|
|
86
|
-
validWindow: [0, Number.MAX_SAFE_INTEGER],
|
|
87
|
-
};
|
|
89
|
+
export const FULL_VALID_WINDOW: [number, number] = [0, Number.MAX_SAFE_INTEGER];
|
|
90
|
+
|
|
88
91
|
|
|
89
92
|
|
|
90
93
|
|
|
@@ -94,33 +97,83 @@ export const DEFAULT_SYNC_OPTIONS: SyncOptions = {
|
|
|
94
97
|
// bytes served by get() were most recently written".
|
|
95
98
|
export type ArchiveFileInfo = { path: string; createTime: number; size: number };
|
|
96
99
|
|
|
100
|
+
// An in-progress background synchronization task (see ArchivesConfig.syncing)
|
|
101
|
+
export type SyncActivity = {
|
|
102
|
+
// A metadata scan is a single listing call, so it has no incremental progress - just that it's
|
|
103
|
+
// running and since when. A full sync knows its exact file/byte progress.
|
|
104
|
+
type: "metadataScan" | "fullSync";
|
|
105
|
+
sourceDebugName: string;
|
|
106
|
+
startTime: number;
|
|
107
|
+
doneFiles?: number;
|
|
108
|
+
totalFiles?: number;
|
|
109
|
+
doneBytes?: number;
|
|
110
|
+
totalBytes?: number;
|
|
111
|
+
};
|
|
112
|
+
|
|
97
113
|
export type ArchivesConfig = {
|
|
98
114
|
// Whether getChangesAfter is implemented (fast change polling, instead of full rescans)
|
|
99
115
|
supportsChangesAfter?: boolean;
|
|
116
|
+
// The bucket's full routing config (ROUTING_FILE). Absent for sources that don't have one (a
|
|
117
|
+
// bare disk source, or a bucket that doesn't exist yet).
|
|
118
|
+
remoteConfig?: RemoteConfig;
|
|
119
|
+
// Live index totals (tombstones excluded), kept up to date in memory on every mutation and
|
|
120
|
+
// recomputed on load - so any drift heals on restart
|
|
121
|
+
index?: { fileCount: number; byteCount: number };
|
|
122
|
+
// The same totals broken down by which source currently holds each file's bytes (the first
|
|
123
|
+
// entry is the server's own disk)
|
|
124
|
+
indexSources?: { debugName: string; fileCount: number; byteCount: number }[];
|
|
125
|
+
// The server's configured readerDiskLimit, when it runs as a bounded read cache
|
|
126
|
+
readerDiskLimit?: number;
|
|
127
|
+
// Background synchronization currently in progress (empty when idle)
|
|
128
|
+
syncing?: SyncActivity[];
|
|
100
129
|
};
|
|
101
130
|
|
|
102
|
-
//
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
|
|
108
|
-
//
|
|
109
|
-
noWriteBack?: boolean;
|
|
110
|
-
// If a read wasn't served by this source, write the data back to it (using it as a cache), and
|
|
111
|
-
// update the index so it becomes the new source. Set for the local disk source.
|
|
112
|
-
cacheReads?: boolean;
|
|
113
|
-
// Ignore values with write times outside [start, end].
|
|
131
|
+
// A synchronization source of a BlobStore (which synchronizes an index + local cache from them)
|
|
132
|
+
export type ArchivesSource = {
|
|
133
|
+
source: IArchives;
|
|
134
|
+
// From the source's CommonConfig. Values with write times outside the window are ignored when
|
|
135
|
+
// scanning, and once its end is sufficiently past (see windowAcceptsWrites) the source stops
|
|
136
|
+
// receiving writes entirely - still scanned (it holds the authoritative data for its window),
|
|
137
|
+
// it just stops growing.
|
|
114
138
|
validWindow: [number, number];
|
|
115
|
-
//
|
|
116
|
-
//
|
|
117
|
-
|
|
139
|
+
// From the source's CommonConfig (intersected with the owning store's own route): only keys
|
|
140
|
+
// routing into [start, end) are accepted from this source's scans and sent to it in
|
|
141
|
+
// writes/reconciliation. The routing file is exempt - config flows everywhere. Absent = all keys.
|
|
142
|
+
route?: [number, number];
|
|
143
|
+
// From the source's CommonConfig; see there.
|
|
144
|
+
noFullSync?: boolean;
|
|
118
145
|
};
|
|
119
|
-
|
|
146
|
+
|
|
147
|
+
// The grace covers clock uncertainty around the window edge: a write slightly past the end doesn't
|
|
148
|
+
// hurt, but once clearly past, the source is an archive and must stop growing.
|
|
149
|
+
export const WRITE_PAST_WINDOW_GRACE = 5 * 60 * 1000;
|
|
150
|
+
|
|
151
|
+
// Error marker a server includes when a freshly-stamped write reaches it outside its valid windows
|
|
152
|
+
// (the client resolved its target, then time crossed a window boundary before the write landed).
|
|
153
|
+
// Clients detect this marker and re-resolve the currently-valid source, retrying ONCE - boundaries
|
|
154
|
+
// are far apart, so hitting it twice in one attempt means something is actually wrong.
|
|
155
|
+
export const STORAGE_WRONG_VALID_WINDOW = "REMOTE_STORAGE_WRONG_VALID_WINDOW_a7c1f04e";
|
|
156
|
+
|
|
157
|
+
// Error marker a server includes when a freshly-stamped write's key routes outside the shards this
|
|
158
|
+
// server handles (the client's config disagrees with the server's - clients re-resolve once)
|
|
159
|
+
export const STORAGE_WRONG_ROUTE = "REMOTE_STORAGE_WRONG_ROUTE_c94d2e17";
|
|
160
|
+
|
|
161
|
+
export const FULL_ROUTE: [number, number] = [0, 1];
|
|
162
|
+
|
|
163
|
+
// A key containing this sentinel doesn't have a fixed shard: setVariableShard picks the (lowest
|
|
164
|
+
// latency, up) write shard, appends "_<value in the shard's route>" directly after the sentinel,
|
|
165
|
+
// and returns the materialized key. getRoute treats that suffix as a complete route override.
|
|
166
|
+
export const VARIABLE_SHARD = "VARIABLE_SHARD_f0234jfah08fgyhfgyssdds83nmp";
|
|
167
|
+
export function windowAcceptsWrites(validWindow: [number, number] | undefined): boolean {
|
|
168
|
+
if (!validWindow) return true;
|
|
169
|
+
return validWindow[1] + WRITE_PAST_WINDOW_GRACE > Date.now();
|
|
170
|
+
}
|
|
120
171
|
|
|
121
172
|
export type ArchivesSyncSourceStatus = {
|
|
122
173
|
debugName: string;
|
|
123
|
-
|
|
174
|
+
validWindow: [number, number];
|
|
175
|
+
route?: [number, number];
|
|
176
|
+
noFullSync?: boolean;
|
|
124
177
|
supportsChangesAfter: boolean;
|
|
125
178
|
initialScanComplete: boolean;
|
|
126
179
|
// Files seen in this source's scans / change polls so far
|
|
@@ -135,9 +188,11 @@ export type ArchivesSyncStatus = {
|
|
|
135
188
|
|
|
136
189
|
export interface IArchives {
|
|
137
190
|
getDebugName(): string;
|
|
191
|
+
/** Whether writes would be accepted (credentials exist, the account trusts this machine, etc).
|
|
192
|
+
* Checked without writing anything. */
|
|
193
|
+
hasWriteAccess(): Promise<boolean>;
|
|
138
194
|
get(fileName: string, config?: { range?: { start: number; end: number } }): Promise<Buffer | undefined>;
|
|
139
|
-
|
|
140
|
-
get2(fileName: string, config?: { range?: { start: number; end: number } }): Promise<{ data: Buffer; writeTime: number } | undefined>;
|
|
195
|
+
get2(fileName: string, config?: { range?: { start: number; end: number } }): Promise<{ data: Buffer; writeTime: number; size: number } | undefined>;
|
|
141
196
|
/**
|
|
142
197
|
* lastModified stamps the write with that last-write time instead of now. If it is OLDER than
|
|
143
198
|
* the file's current last-write time the write no-ops (so delayed / synchronized writes can
|
package/storage/backblaze.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export declare class ArchivesBackblaze implements IArchives {
|
|
|
8
8
|
public?: boolean;
|
|
9
9
|
immutable?: boolean;
|
|
10
10
|
cacheTime?: number;
|
|
11
|
+
allowedOrigins?: string[];
|
|
11
12
|
});
|
|
12
13
|
private bucketName;
|
|
13
14
|
private bucketId;
|
|
@@ -16,6 +17,7 @@ export declare class ArchivesBackblaze implements IArchives {
|
|
|
16
17
|
private log;
|
|
17
18
|
getDebugName(): string;
|
|
18
19
|
private getBucketAPI;
|
|
20
|
+
private currentReset;
|
|
19
21
|
private last503Reset;
|
|
20
22
|
private apiRetryLogic;
|
|
21
23
|
get(fileName: string, config?: {
|
|
@@ -33,8 +35,10 @@ export declare class ArchivesBackblaze implements IArchives {
|
|
|
33
35
|
}): Promise<{
|
|
34
36
|
data: Buffer;
|
|
35
37
|
writeTime: number;
|
|
38
|
+
size: number;
|
|
36
39
|
} | undefined>;
|
|
37
40
|
getConfig(): Promise<ArchivesConfig>;
|
|
41
|
+
hasWriteAccess(): Promise<boolean>;
|
|
38
42
|
set(fileName: string, data: Buffer, config?: {
|
|
39
43
|
lastModified?: number;
|
|
40
44
|
}): Promise<void>;
|
|
@@ -60,6 +64,17 @@ export declare class ArchivesBackblaze implements IArchives {
|
|
|
60
64
|
size: number;
|
|
61
65
|
}[]>;
|
|
62
66
|
assertPathValid(path: string): Promise<void>;
|
|
67
|
+
move(config: {
|
|
68
|
+
path: string;
|
|
69
|
+
target: IArchives;
|
|
70
|
+
targetPath: string;
|
|
71
|
+
copyInstead?: boolean;
|
|
72
|
+
}): Promise<void>;
|
|
73
|
+
copy(config: {
|
|
74
|
+
path: string;
|
|
75
|
+
target: IArchives;
|
|
76
|
+
targetPath: string;
|
|
77
|
+
}): Promise<void>;
|
|
63
78
|
getURL(path: string): Promise<string>;
|
|
64
79
|
getDownloadAuthorization(config: {
|
|
65
80
|
fileNamePrefix?: string;
|