@milaboratories/pl-drivers 1.2.35 → 1.3.0

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 (38) hide show
  1. package/dist/clients/download.d.ts +5 -2
  2. package/dist/clients/download.d.ts.map +1 -1
  3. package/dist/clients/helpers.d.ts +2 -2
  4. package/dist/clients/helpers.d.ts.map +1 -1
  5. package/dist/drivers/helpers/ls_list_entry.d.ts +8 -13
  6. package/dist/drivers/helpers/ls_list_entry.d.ts.map +1 -1
  7. package/dist/drivers/helpers/ls_storage_entry.d.ts +6 -8
  8. package/dist/drivers/helpers/ls_storage_entry.d.ts.map +1 -1
  9. package/dist/drivers/ls.d.ts +40 -12
  10. package/dist/drivers/ls.d.ts.map +1 -1
  11. package/dist/drivers/types.d.ts +80 -0
  12. package/dist/drivers/types.d.ts.map +1 -0
  13. package/dist/drivers/upload.d.ts +18 -26
  14. package/dist/drivers/upload.d.ts.map +1 -1
  15. package/dist/helpers/validate.d.ts +2 -0
  16. package/dist/helpers/validate.d.ts.map +1 -0
  17. package/dist/index.d.ts +2 -0
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +1 -1
  20. package/dist/index.js.map +1 -1
  21. package/dist/index.mjs +943 -918
  22. package/dist/index.mjs.map +1 -1
  23. package/package.json +5 -5
  24. package/src/clients/download.test.ts +5 -14
  25. package/src/clients/download.ts +13 -5
  26. package/src/clients/helpers.ts +13 -43
  27. package/src/drivers/download_blob.test.ts +4 -4
  28. package/src/drivers/helpers/ls_list_entry.test.ts +5 -7
  29. package/src/drivers/helpers/ls_list_entry.ts +31 -36
  30. package/src/drivers/helpers/ls_storage_entry.ts +18 -62
  31. package/src/drivers/logs.test.ts +3 -3
  32. package/src/drivers/ls.test.ts +112 -30
  33. package/src/drivers/ls.ts +233 -83
  34. package/src/drivers/types.ts +41 -0
  35. package/src/drivers/upload.test.ts +43 -82
  36. package/src/drivers/upload.ts +59 -111
  37. package/src/helpers/validate.ts +6 -0
  38. package/src/index.ts +3 -0
@@ -1,35 +1,27 @@
1
1
  import {
2
- FieldId,
3
2
  isNotNullResourceId,
4
3
  PlTransaction,
5
4
  PollTxAccessor,
6
5
  ResourceId,
7
6
  TestHelpers
8
7
  } from '@milaboratories/pl-client';
9
- import {
10
- ConsoleLoggerAdapter,
11
- HmacSha256Signer,
12
- Signer
13
- } from '@milaboratories/ts-helpers';
14
- import * as fs from 'node:fs';
8
+ import { ConsoleLoggerAdapter, HmacSha256Signer, Signer } from '@milaboratories/ts-helpers';
15
9
  import * as fsp from 'node:fs/promises';
16
10
  import * as os from 'node:os';
17
11
  import * as path from 'node:path';
18
12
  import { PlClient } from '@milaboratories/pl-client';
19
- import { poll } from '@milaboratories/pl-client';
20
- import { UploadOpts, UploadDriver, UploadResourceSnapshot } from './upload';
21
- import {
22
- createUploadBlobClient,
23
- createUploadProgressClient
24
- } from '../clients/helpers';
25
- import { Writable, Readable } from 'node:stream';
13
+ import { ImportResourceSnapshot, makeBlobImportSnapshot, UploadDriver } from './upload';
14
+ import { createUploadBlobClient, createUploadProgressClient } from '../clients/helpers';
15
+
26
16
  import { test, expect } from '@jest/globals';
17
+ import { SynchronizedTreeState } from '@milaboratories/pl-tree';
18
+ import { Computable } from '@milaboratories/computable';
27
19
 
