@milaboratories/pl-drivers 1.3.25 → 1.4.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 (78) hide show
  1. package/dist/clients/constructors.d.ts +14 -0
  2. package/dist/clients/constructors.d.ts.map +1 -0
  3. package/dist/clients/download.d.ts +19 -14
  4. package/dist/clients/download.d.ts.map +1 -1
  5. package/dist/clients/helpers.d.ts +4 -13
  6. package/dist/clients/helpers.d.ts.map +1 -1
  7. package/dist/clients/upload.d.ts +15 -13
  8. package/dist/clients/upload.d.ts.map +1 -1
  9. package/dist/drivers/{download_and_logs_blob.d.ts → download_blob.d.ts} +13 -40
  10. package/dist/drivers/download_blob.d.ts.map +1 -0
  11. package/dist/drivers/download_blob_task.d.ts +34 -0
  12. package/dist/drivers/download_blob_task.d.ts.map +1 -0
  13. package/dist/drivers/download_url.d.ts +11 -9
  14. package/dist/drivers/download_url.d.ts.map +1 -1
  15. package/dist/drivers/helpers/download_local_handle.d.ts +9 -0
  16. package/dist/drivers/helpers/download_local_handle.d.ts.map +1 -0
  17. package/dist/drivers/helpers/download_remote_handle.d.ts +8 -0
  18. package/dist/drivers/helpers/download_remote_handle.d.ts.map +1 -0
  19. package/dist/drivers/helpers/files_cache.d.ts +2 -1
  20. package/dist/drivers/helpers/files_cache.d.ts.map +1 -1
  21. package/dist/drivers/helpers/helpers.d.ts +2 -24
  22. package/dist/drivers/helpers/helpers.d.ts.map +1 -1
  23. package/dist/drivers/helpers/logs_handle.d.ts +13 -0
  24. package/dist/drivers/helpers/logs_handle.d.ts.map +1 -0
  25. package/dist/drivers/helpers/ls_remote_import_handle.d.ts +8 -0
  26. package/dist/drivers/helpers/ls_remote_import_handle.d.ts.map +1 -0
  27. package/dist/drivers/logs.d.ts +1 -5
  28. package/dist/drivers/logs.d.ts.map +1 -1
  29. package/dist/drivers/logs_stream.d.ts.map +1 -1
  30. package/dist/drivers/ls.d.ts.map +1 -1
  31. package/dist/drivers/types.d.ts +47 -4
  32. package/dist/drivers/types.d.ts.map +1 -1
  33. package/dist/drivers/upload.d.ts +2 -28
  34. package/dist/drivers/upload.d.ts.map +1 -1
  35. package/dist/drivers/upload_task.d.ts +41 -0
  36. package/dist/drivers/upload_task.d.ts.map +1 -0
  37. package/dist/helpers/download.d.ts +2 -2
  38. package/dist/helpers/download.d.ts.map +1 -1
  39. package/dist/index.d.ts +2 -2
  40. package/dist/index.d.ts.map +1 -1
  41. package/dist/index.js +2 -2
  42. package/dist/index.js.map +1 -1
  43. package/dist/index.mjs +1537 -1526
  44. package/dist/index.mjs.map +1 -1
  45. package/package.json +5 -5
  46. package/src/clients/constructors.ts +54 -0
  47. package/src/clients/download.test.ts +9 -6
  48. package/src/clients/download.ts +74 -64
  49. package/src/clients/helpers.ts +2 -53
  50. package/src/clients/upload.ts +136 -102
  51. package/src/drivers/download_blob.test.ts +12 -11
  52. package/src/drivers/{download_and_logs_blob.ts → download_blob.ts} +154 -290
  53. package/src/drivers/download_blob_task.ts +126 -0
  54. package/src/drivers/download_url.test.ts +1 -1
  55. package/src/drivers/download_url.ts +44 -37
  56. package/src/drivers/helpers/download_local_handle.ts +29 -0
  57. package/src/drivers/helpers/download_remote_handle.ts +40 -0
  58. package/src/drivers/helpers/files_cache.test.ts +7 -6
  59. package/src/drivers/helpers/files_cache.ts +6 -5
  60. package/src/drivers/helpers/helpers.ts +6 -100
  61. package/src/drivers/helpers/logs_handle.ts +52 -0
  62. package/src/drivers/helpers/ls_remote_import_handle.ts +43 -0
  63. package/src/drivers/logs.test.ts +14 -14
  64. package/src/drivers/logs.ts +3 -43
  65. package/src/drivers/logs_stream.ts +32 -6
  66. package/src/drivers/ls.test.ts +1 -2
  67. package/src/drivers/ls.ts +26 -28
  68. package/src/drivers/types.ts +48 -0
  69. package/src/drivers/upload.test.ts +8 -18
  70. package/src/drivers/upload.ts +38 -271
  71. package/src/drivers/upload_task.ts +251 -0
  72. package/src/helpers/download.ts +18 -15
  73. package/src/index.ts +2 -2
  74. package/dist/drivers/download_and_logs_blob.d.ts.map +0 -1
  75. package/dist/drivers/helpers/ls_list_entry.d.ts +0 -44
  76. package/dist/drivers/helpers/ls_list_entry.d.ts.map +0 -1
  77. package/src/drivers/helpers/ls_list_entry.test.ts +0 -55
  78. package/src/drivers/helpers/ls_list_entry.ts +0 -147
