sliftutils 1.7.71 → 1.7.72
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/dist/treeSummary.ts.cache +2 -2
- package/index.d.ts +505 -257
- package/misc/dist/environment.ts.cache +2 -2
- package/misc/dist/getSecret.ts.cache +2 -2
- package/misc/dist/strings.ts.cache +2 -2
- package/misc/dist/zip.ts.cache +2 -2
- package/misc/https/dist/certs.ts.cache +2 -2
- package/misc/https/dist/hostServer.ts.cache +5 -2
- package/misc/https/dist/persistentLocalStorage.ts.cache +2 -2
- package/package.json +1 -1
- package/render-utils/dist/observer.tsx.cache +2 -2
- package/spec.txt +10 -0
- package/storage/ArchivesDisk.d.ts +4 -13
- package/storage/ArchivesDisk.ts +6 -4
- package/storage/BulkDatabase2/dist/BulkDatabaseBase.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/BulkDatabaseFormat.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/BulkDatabaseMerge.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/BulkDatabaseReader.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/LoadedIndex.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/WriteOverlay.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/blockCache.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/mergeLock.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/mergeMarkers.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/streamLog.ts.cache +2 -2
- package/storage/BulkDatabase2/dist/syncClient.ts.cache +2 -2
- package/storage/IArchives.d.ts +14 -10
- package/storage/IArchives.ts +16 -4
- package/storage/backblaze.d.ts +3 -9
- package/storage/backblaze.ts +22 -19
- package/storage/dist/ArchivesDisk.ts.cache +6 -3
- package/storage/dist/FileFolderAPI.tsx.cache +2 -2
- package/storage/dist/IArchives.ts.cache +18 -4
- package/storage/dist/IndexedDBFileFolderAPI.ts.cache +2 -2
- package/storage/dist/JSONStorage.ts.cache +2 -2
- package/storage/dist/PendingManager.tsx.cache +2 -2
- package/storage/dist/TransactionStorage.ts.cache +2 -2
- package/storage/dist/backblaze.ts.cache +36 -27
- package/storage/dist/fileSystemPointer.ts.cache +2 -2
- package/storage/dist/remoteFileStorage.ts.cache +2 -2
- package/storage/remoteStorage/ArchivesRemote.d.ts +5 -9
- package/storage/remoteStorage/ArchivesRemote.ts +25 -20
- package/storage/remoteStorage/ArchivesUrl.d.ts +3 -9
- package/storage/remoteStorage/ArchivesUrl.ts +7 -5
- package/storage/remoteStorage/accessPage.tsx +4 -4
- package/storage/remoteStorage/accessStats.d.ts +2 -0
- package/storage/remoteStorage/accessStats.ts +32 -0
- package/storage/remoteStorage/blobStore.d.ts +193 -88
- package/storage/remoteStorage/blobStore.ts +535 -400
- package/storage/remoteStorage/bucketDisk.d.ts +18 -0
- package/storage/remoteStorage/bucketDisk.ts +66 -0
- package/storage/remoteStorage/createArchives.d.ts +4 -10
- package/storage/remoteStorage/createArchives.ts +101 -62
- package/storage/remoteStorage/dist/ArchivesRemote.ts.cache +29 -20
- package/storage/remoteStorage/dist/ArchivesUrl.ts.cache +8 -5
- package/storage/remoteStorage/dist/accessPage.tsx.cache +6 -6
- package/storage/remoteStorage/dist/accessStats.ts.cache +39 -4
- package/storage/remoteStorage/dist/blobStore.ts.cache +517 -375
- package/storage/remoteStorage/dist/bucketDisk.ts.cache +72 -0
- package/storage/remoteStorage/dist/cliArgs.ts.cache +2 -2
- package/storage/remoteStorage/dist/createArchives.ts.cache +112 -58
- package/storage/remoteStorage/dist/deployTakeover.ts.cache +2 -2
- package/storage/remoteStorage/dist/intermediateSources.ts.cache +13 -13
- package/storage/remoteStorage/dist/remoteConfig.ts.cache +19 -3
- package/storage/remoteStorage/dist/serverConfig.ts.cache +116 -0
- package/storage/remoteStorage/dist/sourceWrapper.ts.cache +7 -6
- package/storage/remoteStorage/dist/sourcesList.ts.cache +6 -3
- package/storage/remoteStorage/dist/storageClientController.ts.cache +2 -2
- package/storage/remoteStorage/dist/storageController.ts.cache +224 -191
- package/storage/remoteStorage/dist/storageServer.ts.cache +9 -9
- package/storage/remoteStorage/dist/storageServerState.ts.cache +330 -567
- package/storage/remoteStorage/dist/storePlan.ts.cache +149 -0
- package/storage/remoteStorage/dist/validation.ts.cache +40 -0
- package/storage/remoteStorage/grantAccessCli.ts +1 -1
- package/storage/remoteStorage/intermediateSources.d.ts +3 -5
- package/storage/remoteStorage/intermediateSources.ts +14 -16
- package/storage/remoteStorage/remoteConfig.d.ts +2 -2
- package/storage/remoteStorage/remoteConfig.ts +19 -3
- package/storage/remoteStorage/serverConfig.d.ts +27 -0
- package/storage/remoteStorage/serverConfig.ts +109 -0
- package/storage/remoteStorage/sourceWrapper.d.ts +3 -3
- package/storage/remoteStorage/sourceWrapper.ts +7 -6
- package/storage/remoteStorage/sourcesList.ts +3 -0
- package/storage/remoteStorage/storageController.d.ts +118 -36
- package/storage/remoteStorage/storageController.ts +166 -168
- package/storage/remoteStorage/storageServer.ts +1 -1
- package/storage/remoteStorage/storageServerState.d.ts +52 -63
- package/storage/remoteStorage/storageServerState.ts +340 -584
- package/storage/remoteStorage/storePlan.d.ts +34 -0
- package/storage/remoteStorage/storePlan.ts +166 -0
- package/storage/remoteStorage/validation.d.ts +4 -0
- package/storage/remoteStorage/validation.ts +31 -0
|
@@ -1,37 +1,46 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
/// <reference types="node" />
|
|
3
|
-
import { IArchives, ArchiveFileInfo, ArchivesSource, ArchivesSyncStatus, ChangesAfterConfig,
|
|
3
|
+
import { IArchives, ArchiveFileInfo, ArchivesSource, ArchivesSyncStatus, ChangesAfterConfig, FindConfig, HostedConfig, SyncActivity } from "../IArchives";
|
|
4
|
+
import { ArchivesDisk } from "../ArchivesDisk";
|
|
4
5
|
export declare const DEFAULT_FAST_WRITE_DELAY: number;
|
|
5
6
|
export declare const WINDOW_END_FLUSH_MARGIN: number;
|
|
6
|
-
export type WriteConfig = {
|
|
7
|
-
fast?: boolean;
|
|
8
|
-
writeDelay?: number;
|
|
9
|
-
lastModified?: number;
|
|
10
|
-
};
|
|
11
7
|
export type IBucketStore = {
|
|
12
|
-
|
|
13
|
-
get2(
|
|
8
|
+
/** internal (store-to-store) reads answer purely from the local disk; see GetConfig.internal */
|
|
9
|
+
get2(config: {
|
|
10
|
+
path: string;
|
|
11
|
+
range?: {
|
|
12
|
+
start: number;
|
|
13
|
+
end: number;
|
|
14
|
+
};
|
|
15
|
+
internal?: boolean;
|
|
16
|
+
includeTombstones?: boolean;
|
|
17
|
+
}): Promise<{
|
|
14
18
|
data: Buffer;
|
|
15
19
|
writeTime: number;
|
|
16
20
|
size: number;
|
|
17
21
|
} | undefined>;
|
|
18
|
-
|
|
22
|
+
/** internal (store-to-store) writes go to the local disk + index with no fan-out; see SetConfig.internal */
|
|
23
|
+
set(config: {
|
|
24
|
+
path: string;
|
|
19
25
|
data: Buffer;
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
26
|
+
lastModified?: number;
|
|
27
|
+
forceSetImmutable?: boolean;
|
|
28
|
+
internal?: boolean;
|
|
29
|
+
}): Promise<void>;
|
|
30
|
+
del(config: {
|
|
31
|
+
path: string;
|
|
32
|
+
lastModified?: number;
|
|
33
|
+
internal?: boolean;
|
|
25
34
|
}): Promise<void>;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
35
|
+
getInfo(config: {
|
|
36
|
+
path: string;
|
|
37
|
+
includeTombstones?: boolean;
|
|
38
|
+
}): Promise<{
|
|
29
39
|
writeTime: number;
|
|
30
40
|
size: number;
|
|
31
41
|
} | undefined>;
|
|
32
|
-
findInfo(
|
|
33
|
-
|
|
34
|
-
type?: "files" | "folders";
|
|
42
|
+
findInfo(config: FindConfig & {
|
|
43
|
+
prefix: string;
|
|
35
44
|
}): Promise<ArchiveFileInfo[]>;
|
|
36
45
|
getChangesAfter2(config: ChangesAfterConfig): Promise<ArchiveFileInfo[]>;
|
|
37
46
|
getSyncStatus?(): Promise<ArchivesSyncStatus>;
|
|
@@ -57,11 +66,78 @@ export type IBucketStore = {
|
|
|
57
66
|
byteCount: number;
|
|
58
67
|
}[];
|
|
59
68
|
}>;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
69
|
+
/** path/lastModified let the store reject an upload into an immutable bucket before any bytes move */
|
|
70
|
+
startLargeUpload(config?: {
|
|
71
|
+
path?: string;
|
|
72
|
+
lastModified?: number;
|
|
73
|
+
}): Promise<string>;
|
|
74
|
+
appendLargeUpload(config: {
|
|
75
|
+
id: string;
|
|
76
|
+
data: Buffer;
|
|
77
|
+
}): Promise<void>;
|
|
78
|
+
finishLargeUpload(config: {
|
|
79
|
+
id: string;
|
|
80
|
+
path: string;
|
|
81
|
+
lastModified?: number;
|
|
82
|
+
}): Promise<void>;
|
|
83
|
+
cancelLargeUpload(config: {
|
|
84
|
+
id: string;
|
|
85
|
+
}): Promise<void>;
|
|
64
86
|
};
|
|
87
|
+
/** rawDisk buckets: the disk IS the store. No index, no synchronization, no window/route/immutability validation. */
|
|
88
|
+
export declare class RawDiskStore implements IBucketStore {
|
|
89
|
+
private disk;
|
|
90
|
+
constructor(disk: ArchivesDisk);
|
|
91
|
+
get2(config: {
|
|
92
|
+
path: string;
|
|
93
|
+
range?: {
|
|
94
|
+
start: number;
|
|
95
|
+
end: number;
|
|
96
|
+
};
|
|
97
|
+
internal?: boolean;
|
|
98
|
+
includeTombstones?: boolean;
|
|
99
|
+
}): Promise<{
|
|
100
|
+
data: Buffer;
|
|
101
|
+
writeTime: number;
|
|
102
|
+
size: number;
|
|
103
|
+
} | undefined>;
|
|
104
|
+
set(config: {
|
|
105
|
+
path: string;
|
|
106
|
+
data: Buffer;
|
|
107
|
+
lastModified?: number;
|
|
108
|
+
forceSetImmutable?: boolean;
|
|
109
|
+
internal?: boolean;
|
|
110
|
+
}): Promise<void>;
|
|
111
|
+
del(config: {
|
|
112
|
+
path: string;
|
|
113
|
+
lastModified?: number;
|
|
114
|
+
internal?: boolean;
|
|
115
|
+
}): Promise<void>;
|
|
116
|
+
getInfo(config: {
|
|
117
|
+
path: string;
|
|
118
|
+
includeTombstones?: boolean;
|
|
119
|
+
}): Promise<{
|
|
120
|
+
writeTime: number;
|
|
121
|
+
size: number;
|
|
122
|
+
} | undefined>;
|
|
123
|
+
findInfo(config: FindConfig & {
|
|
124
|
+
prefix: string;
|
|
125
|
+
}): Promise<ArchiveFileInfo[]>;
|
|
126
|
+
getChangesAfter2(config: ChangesAfterConfig): Promise<ArchiveFileInfo[]>;
|
|
127
|
+
startLargeUpload(): Promise<string>;
|
|
128
|
+
appendLargeUpload(config: {
|
|
129
|
+
id: string;
|
|
130
|
+
data: Buffer;
|
|
131
|
+
}): Promise<void>;
|
|
132
|
+
finishLargeUpload(config: {
|
|
133
|
+
id: string;
|
|
134
|
+
path: string;
|
|
135
|
+
lastModified?: number;
|
|
136
|
+
}): Promise<void>;
|
|
137
|
+
cancelLargeUpload(config: {
|
|
138
|
+
id: string;
|
|
139
|
+
}): Promise<void>;
|
|
140
|
+
}
|
|
65
141
|
export type BlobSourceSpec = {
|
|
66
142
|
identity: string;
|
|
67
143
|
url: string;
|
|
@@ -80,47 +156,51 @@ export declare class BlobStore implements IBucketStore {
|
|
|
80
156
|
readerDiskLimit?: number | undefined;
|
|
81
157
|
onWriteCounted?: ((kind: "original" | "flushed", bytes: number) => void) | undefined;
|
|
82
158
|
resolveSourceUrl?: ((url: string) => IArchives) | undefined;
|
|
159
|
+
entries?: HostedConfig[] | undefined;
|
|
83
160
|
} | undefined);
|
|
84
|
-
private stopped;
|
|
85
|
-
private index;
|
|
86
|
-
private mem;
|
|
87
|
-
private indexFileCount;
|
|
88
|
-
private indexByteCount;
|
|
89
|
-
private sourceFileCounts;
|
|
90
|
-
private sourceByteCounts;
|
|
91
|
-
private syncActivities;
|
|
92
|
-
private dirty;
|
|
93
|
-
private overlay;
|
|
94
|
-
private sourceStates;
|
|
95
|
-
private syncStarted;
|
|
96
|
-
private sourcesList;
|
|
97
|
-
private slotSourcesListIndexes;
|
|
98
|
-
private slotRegistrations;
|
|
99
|
-
private isLive;
|
|
100
|
-
private registerSlot;
|
|
101
|
-
private sourcesListIndexOfSlot;
|
|
102
|
-
private slotForSourcesListIndex;
|
|
103
|
-
private getEntryHolder;
|
|
104
161
|
init: {
|
|
105
162
|
(): Promise<void>;
|
|
106
163
|
reset(): void;
|
|
107
164
|
set(newValue: Promise<void>): void;
|
|
108
165
|
};
|
|
109
166
|
dispose(): Promise<void>;
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
167
|
+
get2(config: {
|
|
168
|
+
path: string;
|
|
169
|
+
range?: {
|
|
170
|
+
start: number;
|
|
171
|
+
end: number;
|
|
172
|
+
};
|
|
173
|
+
internal?: boolean;
|
|
174
|
+
includeTombstones?: boolean;
|
|
175
|
+
}): Promise<{
|
|
176
|
+
data: Buffer;
|
|
177
|
+
writeTime: number;
|
|
178
|
+
size: number;
|
|
179
|
+
} | undefined>;
|
|
180
|
+
set(config: {
|
|
181
|
+
path: string;
|
|
182
|
+
data: Buffer;
|
|
183
|
+
lastModified?: number;
|
|
184
|
+
forceSetImmutable?: boolean;
|
|
185
|
+
internal?: boolean;
|
|
123
186
|
}): Promise<void>;
|
|
187
|
+
del(config: {
|
|
188
|
+
path: string;
|
|
189
|
+
lastModified?: number;
|
|
190
|
+
internal?: boolean;
|
|
191
|
+
}): Promise<void>;
|
|
192
|
+
getInfo(config: {
|
|
193
|
+
path: string;
|
|
194
|
+
includeTombstones?: boolean;
|
|
195
|
+
}): Promise<{
|
|
196
|
+
writeTime: number;
|
|
197
|
+
size: number;
|
|
198
|
+
} | undefined>;
|
|
199
|
+
findInfo(config: FindConfig & {
|
|
200
|
+
prefix: string;
|
|
201
|
+
}): Promise<ArchiveFileInfo[]>;
|
|
202
|
+
getChangesAfter2(config: ChangesAfterConfig): Promise<ArchiveFileInfo[]>;
|
|
203
|
+
getSyncStatus(): Promise<ArchivesSyncStatus>;
|
|
124
204
|
/** The cheap always-current totals plus any in-progress background synchronization. */
|
|
125
205
|
getSyncProgress(): {
|
|
126
206
|
index: {
|
|
@@ -145,7 +225,60 @@ export declare class BlobStore implements IBucketStore {
|
|
|
145
225
|
byteCount: number;
|
|
146
226
|
}[];
|
|
147
227
|
}>;
|
|
228
|
+
/** Applies a config change to the RUNNING store: windows/routes update in place, new sources are added (their sync starts immediately), and removed sources' slots go dead (their scans stop, their index entries drop). The store survives every routine config evolution - it is never destroyed for a source-list change, only for structural flips it cannot express (rawDisk). Pending fast writes are re-capped to the new flush deadline (flushing immediately when it has already passed). */
|
|
229
|
+
updateSources(specs: BlobSourceSpec[], entries?: HostedConfig[]): void;
|
|
230
|
+
/** Rescans our own disk's metadata into the index - used around valid window handoffs, where another process wrote files to the shared folder that our index hasn't seen. */
|
|
231
|
+
rescanBase(): Promise<void>;
|
|
232
|
+
/** A boundary scan of the node that owned (part of) our route in the valid window before ours, when that node is different storage (a disk rescan can't see its writes): just its changes since the boundary neighborhood, with matching values pulled onto our own disk. */
|
|
233
|
+
boundaryScanRemote(source: IArchives, config: {
|
|
234
|
+
since: number;
|
|
235
|
+
route?: [number, number];
|
|
236
|
+
}): Promise<void>;
|
|
237
|
+
startLargeUpload(config?: {
|
|
238
|
+
path?: string;
|
|
239
|
+
lastModified?: number;
|
|
240
|
+
}): Promise<string>;
|
|
241
|
+
appendLargeUpload(config: {
|
|
242
|
+
id: string;
|
|
243
|
+
data: Buffer;
|
|
244
|
+
}): Promise<void>;
|
|
245
|
+
finishLargeUpload(config: {
|
|
246
|
+
id: string;
|
|
247
|
+
path: string;
|
|
248
|
+
lastModified?: number;
|
|
249
|
+
}): Promise<void>;
|
|
250
|
+
cancelLargeUpload(config: {
|
|
251
|
+
id: string;
|
|
252
|
+
}): Promise<void>;
|
|
253
|
+
private stopped;
|
|
254
|
+
private index;
|
|
255
|
+
private mem;
|
|
256
|
+
private indexFileCount;
|
|
257
|
+
private indexByteCount;
|
|
258
|
+
private sourceFileCounts;
|
|
259
|
+
private sourceByteCounts;
|
|
260
|
+
private syncActivities;
|
|
261
|
+
private dirty;
|
|
262
|
+
private overlay;
|
|
263
|
+
private sourceStates;
|
|
264
|
+
private syncStarted;
|
|
265
|
+
private entries;
|
|
266
|
+
private sourcesList;
|
|
267
|
+
private slotSourcesListIndexes;
|
|
268
|
+
private slotRegistrations;
|
|
269
|
+
private isLive;
|
|
270
|
+
private registerSlot;
|
|
271
|
+
private sourcesListIndexOfSlot;
|
|
272
|
+
private slotForSourcesListIndex;
|
|
273
|
+
private getEntryHolder;
|
|
274
|
+
private loadIndex;
|
|
275
|
+
private countEntry;
|
|
276
|
+
private setIndexEntry;
|
|
277
|
+
private deleteIndexEntry;
|
|
278
|
+
private removeSource;
|
|
148
279
|
private flushIndex;
|
|
280
|
+
private assertMutable;
|
|
281
|
+
private assertInternalWriteAccepted;
|
|
149
282
|
private runSourceSync;
|
|
150
283
|
private isDeadIntermediate;
|
|
151
284
|
private scanSource;
|
|
@@ -156,43 +289,15 @@ export declare class BlobStore implements IBucketStore {
|
|
|
156
289
|
private waitForRequiredScans;
|
|
157
290
|
private checkMissingKey;
|
|
158
291
|
private getIndexEntry;
|
|
159
|
-
get(key: string, config?: GetConfig): Promise<Buffer | undefined>;
|
|
160
|
-
get2(key: string, config?: GetConfig): Promise<{
|
|
161
|
-
data: Buffer;
|
|
162
|
-
writeTime: number;
|
|
163
|
-
size: number;
|
|
164
|
-
} | undefined>;
|
|
165
292
|
/** Internal (store-to-store) read: purely the local disk, completely short-circuiting the index and holder resolution - the caller is another store, and chasing OUR remote holders while answering it is how infinite get loops between stores form. No window or route checks: if the bytes are on our disk, the caller may have them. Note fast writes still sitting in the overlay are invisible here; the caller re-finds them after our flush. */
|
|
166
|
-
getInternal2
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
size: number;
|
|
170
|
-
} | undefined>;
|
|
171
|
-
/** Internal (store-to-store) write: the local disk plus our index, with NO downstream fan-out - the pushing store owns propagation, and fanning its pushes back out is how write loops between stores form. Window/route acceptance is the caller's (writeBucketFile's) job; only-take-latest still applies here. */
|
|
172
|
-
setInternal(key: string, data: Buffer, config: {
|
|
173
|
-
lastModified: number;
|
|
174
|
-
}): Promise<void>;
|
|
293
|
+
private getInternal2;
|
|
294
|
+
/** Internal (store-to-store) write: the local disk plus our index, with NO downstream fan-out - the pushing store owns propagation, and fanning its pushes back out is how write loops between stores form. Only-take-latest still applies here. */
|
|
295
|
+
private setInternal;
|
|
175
296
|
private cacheRead;
|
|
176
|
-
set(key: string, data: Buffer, config?: WriteConfig): Promise<string>;
|
|
177
|
-
del(key: string, config?: WriteConfig): Promise<void>;
|
|
178
297
|
private setOrDelete;
|
|
179
298
|
private getWritableSources;
|
|
180
299
|
private writeToSources;
|
|
181
|
-
getInfo(key: string, config?: GetInfoConfig): Promise<{
|
|
182
|
-
writeTime: number;
|
|
183
|
-
size: number;
|
|
184
|
-
} | undefined>;
|
|
185
|
-
findInfo(prefix: string, config?: {
|
|
186
|
-
shallow?: boolean;
|
|
187
|
-
type?: "files" | "folders";
|
|
188
|
-
}): Promise<ArchiveFileInfo[]>;
|
|
189
|
-
getChangesAfter2(config: ChangesAfterConfig): Promise<ArchiveFileInfo[]>;
|
|
190
|
-
getSyncStatus(): Promise<ArchivesSyncStatus>;
|
|
191
300
|
private getDiskSource;
|
|
192
|
-
startLargeUpload(): Promise<string>;
|
|
193
|
-
appendLargeUpload(id: string, data: Buffer): Promise<void>;
|
|
194
|
-
finishLargeUpload(id: string, key: string, lastModified?: number): Promise<void>;
|
|
195
|
-
cancelLargeUpload(id: string): Promise<void>;
|
|
196
301
|
private flushOverlay;
|
|
197
302
|
private evicting;
|
|
198
303
|
private enforceDiskLimit;
|