sliftutils 1.7.48 → 1.7.50

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.
Files changed (35) hide show
  1. package/index.d.ts +99 -38
  2. package/package.json +1 -1
  3. package/storage/ArchivesDisk.d.ts +5 -5
  4. package/storage/ArchivesDisk.ts +19 -5
  5. package/storage/IArchives.d.ts +36 -7
  6. package/storage/IArchives.ts +76 -8
  7. package/storage/backblaze.d.ts +4 -4
  8. package/storage/backblaze.ts +89 -36
  9. package/storage/dist/ArchivesDisk.ts.cache +8 -2
  10. package/storage/dist/IArchives.ts.cache +2 -2
  11. package/storage/dist/backblaze.ts.cache +86 -36
  12. package/storage/remoteStorage/ArchivesRemote.d.ts +4 -5
  13. package/storage/remoteStorage/ArchivesRemote.ts +7 -7
  14. package/storage/remoteStorage/ArchivesUrl.d.ts +2 -1
  15. package/storage/remoteStorage/ArchivesUrl.ts +13 -3
  16. package/storage/remoteStorage/blobStore.d.ts +15 -6
  17. package/storage/remoteStorage/blobStore.ts +198 -115
  18. package/storage/remoteStorage/createArchives.d.ts +4 -5
  19. package/storage/remoteStorage/createArchives.ts +6 -11
  20. package/storage/remoteStorage/dist/ArchivesRemote.ts.cache +5 -5
  21. package/storage/remoteStorage/dist/ArchivesUrl.ts.cache +15 -4
  22. package/storage/remoteStorage/dist/blobStore.ts.cache +194 -108
  23. package/storage/remoteStorage/dist/createArchives.ts.cache +4 -9
  24. package/storage/remoteStorage/dist/remoteConfig.ts.cache +15 -3
  25. package/storage/remoteStorage/dist/sourcesList.ts.cache +79 -0
  26. package/storage/remoteStorage/dist/storageController.ts.cache +7 -10
  27. package/storage/remoteStorage/dist/storageServerState.ts.cache +50 -18
  28. package/storage/remoteStorage/remoteConfig.d.ts +3 -1
  29. package/storage/remoteStorage/remoteConfig.ts +11 -1
  30. package/storage/remoteStorage/sourcesList.d.ts +15 -0
  31. package/storage/remoteStorage/sourcesList.ts +69 -0
  32. package/storage/remoteStorage/storageController.d.ts +4 -4
  33. package/storage/remoteStorage/storageController.ts +11 -14
  34. package/storage/remoteStorage/storageServerState.d.ts +3 -0
  35. package/storage/remoteStorage/storageServerState.ts +40 -15
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="node" />
3
- import { IArchives, ArchiveFileInfo, ArchivesConfig, ArchivesSyncStatus } from "../IArchives";
3
+ import { IArchives, ArchiveFileInfo, ArchivesConfig, ArchivesSyncStatus, ChangesAfterConfig, SetConfig } from "../IArchives";
4
4
  export type ArchivesRemoteConfig = {
5
5
  url: string;
6
6
  waitForAccess?: boolean;
@@ -55,9 +55,7 @@ export declare class ArchivesRemote implements IArchives {
55
55
  writeTime: number;
56
56
  size: number;
57
57
  } | undefined>;
58
- set(fileName: string, data: Buffer, config?: {
59
- lastModified?: number;
60
- }): Promise<string>;
58
+ set(fileName: string, data: Buffer, config?: SetConfig): Promise<string>;
61
59
  del(fileName: string): Promise<void>;
62
60
  getInfo(fileName: string): Promise<{
63
61
  writeTime: number;
@@ -71,11 +69,12 @@ export declare class ArchivesRemote implements IArchives {
71
69
  shallow?: boolean;
72
70
  type: "files" | "folders";
73
71
  }): Promise<string[]>;
74
- getChangesAfter(time: number): Promise<ArchiveFileInfo[]>;
72
+ getChangesAfter2(config: ChangesAfterConfig): Promise<ArchiveFileInfo[]>;
75
73
  getConfig(): Promise<ArchivesConfig>;
76
74
  getSyncStatus(): Promise<ArchivesSyncStatus>;
77
75
  setLargeFile(config: {
78
76
  path: string;
77
+ lastModified?: number;
79
78
  getNextData(): Promise<Buffer | undefined>;
80
79
  }): Promise<void>;
81
80
  getURL(path: string): Promise<string>;
@@ -2,7 +2,7 @@ import { SocketFunction } from "socket-function/SocketFunction";
2
2
  import { timeInMinute } from "socket-function/src/misc";
3
3
  import { delay } from "socket-function/src/batching";
4
4
  import { getIdentityCA, loadIdentityCA, sign } from "../../misc/https/certs";
5
- import { IArchives, ArchiveFileInfo, ArchivesConfig, ArchivesSyncStatus } from "../IArchives";
5
+ import { IArchives, ArchiveFileInfo, ArchivesConfig, ArchivesSyncStatus, ChangesAfterConfig, SetConfig } from "../IArchives";
6
6
  import { parseHostedUrl, getBucketBaseUrl, buildFileUrl } from "./remoteConfig";
7
7
  import {
8
8
  RemoteStorageController, STORAGE_AUTH_PURPOSE,
@@ -145,8 +145,8 @@ export class ArchivesRemote implements IArchives {
145
145
  let result = await this.call(() => this.controller.get2(this.account, this.bucketName, fileName, config?.range));
146
146
  return result && { data: Buffer.from(result.data), writeTime: result.writeTime, size: result.size } || undefined;
147
147
  }
148
- public async set(fileName: string, data: Buffer, config?: { lastModified?: number }): Promise<string> {
149
- await this.call(() => this.controller.set(this.account, this.bucketName, fileName, data, config?.lastModified));
148
+ public async set(fileName: string, data: Buffer, config?: SetConfig): Promise<string> {
149
+ await this.call(() => this.controller.set(this.account, this.bucketName, fileName, data, config?.lastModified, config?.forceSetImmutable));
150
150
  return fileName;
151
151
  }
152
152
  public async del(fileName: string): Promise<void> {
@@ -161,8 +161,8 @@ export class ArchivesRemote implements IArchives {
161
161
  public async find(prefix: string, config?: { shallow?: boolean; type: "files" | "folders" }): Promise<string[]> {
162
162
  return (await this.findInfo(prefix, config)).map(x => x.path);
163
163
  }
164
- public async getChangesAfter(time: number): Promise<ArchiveFileInfo[]> {
165
- return await this.call(() => this.controller.getChangesAfter(this.account, this.bucketName, time));
164
+ public async getChangesAfter2(config: ChangesAfterConfig): Promise<ArchiveFileInfo[]> {
165
+ return await this.call(() => this.controller.getChangesAfter2(this.account, this.bucketName, config));
166
166
  }
167
167
  public async getConfig(): Promise<ArchivesConfig> {
168
168
  return await this.call(() => this.controller.getArchivesConfig(this.account, this.bucketName));
@@ -171,10 +171,10 @@ export class ArchivesRemote implements IArchives {
171
171
  return await this.call(() => this.controller.getSyncStatus(this.account, this.bucketName));
172
172
  }
173
173
 
174
- public async setLargeFile(config: { path: string; getNextData(): Promise<Buffer | undefined> }): Promise<void> {
174
+ public async setLargeFile(config: { path: string; lastModified?: number; getNextData(): Promise<Buffer | undefined> }): Promise<void> {
175
175
  // Ensure we're authenticated with access BEFORE consuming any data (the stream cannot be rewound, so we can't use the retry loop around the actual upload)
176
176
  await this.call(() => this.controller.getInfo(this.account, this.bucketName, config.path));
177
- let uploadId = await this.controller.startLargeFile(this.account, this.bucketName, config.path);
177
+ let uploadId = await this.controller.startLargeFile(this.account, this.bucketName, config.path, config.lastModified);
178
178
  try {
179
179
  while (true) {
180
180
  let data = await config.getNextData();
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="node" />
3
- import { IArchives, ArchiveFileInfo, ArchivesConfig } from "../IArchives";
3
+ import { IArchives, ArchiveFileInfo, ArchivesConfig, ChangesAfterConfig } from "../IArchives";
4
4
  export declare class ArchivesUrl implements IArchives {
5
5
  private base;
6
6
  constructor(base: string);
@@ -42,6 +42,7 @@ export declare class ArchivesUrl implements IArchives {
42
42
  shallow?: boolean;
43
43
  type: "files" | "folders";
44
44
  }): Promise<ArchiveFileInfo[]>;
45
+ getChangesAfter2(config: ChangesAfterConfig): Promise<ArchiveFileInfo[]>;
45
46
  getURL(path: string): Promise<string>;
46
47
  getConfig(): Promise<ArchivesConfig>;
47
48
  hasWriteAccess(): Promise<boolean>;
@@ -1,5 +1,5 @@
1
1
  import { httpsRequest, HttpsResponseInfo } from "socket-function/src/https";
2
- import { IArchives, ArchiveFileInfo, ArchivesConfig } from "../IArchives";
2
+ import { IArchives, ArchiveFileInfo, ArchivesConfig, ChangesAfterConfig } from "../IArchives";
3
3
  import { buildFileUrl } from "./remoteConfig";
4
4
 
5
5
  // Read-only IArchives over a public bucket's plain-URL form (our storage server's
@@ -53,8 +53,15 @@ export class ArchivesUrl implements IArchives {
53
53
  return { data, writeTime, size };
54
54
  }
55
55
  public async getInfo(fileName: string): Promise<{ writeTime: number; size: number } | undefined> {
56
- let result = await this.get2(fileName);
57
- return result && { writeTime: result.writeTime, size: result.size } || undefined;
56
+ // A 1-byte ranged read: Content-Range carries the full size and Last-Modified the write time, so metadata never downloads the file
57
+ try {
58
+ let result = await this.get2(fileName, { range: { start: 0, end: 1 } });
59
+ return result && { writeTime: result.writeTime, size: result.size } || undefined;
60
+ } catch {
61
+ // Some servers reject ranged reads of empty files (416 instead of an empty 206); a full read is the fallback, and for an empty file it is free anyway
62
+ let result = await this.get2(fileName);
63
+ return result && { writeTime: result.writeTime, size: result.size } || undefined;
64
+ }
58
65
  }
59
66
 
60
67
  public async set(fileName: string, data: Buffer, config?: { lastModified?: number }): Promise<string> {
@@ -72,6 +79,9 @@ export class ArchivesUrl implements IArchives {
72
79
  public async findInfo(prefix: string, config?: { shallow?: boolean; type: "files" | "folders" }): Promise<ArchiveFileInfo[]> {
73
80
  throw this.readOnlyError("findInfo (listing)");
74
81
  }
82
+ public async getChangesAfter2(config: ChangesAfterConfig): Promise<ArchiveFileInfo[]> {
83
+ throw this.readOnlyError("getChangesAfter2 (listing)");
84
+ }
75
85
 
76
86
  public async getURL(path: string): Promise<string> {
77
87
  return buildFileUrl(this.base, path);
@@ -1,6 +1,6 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="node" />
3
- import { IArchives, ArchiveFileInfo, ArchivesSource, ArchivesSyncStatus, SyncActivity } from "../IArchives";
3
+ import { IArchives, ArchiveFileInfo, ArchivesSource, ArchivesSyncStatus, ChangesAfterConfig, SyncActivity } from "../IArchives";
4
4
  export declare const DEFAULT_FAST_WRITE_DELAY: number;
5
5
  export declare const WINDOW_END_FLUSH_MARGIN: number;
6
6
  export type WriteConfig = {
@@ -35,7 +35,7 @@ export type IBucketStore = {
35
35
  shallow?: boolean;
36
36
  type?: "files" | "folders";
37
37
  }): Promise<ArchiveFileInfo[]>;
38
- getChangesAfter?(time: number): Promise<ArchiveFileInfo[]>;
38
+ getChangesAfter2(config: ChangesAfterConfig): Promise<ArchiveFileInfo[]>;
39
39
  getSyncStatus?(): Promise<ArchivesSyncStatus>;
40
40
  getSyncProgress?(): {
41
41
  index: {
@@ -61,11 +61,12 @@ export type IBucketStore = {
61
61
  }>;
62
62
  startLargeUpload(): Promise<string>;
63
63
  appendLargeUpload(id: string, data: Buffer): Promise<void>;
64
- finishLargeUpload(id: string, key: string): Promise<void>;
64
+ finishLargeUpload(id: string, key: string, lastModified?: number): Promise<void>;
65
65
  cancelLargeUpload(id: string): Promise<void>;
66
66
  };
67
67
  export type BlobSourceSpec = {
68
68
  identity: string;
69
+ url: string;
69
70
  validWindow: [number, number];
70
71
  route?: [number, number];
71
72
  noFullSync?: boolean;
@@ -79,6 +80,7 @@ export declare class BlobStore implements IBucketStore {
79
80
  onIndexChanged?: ((key: string) => void) | undefined;
80
81
  readerDiskLimit?: number | undefined;
81
82
  onWriteCounted?: ((kind: "original" | "flushed", bytes: number) => void) | undefined;
83
+ resolveSourceUrl?: ((url: string) => IArchives) | undefined;
82
84
  } | undefined);
83
85
  private stopped;
84
86
  private index;
@@ -92,7 +94,14 @@ export declare class BlobStore implements IBucketStore {
92
94
  private overlay;
93
95
  private sourceStates;
94
96
  private syncStarted;
97
+ private sourcesList;
98
+ private slotSourcesListIndexes;
99
+ private slotRegistrations;
95
100
  private isLive;
101
+ private registerSlot;
102
+ private sourcesListIndexOfSlot;
103
+ private slotForSourcesListIndex;
104
+ private getEntryHolder;
96
105
  init: {
97
106
  (): Promise<void>;
98
107
  reset(): void;
@@ -141,7 +150,7 @@ export declare class BlobStore implements IBucketStore {
141
150
  private runSourceSync;
142
151
  private scanSource;
143
152
  private reconcileSource;
144
- private applyScanned;
153
+ private updateScanIndex;
145
154
  private pollChanges;
146
155
  private copySourceFiles;
147
156
  private waitForRequiredScans;
@@ -176,12 +185,12 @@ export declare class BlobStore implements IBucketStore {
176
185
  shallow?: boolean;
177
186
  type?: "files" | "folders";
178
187
  }): Promise<ArchiveFileInfo[]>;
179
- getChangesAfter(time: number): Promise<ArchiveFileInfo[]>;
188
+ getChangesAfter2(config: ChangesAfterConfig): Promise<ArchiveFileInfo[]>;
180
189
  getSyncStatus(): Promise<ArchivesSyncStatus>;
181
190
  private getDiskSource;
182
191
  startLargeUpload(): Promise<string>;
183
192
  appendLargeUpload(id: string, data: Buffer): Promise<void>;
184
- finishLargeUpload(id: string, key: string): Promise<void>;
193
+ finishLargeUpload(id: string, key: string, lastModified?: number): Promise<void>;
185
194
  cancelLargeUpload(id: string): Promise<void>;
186
195
  private flushOverlay;
187
196
  private evicting;