@@ -1,28 +1,28 @@
1
+ import { expect, test } from '@jest/globals';
2
+ import { Computable } from '@milaboratories/computable';
1
3
  import {
4
+ AnyFieldRef,
5
+ FieldId,
6
+ FieldRef,
2
7
  PlClient,
3
8
  PlTransaction,
9
+ ResourceId,
10
+ ResourceRef,
4
11
  ResourceType,
5
12
  TestHelpers,
6
13
  jsonToData,
7
- FieldRef,
8
- FieldId,
9
- AnyFieldRef,
10
- ResourceRef,
11
- stringifyWithResourceId,
12
- ResourceId
14
+ stringifyWithResourceId
13
15
  } from '@milaboratories/pl-client';
16
+ import { SynchronizedTreeState } from '@milaboratories/pl-tree';
14
17
  import { ConsoleLoggerAdapter, HmacSha256Signer, notEmpty } from '@milaboratories/ts-helpers';
15
- import { scheduler } from 'node:timers/promises';
16
- import { Computable } from '@milaboratories/computable';
17
- import * as os from 'node:os';
18
18
  import * as fsp from 'node:fs/promises';
19
+ import * as os from 'node:os';
19
20
  import * as path from 'node:path';
20
- import { SynchronizedTreeState } from '@milaboratories/pl-tree';
21
- import { DownloadDriver } from './download_and_logs_blob';
22
- import { createDownloadClient, createLogsClient } from '../clients/helpers';
23
- import { LogsStreamDriver } from './logs_stream';
21
+ import { scheduler } from 'node:timers/promises';
22
+ import { createDownloadClient, createLogsClient } from '../clients/constructors';
23
+ import { DownloadDriver } from './download_blob';
24
24
  import { LogsDriver } from './logs';
25
- import { test, expect } from '@jest/globals';
25
+ import { LogsStreamDriver } from './logs_stream';
26
26
 