28
20
  test('upload a blob', async () => {
29
21
  await withTest(async ({ client, uploader, signer }: TestArg) => {
30
22
  const stats = await writeFile('42', signer);
31
23
  const uploadId = await createBlobUpload(client, stats);
32
- const handleRes = await getHandleField(client, uploadId);
24
+ const handleRes = await getSnapshot(client, uploadId);
33
25
 
34
26
  const c = uploader.getProgressId(handleRes);
35
27
 
@@ -61,7 +53,7 @@ test('upload a big blob', async () => {
61
53
  await withTest(async ({ client, uploader, signer }: TestArg) => {
62
54
  const stats = await writeFile(hugeString, signer);
63
55
  const uploadId = await createBlobUpload(client, stats);
64
- const handleRes = await getHandleField(client, uploadId);
56
+ const handleRes = await getSnapshot(client, uploadId);
65
57
 
66
58
  const c = uploader.getProgressId(handleRes);
67
59
 
@@ -113,7 +105,7 @@ test.skip('upload a very big blob', async () => {
113
105
  '/home/snyssfx/Downloads/Kung Fu Hustle (2004) Open Matte 1080p.mkv'
114
106
  );
115
107
  const uploadId = await createBlobUpload(client, stats);
116
- const handleRes = await getHandleField(client, uploadId);
108
+ const handleRes = await getSnapshot(client, uploadId);
117
109
 
118
110
  const c = uploader.getProgressId(handleRes);
119
111
 
@@ -139,7 +131,7 @@ test('upload a blob with wrong modification time', async () => {
139
131
  const stats = await writeFile('42', signer);
140
132
  stats.mtime -= 1000n;
141
133
  const uploadId = await createBlobUpload(client, stats);
142
- const handleRes = await getHandleField(client, uploadId);
134
+ const handleRes = await getSnapshot(client, uploadId);
143
135
 
144
136
  const c = uploader.getProgressId(handleRes);
145
137
 
@@ -162,7 +154,7 @@ test('upload a duplicate blob', async () => {
162
154
  await withTest(async ({ client, uploader, signer }: TestArg) => {
163
155
  const stats = await writeFile('42', signer);
164
156
  const uploadId = await createBlobUpload(client, stats);
165
- const handleRes = await getHandleField(client, uploadId);
157
+ const handleRes = await getSnapshot(client, uploadId);
166
158
 
167
159
  const cOrig = uploader.getProgressId(handleRes);
168
160
  const cDupl = uploader.getProgressId(handleRes);
@@ -215,9 +207,7 @@ test('upload lots of duplicate blobs concurrently', async () => {
215
207
 
216
208
  const { uploadIds } = await createMapOfUploads(client, n, settings);
217
209
 
218
- const handles = await Promise.all(
219
- uploadIds.map((id) => getHandleField(client, id))
220
- );
210
+ const handles = await Promise.all(uploadIds.map((id) => getSnapshot(client, id)));
221
211
  const computables = handles.map((handle) => uploader.getProgressId(handle));
222
212
 
223
213
  for (const c of computables) {
@@ -247,7 +237,7 @@ test('index a blob', async () => {
247
237
  './another_answer_to_the_ultimate_question.txt',
248
238
  'library'
249
239
  );
250
- const handleRes = await getHandleField(client, uploadId);
240
+ const handleRes = await getSnapshot(client, uploadId);
251
241
 
252
242
  const c = uploader.getProgressId(handleRes);
253
243
 
@@ -302,8 +292,7 @@ async function writeFile(
302
292
  tmpDir?: string,
303
293
  fileName: string = 'testUploadABlob.txt'
304
294
  ): Promise<FileStat> {
305
- if (tmpDir == undefined)
306
- tmpDir = await fsp.mkdtemp(path.join(os.tmpdir(), 'test'));
295
+ if (tmpDir == undefined) tmpDir = await fsp.mkdtemp(path.join(os.tmpdir(), 'test'));
307
296
 
308
297
  const fPath = path.join(tmpDir, fileName);
309
298
 
@@ -321,11 +310,7 @@ async function getFileStats(signer: Signer, fPath: string): Promise<FileStat> {
321
310
  return { fPath, mtime, fileSignature, size: stats.size };
322
311
  }
323
312
 
324
- async function createMapOfUploads(
325
- c: PlClient,
326
- n: number,
327
- settings: FileStat[]
328
- ) {
313
+ async function createMapOfUploads(c: PlClient, n: number, settings: FileStat[]) {
329
314
  return await c.withWriteTx(
330
315
  'UploaderCreateMapOfUploads',
331
316
  async (tx: PlTransaction) => {
@@ -340,11 +325,7 @@ async function createMapOfUploads(
340
325
  tx.setField(fId, uploadId);
341
326
  }
342
327
 
343
- tx.createField(
344
- { resourceId: c.clientRoot, fieldName: 'project1' },
345
- 'Dynamic',
346
- mapId
347
- );
328
+ tx.createField({ resourceId: c.clientRoot, fieldName: 'project1' }, 'Dynamic', mapId);
348
329
  await tx.commit();
349
330
 
350
331
  return {
@@ -356,20 +337,13 @@ async function createMapOfUploads(
356
337
  );
357
338
  }
358
339
 
359
- async function createBlobUpload(
360
- c: PlClient,
361
- stat: FileStat
362
- ): Promise<ResourceId> {
340
+ async function createBlobUpload(c: PlClient, stat: FileStat): Promise<ResourceId> {
363
341
  return await c.withWriteTx(
364
342
  'UploadDriverCreateTest',
365
343
  async (tx: PlTransaction) => {
366
344
  const uploadId = await createBlobUploadTx(tx, stat);
367
345
 
368
- tx.createField(
369
- { resourceId: c.clientRoot, fieldName: 'project1' },
370
- 'Dynamic',
371
- uploadId
372
- );
346
+ tx.createField({ resourceId: c.clientRoot, fieldName: 'project1' }, 'Dynamic', uploadId);
373
347
  await tx.commit();
374
348
 
375
349
  return uploadId;
@@ -378,10 +352,7 @@ async function createBlobUpload(
378
352
  );
379
353
  }
380
354
 
381
- async function createBlobUploadTx(
382
- tx: PlTransaction,
383
- stat: FileStat
384
- ): Promise<ResourceId> {
355
+ async function createBlobUploadTx(tx: PlTransaction, stat: FileStat): Promise<ResourceId> {
385
356
  const settings = {
386
357
  modificationTime: stat.mtime.toString(),
387
358
  localPath: stat.fPath,
@@ -394,11 +365,7 @@ async function createBlobUploadTx(
394
365
  return await upload.globalId;
395
366
  }
396
367
 
397
- async function createBlobIndex(
398
- c: PlClient,
399
- path: string,
400
- storageId: string
401
- ): Promise<ResourceId> {
368
+ async function createBlobIndex(c: PlClient, path: string, storageId: string): Promise<ResourceId> {
402
369
  return await c.withWriteTx(
403
370
  'UploadDriverCreateTest',
404
371
  async (tx: PlTransaction) => {
@@ -407,10 +374,7 @@ async function createBlobIndex(
407
374
  path: path
408
375
  };
409
376
  const data = new TextEncoder().encode(JSON.stringify(settings));
410
- const importInternal = tx.createStruct(
411
- { name: 'BlobImportInternal', version: '1' },
412
- data
413
- );
377
+ const importInternal = tx.createStruct({ name: 'BlobImportInternal', version: '1' }, data);
414
378
  tx.createField(
415
379
  { resourceId: c.clientRoot, fieldName: 'project1' },
416
380
  'Dynamic',
@@ -424,32 +388,29 @@ async function createBlobIndex(
424
388
  );
425
389
  }
426
390
 
427
- async function getHandleField(
391
+ async function getSnapshot(
428
392
  client: PlClient,
429
393
  uploadId: ResourceId
430
- ): Promise<UploadResourceSnapshot> {
431
- return await poll(client, async (tx: PollTxAccessor) => {
432
- const upload = await tx.get(uploadId);
433
- const handle = await upload.get('handle');
434
-
435
- const blob = handle.data.fields.find((f) => f.name == 'blob')?.value;
436
- const incarnation = handle.data.fields.find(
437
- (f) => f.name == 'incarnation'
438
- )?.value;
439
-
440
- const fields = {
441
- blob: undefined as ResourceId | undefined,
442
- incarnation: undefined as ResourceId | undefined
443
- };
444
- if (blob != undefined && isNotNullResourceId(blob)) fields.blob = blob;
445
- if (incarnation != undefined && isNotNullResourceId(incarnation))
446
- fields.incarnation = incarnation;
447
-
448
- return {
449
- ...handle.data,
450
- data: JSON.parse(handle.data.data!.toString()) as UploadOpts,
451
- fields,
452
- kv: undefined
453
- };
394
+ ): Promise<ImportResourceSnapshot> {
395
+ const tree = await SynchronizedTreeState.init(client, uploadId, {
396
+ stopPollingDelay: 600,
397
+ pollingInterval: 300
454
398
  });
399
+ try {
400
+ const computable = Computable.make((ctx) => {
401
+ const handle = ctx
402
+ .accessor(tree.entry())
403
+ .node()
404
+ .traverse({ field: 'handle', assertFieldType: 'Output' });
405
+ if (!handle) return undefined;
406
+ else return makeBlobImportSnapshot(handle, ctx);
407
+ }).withStableType();
408
+ while (true) {
409
+ const value = await computable.getValue();
410
+ if (value !== undefined) return value;
411
+ await computable.awaitChange();
412
+ }
413
+ } finally {
414
+ await tree.terminate();
415
+ }
455
416
  }
@@ -1,8 +1,5 @@
1
1
  import { randomUUID } from 'node:crypto';
2
- import {
3
- ResourceId,
4
- stringifyWithResourceId
5
- } from '@milaboratories/pl-client';
2
+ import { ResourceId, stringifyWithResourceId } from '@milaboratories/pl-client';
6
3
  import {
7
4
  Watcher,
8
5
  ChangeSource,
@@ -19,47 +16,55 @@ import {
19
16
  } from '@milaboratories/ts-helpers';
20
17
  import * as sdk from '@milaboratories/pl-model-common';
21
18
  import { ProgressStatus, ClientProgress } from '../clients/progress';
22
- import {
23
- ClientUpload,
24
- MTimeError,
25
- NoFileForUploading,
26
- UnexpectedEOF
27
- } from '../clients/upload';
19
+ import { ClientUpload, MTimeError, NoFileForUploading, UnexpectedEOF } from '../clients/upload';
28
20
  import {
29
21
  InferSnapshot,
30
22
  isPlTreeEntry,
23
+ isPlTreeEntryAccessor,
31
24
  makeResourceSnapshot,
32
25
  PlTreeEntry,
26
+ PlTreeEntryAccessor,
27
+ PlTreeNodeAccessor,
33
28
  rsSchema
34
29
  } from '@milaboratories/pl-tree';
35
30
  import { scheduler } from 'node:timers/promises';
36
31
  import { PollingOps } from './helpers/polling_ops';
37
- import { z } from 'zod';
32
+ import { ImportFileHandleUploadData } from './types';
38
33
 
39
34
  /** Options from BlobUpload resource that have to be passed to getProgress. */
40
35
 
41
- const UploadOptsSchema = z.object({
42
- localPath: z.string(),
43
- pathSignature: z.string(),
44
- modificationTime: z.string()
45
- });
46
-
47
- const ImportOptsSchema = z.union([UploadOptsSchema, z.object({})]);
48
-
49
- export type UploadOpts = z.infer<typeof UploadOptsSchema>;
50
-
51
36
  /** ResourceSnapshot that can be passed to GetProgressID */
52
37
  export const UploadResourceSnapshot = rsSchema({
53
- data: ImportOptsSchema,
38
+ data: ImportFileHandleUploadData,
39
+ fields: {
40
+ blob: false
41
+ }
42
+ });
43
+
44
+ export const IndexResourceSnapshot = rsSchema({
54
45
  fields: {
55
- blob: false, // for BlobUpload
56
- incarnation: false // for BlobIndex
46
+ incarnation: false
57
47
  }
58
48
  });
59
49
 
60
- export type UploadResourceSnapshot = InferSnapshot<
61
- typeof UploadResourceSnapshot
62
- >;
50
+ export type UploadResourceSnapshot = InferSnapshot<typeof UploadResourceSnapshot>;
51
+ export type IndexResourceSnapshot = InferSnapshot<typeof IndexResourceSnapshot>;
52
+
53
+ export type ImportResourceSnapshot = UploadResourceSnapshot | IndexResourceSnapshot;
54
+
55
+ export function makeBlobImportSnapshot(
56
+ entryOrAccessor: PlTreeEntry | PlTreeNodeAccessor | PlTreeEntryAccessor,
57
+ ctx: ComputableCtx
58
+ ): ImportResourceSnapshot {
59
+ const node = isPlTreeEntry(entryOrAccessor)
60
+ ? ctx.accessor(entryOrAccessor).node()
61
+ : isPlTreeEntryAccessor(entryOrAccessor)
62
+ ? entryOrAccessor.node()
63
+ : entryOrAccessor;
64
+ if (node.resourceType.name.startsWith('BlobUpload'))
65
+ return makeResourceSnapshot(node, UploadResourceSnapshot);
66
+ else return makeResourceSnapshot(node, IndexResourceSnapshot);
67
+ }
63
68
 
64
69
  export type UploadDriverOps = PollingOps & {
65
70
  /** How much parts of a file can be multipart-uploaded to S3 at once. */
@@ -112,22 +117,21 @@ export class UploadDriver {
112
117
 
113
118
  /** Returns a progress id and schedules an upload task if it's necessary. */
114
119
  getProgressId(
115
- res: UploadResourceSnapshot | PlTreeEntry
120
+ handleResource: ImportResourceSnapshot | PlTreeEntry
116
121
  ): Computable<sdk.ImportProgress>;
117
122
  getProgressId(
118
- res: UploadResourceSnapshot | PlTreeEntry,
123
+ handleResource: ImportResourceSnapshot | PlTreeEntry,
119
124
  ctx: ComputableCtx
120
125
  ): sdk.ImportProgress;
121
126
  getProgressId(
122
- res: UploadResourceSnapshot | PlTreeEntry,
127
+ handleResource: ImportResourceSnapshot | PlTreeEntry,
123
128
  ctx?: ComputableCtx
124
129
  ): Computable<sdk.ImportProgress> | sdk.ImportProgress {
125
- if (ctx == undefined)
126
- return Computable.make((ctx) => this.getProgressId(res, ctx));
130
+ if (ctx == undefined) return Computable.make((ctx) => this.getProgressId(handleResource, ctx));
127
131
 
128
- const rInfo: UploadResourceSnapshot = isPlTreeEntry(res)
129
- ? makeResourceSnapshot(res, UploadResourceSnapshot, ctx)
130
- : res;
132
+ const rInfo: ImportResourceSnapshot = isPlTreeEntry(handleResource)
133
+ ? makeBlobImportSnapshot(handleResource, ctx)
134
+ : handleResource;
131
135
 
132
136
  const callerId = randomUUID();
133
137
  ctx.attacheHooks(this.hooks);
@@ -135,9 +139,7 @@ export class UploadDriver {
135
139
 
136
140
  const result = this.getProgressIdNoCtx(ctx.watcher, rInfo, callerId);
137
141
  if (!isProgressStable(result)) {
138
- ctx.markUnstable(
139
- `upload/index progress was got, but it's not stable: ${result}`
140
- );
142
+ ctx.markUnstable(`upload/index progress was got, but it's not stable: ${result}`);
141
143
  }
142
144
 
143
145
  return result;
@@ -145,11 +147,11 @@ export class UploadDriver {
145
147
 
146
148
  private getProgressIdNoCtx(
147
149
  w: Watcher,
148
- res: UploadResourceSnapshot,
150
+ res: ImportResourceSnapshot,
149
151
  callerId: string
150
152
  ): sdk.ImportProgress {
151
153
  const blobExists =
152
- res.fields.blob != undefined || res.fields.incarnation != undefined;
154
+ 'blob' in res.fields ? res.fields.blob !== undefined : res.fields.incarnation !== undefined;
153
155
 
154
156
  const value = this.idToProgress.get(res.id);
155
157
 
@@ -195,10 +197,7 @@ export class UploadDriver {
195
197
 
196
198
  private scheduledOnNextState: ScheduledRefresh[] = [];
197
199
 
198
- private scheduleOnNextState(
199
- resolve: () => void,
200
- reject: (err: any) => void
201
- ): void {
200
+ private scheduleOnNextState(resolve: () => void, reject: (err: any) => void): void {
202
201
  this.scheduledOnNextState.push({ resolve, reject });
203
202
  }
204
203
 
@@ -226,9 +225,7 @@ export class UploadDriver {
226
225
  try {
227
226
  await asyncPool(
228
227
  this.opts.nConcurrentGetProgresses,
229
- this.getAllNotDoneProgresses().map(
230
- (p) => async () => await p.updateStatus()
231
- )
228
+ this.getAllNotDoneProgresses().map((p) => async () => await p.updateStatus())
232
229
  );
233
230
 
234
231
  toNotify.forEach((n) => n.resolve());
@@ -259,7 +256,8 @@ class ProgressUpdater {
259
256
  private readonly counter: CallersCounter = new CallersCounter();
260
257
 
261
258
  public progress: sdk.ImportProgress;
262
- private uploadOpts?: UploadOpts;
259
+ /** If this is upload progress this field will be defined */
260
+ private uploadData?: ImportFileHandleUploadData;
263
261
  public uploadingTerminallyFailed?: boolean;
264
262
 
265
263
  constructor(
@@ -268,17 +266,16 @@ class ProgressUpdater {
268
266
  private readonly clientProgress: ClientProgress,
269
267
  private readonly nConcurrentPartsUpload: number,
270
268
  signer: Signer,
271
-
272
- public readonly res: UploadResourceSnapshot
269
+ public readonly res: ImportResourceSnapshot
273
270
  ) {
274
271
  const isUpload = res.type.name.startsWith('BlobUpload');
275
272
  let isUploadSignMatch: boolean | undefined;
276
273
  if (isUpload) {
277
- this.uploadOpts = importToUploadOpts(res);
274
+ this.uploadData = ImportFileHandleUploadData.parse(res.data);
278
275
  isUploadSignMatch = isSignMatch(
279
276
  signer,
280
- this.uploadOpts.localPath,
281
- this.uploadOpts.pathSignature
277
+ this.uploadData.localPath,
278
+ this.uploadData.pathSignature
282
279
  );
283
280
  }
284
281
 
@@ -299,9 +296,7 @@ class ProgressUpdater {
299
296
  }
300
297
 
301
298
  if (this.uploadingTerminallyFailed) {
302
- this.logger.error(
303
- `Uploading terminally failed: ${this.progress.lastError}`
304
- );
299
+ this.logger.error(`Uploading terminally failed: ${this.progress.lastError}`);
305
300
  throw new Error(this.progress.lastError);
306
301
  }
307
302
 
@@ -346,18 +341,16 @@ class ProgressUpdater {
346
341
  if (this.counter.isZero()) return;
347
342
  const parts = await this.clientBlob.initUpload(this.res);
348
343
 
349
- this.logger.info(
350
- `start to upload blob ${this.res.id}, parts count: ${parts.length}`
351
- );
344
+ this.logger.info(`start to upload blob ${this.res.id}, parts count: ${parts.length}`);
352
345
 
353
346
  const partUploadFn = (part: bigint) => async () => {
354
347
  if (this.counter.isZero()) return;
355
348
  await this.clientBlob.partUpload(
356
349
  this.res,
357
- this.uploadOpts!.localPath,
350
+ this.uploadData!.localPath,
358
351
  part,
359
352
  parts.length,
360
- BigInt(this.uploadOpts!.modificationTime)
353
+ BigInt(this.uploadData!.modificationTime)
361
354
  );
362
355
  };
363
356
 
@@ -382,8 +375,7 @@ class ProgressUpdater {
382
375
 
383
376
  private setDone(done: boolean) {
384
377
  this.progress.done = done;
385
- if (done)
386
- this.progress.lastError = undefined;
378
+ if (done) this.progress.lastError = undefined;
387
379
  }
388
380
 
389
381
  async updateStatus() {
@@ -394,15 +386,12 @@ class ProgressUpdater {
394
386
  this.progress.status = protoToStatus(status);
395
387
  this.setDone(status.done);
396
388
 
397
- if (status.done || status.progress != oldStatus?.progress)
398
- this.change.markChanged();
389
+ if (status.done || status.progress != oldStatus?.progress) this.change.markChanged();
399
390
  } catch (e: any) {
400
391
  this.setLastError(e);
401
392
 
402
393
  if (e.name == 'RpcError' && e.code == 'DEADLINE_EXCEEDED') {
403
- this.logger.warn(
404
- `deadline exceeded while getting a status of BlobImport`
405
- );
394
+ this.logger.warn(`deadline exceeded while getting a status of BlobImport`);
406
395
  return;
407
396
  }
408
397
 
@@ -423,44 +412,7 @@ class ProgressUpdater {
423
412
  }
424
413
 
425
414
  function isProgressStable(p: sdk.ImportProgress) {
426
- return (
427
- p.done &&
428
- p.status !== undefined &&
429
- p.status !== null &&
430
- p.status.progress >= 1.0
431
- );
432
- }
433
-
434
- export function importToUploadOpts(res: UploadResourceSnapshot): UploadOpts {
435
- if (res.data == undefined || !('modificationTime' in res.data)) {
436
- throw new Error(
437
- 'no upload options in BlobUpload resource data: ' +
438
- stringifyWithResourceId(res.data)
439
- );
440
- }
441
-
442
- const opts = res.data;
443
- if (opts.modificationTime === undefined) {
444
- throw new Error(
445
- 'no modification time in data: ' + stringifyWithResourceId(res.data)
446
- );
447
- }
448
- if (opts.localPath === undefined) {
449
- throw new Error(
450
- 'no local path in data: ' + stringifyWithResourceId(res.data)
451
- );
452
- }
453
- if (opts.pathSignature === undefined) {
454
- throw new Error(
455
- 'no path signature in data: ' + stringifyWithResourceId(res.data)
456
- );
457
- }
458
-
459
- return {
460
- modificationTime: opts.modificationTime,
461
- localPath: opts.localPath,
462
- pathSignature: opts.pathSignature
463
- };
415
+ return p.done && p.status !== undefined && p.status !== null && p.status.progress >= 1.0;
464
416
  }
465
417
 
466
418
  function protoToStatus(proto: ProgressStatus): sdk.ImportStatus {
@@ -481,11 +433,7 @@ function isSignMatch(signer: Signer, path: string, signature: string): boolean {
481
433
  }
482
434
 
483
435
  function nonRecoverableError(e: any) {
484
- return (
485
- e instanceof MTimeError ||
486
- e instanceof UnexpectedEOF ||
487
- e instanceof NoFileForUploading
488
- );
436
+ return e instanceof MTimeError || e instanceof UnexpectedEOF || e instanceof NoFileForUploading;
489
437
  }
490
438
 
491
439
  function isResourceWasDeletedError(e: any) {
@@ -0,0 +1,6 @@
1
+ import path from 'node:path';
2
+
3
+ export function validateAbsolute(p: string): string {
4
+ if (!path.isAbsolute(p)) throw new Error(`Path ${p} is not absolute.`);
5
+ return p;
6
+ }
package/src/index.ts CHANGED
@@ -13,3 +13,6 @@ export * from './drivers/download_url';
13
13
  export * from './drivers/ls';
14
14
  export * from './drivers/helpers/helpers';
15
15
  export * from './drivers/helpers/polling_ops';
16
+
17
+ export * from './drivers/types';
18
+ export { validateAbsolute } from './helpers/validate';