27
27
  test('should get all logs', async () => {
28
28
  await TestHelpers.withTempRoot(async (client) => {
@@ -1,10 +1,10 @@
1
1
  import { Computable, ComputableCtx } from '@milaboratories/computable';
2
2
  import { PlTreeEntry, ResourceInfo } from '@milaboratories/pl-tree';
3
- import { bigintToResourceId, stringifyWithResourceId } from '@milaboratories/pl-client';
4
3
  import { LogsStreamDriver } from './logs_stream';
5
- import { DownloadDriver } from './download_and_logs_blob';
6
4
  import * as sdk from '@milaboratories/pl-model-common';
7
- import { ConsoleLoggerAdapter, MiLogger } from '@milaboratories/ts-helpers';
5
+ import { MiLogger } from '@milaboratories/ts-helpers';
6
+ import { DownloadDriver } from './download_blob';
7
+ import { isLiveLogHandle } from './helpers/logs_handle';
8
8
 
9
9
  export class LogsDriver implements sdk.LogsDriver {
10
10
  constructor(
@@ -125,43 +125,3 @@ function isBlob(rInfo: ResourceInfo) {
125
125
  function streamManagerGetStream(ctx: ComputableCtx, manager: PlTreeEntry) {
126
126
  return ctx.accessor(manager).node().traverse('stream')?.resourceInfo;
127
127
  }
128
-
129
- export function handleToData(handle: sdk.AnyLogHandle): ResourceInfo {
130
- let parsed: RegExpMatchArray | null;
131
-
132
- if (isLiveLogHandle(handle)) {
133
- parsed = handle.match(liveHandleRegex);
134
- } else if (isReadyLogHandle(handle)) {
135
- parsed = handle.match(readyHandleRegex);
136
- } else throw new Error(`Log handle is malformed: ${handle}`);
137
- if (parsed == null) throw new Error(`Log handle wasn't parsed: ${handle}`);
138
-
139
- const { resourceType, resourceVersion, resourceId } = parsed.groups!;
140
-
141
- return {
142
- id: bigintToResourceId(BigInt(resourceId)),
143
- type: { name: resourceType, version: resourceVersion }
144
- };
145
- }
146
-
147
- export function dataToHandle(live: boolean, rInfo: ResourceInfo): sdk.AnyLogHandle {
148
- if (live) {
149
- return `log+live://log/${rInfo.type.name}/${rInfo.type.version}/${BigInt(rInfo.id)}` as sdk.LiveLogHandle;
150
- }
151
-
152
- return `log+ready://log/${rInfo.type.name}/${rInfo.type.version}/${BigInt(rInfo.id)}` as sdk.ReadyLogHandle;
153
- }
154
-
155
- const liveHandleRegex =
156
- /^log\+live:\/\/log\/(?<resourceType>.*)\/(?<resourceVersion>.*)\/(?<resourceId>.*)$/;
157
-
158
- export function isLiveLogHandle(handle: string): handle is sdk.LiveLogHandle {
159
- return liveHandleRegex.test(handle);
160
- }
161
-
162
- const readyHandleRegex =
163
- /^log\+ready:\/\/log\/(?<resourceType>.*)\/(?<resourceVersion>.*)\/(?<resourceId>.*)$/;
164
-
165
- export function isReadyLogHandle(handle: string): handle is sdk.ReadyLogHandle {
166
- return readyHandleRegex.test(handle);
167
- }
@@ -5,17 +5,23 @@ import {
5
5
  PollingComputableHooks,
6
6
  Watcher
7
7
  } from '@milaboratories/computable';
8
- import { ResourceId, resourceIdToString, stringifyWithResourceId } from '@milaboratories/pl-client';
8
+ import {
9
+ ResourceId,
10
+ resourceIdToString,
11
+ ResourceType,
12
+ stringifyWithResourceId
13
+ } from '@milaboratories/pl-client';
9
14
  import { asyncPool, CallersCounter, MiLogger } from '@milaboratories/ts-helpers';
10
15
  import { ClientLogs } from '../clients/logs';
11
16
  import { randomUUID } from 'node:crypto';
12
17
  import { PlTreeEntry, ResourceInfo, treeEntryToResourceInfo } from '@milaboratories/pl-tree';
13
- import { dataToHandle, handleToData, isLiveLogHandle } from './logs';
14
18
  import { scheduler } from 'node:timers/promises';
15
19
  import { StreamingAPI_Response } from '../proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol';
16
20
  import * as sdk from '@milaboratories/pl-model-common';
17
21
  import { PollingOps } from './helpers/polling_ops';
18
22
  import { RpcError } from '@protobuf-ts/runtime-rpc';
23
+ import { getResourceInfoFromLogHandle, isLiveLogHandle, newLogHandle } from './helpers/logs_handle';
24
+ import { WrongResourceTypeError } from './helpers/helpers';
19
25
 
20
26
  export type LogsStreamDriverOps = PollingOps & {
21
27
  /** Max number of concurrent requests to log streaming backend while calculating computable states */
@@ -81,6 +87,8 @@ export class LogsStreamDriver implements sdk.LogsDriver {
81
87
  lines: number,
82
88
  callerId: string
83
89
  ): string | undefined {
90
+ validateResourceType('getLastLogs', rInfo.type);
91
+
84
92
  let logGetter = this.idToLastLines.get(rInfo.id);
85
93
 
86
94
  if (logGetter == undefined) {
@@ -135,6 +143,8 @@ export class LogsStreamDriver implements sdk.LogsDriver {
135
143
  patternToSearch: string,
136
144
  callerId: string
137
145
  ): string | undefined {
146
+ validateResourceType('getProgressLog', rInfo.type);
147
+
138
148
  let logGetter = this.idToProgressLog.get(rInfo.id);
139
149
 
140
150
  if (logGetter == undefined) {
@@ -162,7 +172,7 @@ export class LogsStreamDriver implements sdk.LogsDriver {
162
172
  const r = treeEntryToResourceInfo(res, ctx);
163
173
 
164
174
  const result = this.getLogHandleNoCtx(r);
165
-
175
+
166
176
  // All logs from streams should be considered unstable,
167
177
  // final value will be got from blobs.
168
178
  ctx.markUnstable(`live_log:${resourceIdToString(r.id)}`);
@@ -171,7 +181,9 @@ export class LogsStreamDriver implements sdk.LogsDriver {
171
181
  }
172
182
 
173
183
  private getLogHandleNoCtx(rInfo: ResourceInfo): sdk.AnyLogHandle {
174
- return dataToHandle(true, rInfo);
184
+ validateResourceType('getLogHandle', rInfo.type);
185
+
186
+ return newLogHandle(true, rInfo);
175
187
  }
176
188
 
177
189
  async lastLines(
@@ -182,7 +194,7 @@ export class LogsStreamDriver implements sdk.LogsDriver {
182
194
  ) {
183
195
  return await this.tryWithNotFound(handle, () =>
184
196
  this.clientLogs.lastLines(
185
- handleToData(handle),
197
+ getResourceInfoFromLogHandle(handle),
186
198
  lineCount,
187
199
  BigInt(offsetBytes ?? 0),
188
200
  searchStr
@@ -197,7 +209,12 @@ export class LogsStreamDriver implements sdk.LogsDriver {
197
209
  searchStr?: string | undefined
198
210
  ) {
199
211
  return await this.tryWithNotFound(handle, () =>
200
- this.clientLogs.readText(handleToData(handle), lineCount, BigInt(offsetBytes ?? 0), searchStr)
212
+ this.clientLogs.readText(
213
+ getResourceInfoFromLogHandle(handle),
214
+ lineCount,
215
+ BigInt(offsetBytes ?? 0),
216
+ searchStr
217
+ )
201
218
  );
202
219
  }
203
220
 
@@ -365,3 +382,12 @@ type ScheduledRefresh = {
365
382
  resolve: () => void;
366
383
  reject: (err: any) => void;
367
384
  };
385
+
386
+ function validateResourceType(methodName: string, rType: ResourceType) {
387
+ if (!rType.name.startsWith('StreamWorkdir')) {
388
+ throw new WrongResourceTypeError(
389
+ `${methodName}: wrong resource type: ${rType.name}, ` +
390
+ `expected: a resource of type 'StreamWorkdir'.`
391
+ );
392
+ }
393
+ }
@@ -1,12 +1,11 @@
1
1
  import { ConsoleLoggerAdapter, HmacSha256Signer } from '@milaboratories/ts-helpers';
2
2
  import { LsDriver } from './ls';
3
- import { createLsFilesClient } from '../clients/helpers';
3
+ import { createLsFilesClient } from '../clients/constructors';
4
4
  import { TestHelpers } from '@milaboratories/pl-client';
5
5
  import * as os from 'node:os';
6
6
  import * as path from 'node:path';
7
7
  import { test, expect } from '@jest/globals';
8
8
  import { isImportFileHandleIndex, isImportFileHandleUpload } from '@milaboratories/pl-model-common';
9
- import { DefaultVirtualLocalStorages } from './virtual_storages';
10
9
 
11
10
  const assetsPath = path.resolve('../../../assets');
12
11
 
package/src/drivers/ls.ts CHANGED
@@ -18,16 +18,16 @@ import {
18
18
  createUploadImportHandle,
19
19
  parseIndexHandle,
20
20
  parseUploadHandle
21
- } from './helpers/ls_list_entry';
21
+ } from './helpers/ls_remote_import_handle';
22
22
  import {
23
23
  createLocalStorageHandle,
24
24
  createRemoteStorageHandle,
25
25
  parseStorageHandle
26
26
  } from './helpers/ls_storage_entry';
27
27
  import { LocalStorageProjection, VirtualLocalStorageSpec } from './types';
28
- import { createLsFilesClient } from '../clients/helpers';
29
28
  import { validateAbsolute } from '../helpers/validate';
30
29
  import { DefaultVirtualLocalStorages } from './virtual_storages';
30
+ import { createLsFilesClient } from '../clients/constructors';
31
31
 
32
32
  /**
33
33
  * Extends public and safe SDK's driver API with methods used internally in the middle
@@ -199,35 +199,33 @@ export class LsDriver implements InternalLsDriver {
199
199
  handle: createIndexImportHandle(storageData.name, e.fullName)
200
200
  }))
201
201
  };
202
- } else {
203
- if (path.sep === '/' && fullPath === '') fullPath = '/';
202
+ }
204
203
 
205
- if (storageData.rootPath === '') {
206
- validateAbsolute(fullPath);
207
- }
208
- const lsRoot = path.isAbsolute(fullPath)
209
- ? fullPath
210
- : path.join(storageData.rootPath, fullPath);
211
-
212
- const entries: LsEntry[] = [];
213
- for await (const dirent of await fsp.opendir(lsRoot)) {
214
- if (!dirent.isFile() && !dirent.isDirectory()) continue;
215
-
216
- // We cannot use no dirent.fullPath no dirent.parentPath,
217
- // since the former is deprecated
218
- // and the later works differently on different versions.
219
- const absolutePath = path.join(lsRoot, dirent.name);
220
-
221
- entries.push({
222
- type: dirent.isFile() ? 'file' : 'dir',
223
- name: dirent.name,
224
- fullPath: absolutePath,
225
- handle: await this.getLocalFileHandle(absolutePath)
226
- });
227
- }
204
+ if (path.sep === '/' && fullPath === '') fullPath = '/';
228
205
 
229
- return { entries };
206
+ if (storageData.rootPath === '') {
207
+ validateAbsolute(fullPath);
208
+ }
209
+ const lsRoot = path.isAbsolute(fullPath) ? fullPath : path.join(storageData.rootPath, fullPath);
210
+
211
+ const entries: LsEntry[] = [];
212
+ for await (const dirent of await fsp.opendir(lsRoot)) {
213
+ if (!dirent.isFile() && !dirent.isDirectory()) continue;
214
+
215
+ // We cannot use no dirent.fullPath no dirent.parentPath,
216
+ // since the former is deprecated
217
+ // and the later works differently on different versions.
218
+ const absolutePath = path.join(lsRoot, dirent.name);
219
+
220
+ entries.push({
221
+ type: dirent.isFile() ? 'file' : 'dir',
222
+ name: dirent.name,
223
+ fullPath: absolutePath,
224
+ handle: await this.getLocalFileHandle(absolutePath)
225
+ });
230
226
  }
227
+
228
+ return { entries };
231
229
  }
232
230
 
233
231
  public async fileToImportHandle(file: sdk.FileLike): Promise<sdk.ImportFileHandle> {
@@ -1,4 +1,27 @@
1
1
  import { z } from 'zod';
2
+ import { InferSnapshot, rsSchema } from '@milaboratories/pl-tree';
3
+
4
+ //
5
+ // download
6
+ //
7
+ /** ResourceSnapshot that can be passed to OnDemandBlob */
8
+ export const OnDemandBlobResourceSnapshot = rsSchema({
9
+ kv: {
10
+ 'ctl/file/blobInfo': z.object({
11
+ sizeBytes: z.coerce.number()
12
+ })
13
+ }
14
+ });
15
+
16
+ export type OnDemandBlobResourceSnapshot = InferSnapshot<typeof OnDemandBlobResourceSnapshot>;
17
+
18
+ export function getSize(bs: OnDemandBlobResourceSnapshot): number {
19
+ return bs.kv['ctl/file/blobInfo'].sizeBytes;
20
+ }
21
+
22
+ //
23
+ // upload
24
+ //
2
25
 
3
26
  export const ImportFileHandleUploadData = z.object({
4
27
  /** Local file path, to take data for upload */
@@ -26,6 +49,31 @@ export const ImportFileHandleData = z.union([
26
49
  ]);
27
50
  export type ImportFileHandleData = z.infer<typeof ImportFileHandleData>;
28
51
 
52
+ /** Options from BlobUpload resource that have to be passed to getProgress. */
53
+
54
+ /** ResourceSnapshot that can be passed to GetProgressID */
55
+ export const UploadResourceSnapshot = rsSchema({
56
+ data: ImportFileHandleUploadData,
57
+ fields: {
58
+ blob: false
59
+ }
60
+ });
61
+
62
+ export const IndexResourceSnapshot = rsSchema({
63
+ fields: {
64
+ incarnation: false
65
+ }
66
+ });
67
+
68
+ export type UploadResourceSnapshot = InferSnapshot<typeof UploadResourceSnapshot>;
69
+ export type IndexResourceSnapshot = InferSnapshot<typeof IndexResourceSnapshot>;
70
+
71
+ export type ImportResourceSnapshot = UploadResourceSnapshot | IndexResourceSnapshot;
72
+
73
+ //
74
+ // ls
75
+ //
76
+
29
77
  /** Defines which storages from pl are available via local paths */
30
78
  export type LocalStorageProjection = {
31
79
  /** Pl storage id */
@@ -1,21 +1,14 @@
1
- import {
2
- isNotNullResourceId,
3
- PlTransaction,
4
- PollTxAccessor,
5
- ResourceId,
6
- TestHelpers
7
- } from '@milaboratories/pl-client';
1
+ import { PlClient, PlTransaction, ResourceId, TestHelpers } from '@milaboratories/pl-client';
8
2
  import { ConsoleLoggerAdapter, HmacSha256Signer, Signer } from '@milaboratories/ts-helpers';
9
3
  import * as fsp from 'node:fs/promises';
10
4
  import * as os from 'node:os';
11
5
  import * as path from 'node:path';
12
- import { PlClient } from '@milaboratories/pl-client';
13
- import { ImportResourceSnapshot, makeBlobImportSnapshot, UploadDriver } from './upload';
14
- import { createUploadBlobClient, createUploadProgressClient } from '../clients/helpers';
15
-
16
- import { test, expect } from '@jest/globals';
17
- import { SynchronizedTreeState } from '@milaboratories/pl-tree';
6
+ import { makeBlobImportSnapshot, UploadDriver } from './upload';
7
+ import { createUploadBlobClient, createUploadProgressClient } from '../clients/constructors';
8
+ import { expect, test } from '@jest/globals';
18
9
  import { Computable } from '@milaboratories/computable';
10
+ import { SynchronizedTreeState } from '@milaboratories/pl-tree';
11
+ import { ImportResourceSnapshot } from './types';
19
12
 
20
13
  test('upload a blob', async () => {
21
14
  await withTest(async ({ client, uploader, signer }: TestArg) => {
@@ -100,10 +93,7 @@ test.skip('upload a very big blob', async () => {
100
93
  // await fileToWrite.close();
101
94
 
102
95
  // const stats = await getFileStats(signer, fPath)
103
- const stats = await getFileStats(
104
- signer,
105
- '/home/snyssfx/Downloads/Kung Fu Hustle (2004) Open Matte 1080p.mkv'
106
- );
96
+ const stats = await getFileStats(signer, '/home/snyssfx/Downloads/a_very_big_file.txt');
107
97
  const uploadId = await createBlobUpload(client, stats);
108
98
  const handleRes = await getSnapshot(client, uploadId);
109
99
 
@@ -407,7 +397,7 @@ async function getSnapshot(
407
397
  }).withStableType();
408
398
  while (true) {
409
399
  const value = await computable.getValue();
410
- if (value !== undefined) return value;
400
+ if (value !== undefined) return value as ImportResourceSnapshot;
411
401
  await computable.awaitChange();
412
402
  }
413
403
  } finally {