@milaboratories/pl-drivers 1.13.0 → 1.14.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.
- package/dist/clients/download.cjs +5 -3
- package/dist/clients/download.cjs.map +1 -1
- package/dist/clients/download.d.ts.map +1 -1
- package/dist/clients/download.js +6 -4
- package/dist/clients/download.js.map +1 -1
- package/dist/clients/logs.cjs +10 -6
- package/dist/clients/logs.cjs.map +1 -1
- package/dist/clients/logs.d.ts.map +1 -1
- package/dist/clients/logs.js +11 -7
- package/dist/clients/logs.js.map +1 -1
- package/dist/clients/ls_api.cjs +5 -3
- package/dist/clients/ls_api.cjs.map +1 -1
- package/dist/clients/ls_api.js +6 -4
- package/dist/clients/ls_api.js.map +1 -1
- package/dist/clients/progress.cjs +7 -3
- package/dist/clients/progress.cjs.map +1 -1
- package/dist/clients/progress.d.ts.map +1 -1
- package/dist/clients/progress.js +8 -4
- package/dist/clients/progress.js.map +1 -1
- package/dist/clients/upload.cjs +22 -12
- package/dist/clients/upload.cjs.map +1 -1
- package/dist/clients/upload.d.ts.map +1 -1
- package/dist/clients/upload.js +23 -13
- package/dist/clients/upload.js.map +1 -1
- package/dist/drivers/download_blob/blob_key.cjs +3 -2
- package/dist/drivers/download_blob/blob_key.cjs.map +1 -1
- package/dist/drivers/download_blob/blob_key.js +3 -2
- package/dist/drivers/download_blob/blob_key.js.map +1 -1
- package/dist/drivers/download_blob/download_blob.cjs.map +1 -1
- package/dist/drivers/download_blob/download_blob.js.map +1 -1
- package/dist/drivers/download_blob_url/driver.cjs +2 -1
- package/dist/drivers/download_blob_url/driver.cjs.map +1 -1
- package/dist/drivers/download_blob_url/driver.d.ts +2 -2
- package/dist/drivers/download_blob_url/driver.d.ts.map +1 -1
- package/dist/drivers/download_blob_url/driver.js +3 -2
- package/dist/drivers/download_blob_url/driver.js.map +1 -1
- package/dist/drivers/download_blob_url/driver_id.cjs +4 -1
- package/dist/drivers/download_blob_url/driver_id.cjs.map +1 -1
- package/dist/drivers/download_blob_url/driver_id.js +3 -1
- package/dist/drivers/download_blob_url/driver_id.js.map +1 -1
- package/dist/drivers/download_url/task.cjs +1 -1
- package/dist/drivers/download_url/task.cjs.map +1 -1
- package/dist/drivers/download_url/task.d.ts.map +1 -1
- package/dist/drivers/download_url/task.js +1 -1
- package/dist/drivers/download_url/task.js.map +1 -1
- package/dist/drivers/helpers/download_remote_handle.cjs +7 -4
- package/dist/drivers/helpers/download_remote_handle.cjs.map +1 -1
- package/dist/drivers/helpers/download_remote_handle.js +8 -5
- package/dist/drivers/helpers/download_remote_handle.js.map +1 -1
- package/dist/drivers/helpers/logs_handle.cjs +9 -6
- package/dist/drivers/helpers/logs_handle.cjs.map +1 -1
- package/dist/drivers/helpers/logs_handle.js +10 -7
- package/dist/drivers/helpers/logs_handle.js.map +1 -1
- package/dist/drivers/helpers/ls_remote_import_handle.cjs +2 -2
- package/dist/drivers/helpers/ls_remote_import_handle.cjs.map +1 -1
- package/dist/drivers/helpers/ls_remote_import_handle.js +2 -2
- package/dist/drivers/helpers/ls_remote_import_handle.js.map +1 -1
- package/dist/drivers/helpers/ls_storage_entry.cjs +10 -16
- package/dist/drivers/helpers/ls_storage_entry.cjs.map +1 -1
- package/dist/drivers/helpers/ls_storage_entry.js +11 -17
- package/dist/drivers/helpers/ls_storage_entry.js.map +1 -1
- package/dist/drivers/logs_stream.cjs.map +1 -1
- package/dist/drivers/logs_stream.js.map +1 -1
- package/dist/drivers/ls.cjs +31 -29
- package/dist/drivers/ls.cjs.map +1 -1
- package/dist/drivers/ls.d.ts +10 -10
- package/dist/drivers/ls.d.ts.map +1 -1
- package/dist/drivers/ls.js +31 -29
- package/dist/drivers/ls.js.map +1 -1
- package/dist/drivers/types.cjs.map +1 -1
- package/dist/drivers/types.d.ts +2 -1
- package/dist/drivers/types.d.ts.map +1 -1
- package/dist/drivers/types.js.map +1 -1
- package/dist/drivers/upload.cjs.map +1 -1
- package/dist/drivers/upload.js.map +1 -1
- package/dist/drivers/virtual_storages.cjs +3 -0
- package/dist/drivers/virtual_storages.cjs.map +1 -1
- package/dist/drivers/virtual_storages.js +3 -0
- package/dist/drivers/virtual_storages.js.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.cjs +2 -2
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.cjs.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.d.ts +2 -2
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.d.ts.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.js +2 -2
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.js.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.cjs +2 -2
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.cjs.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.d.ts.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.js +2 -2
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.js.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.cjs +4 -4
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.cjs.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.d.ts +4 -4
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.d.ts.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.js +4 -4
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.js.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.cjs +6 -6
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.cjs.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.d.ts +6 -6
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.d.ts.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.js +6 -6
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.js.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.cjs +10 -10
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.cjs.map +1 -1
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.js +10 -10
- package/dist/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.js.map +1 -1
- package/dist/proto-rest/downloadapi.d.ts +6 -6
- package/dist/proto-rest/downloadapi.d.ts.map +1 -1
- package/dist/proto-rest/progressapi.d.ts +19 -19
- package/dist/proto-rest/progressapi.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/clients/download.ts +6 -3
- package/src/clients/logs.ts +22 -7
- package/src/clients/ls_api.ts +6 -4
- package/src/clients/progress.ts +18 -4
- package/src/clients/upload.ts +31 -14
- package/src/drivers/download_blob/blob_key.ts +4 -8
- package/src/drivers/download_blob/download_blob.ts +2 -2
- package/src/drivers/download_blob_url/driver.ts +10 -5
- package/src/drivers/download_blob_url/driver_id.ts +5 -3
- package/src/drivers/download_url/task.ts +5 -1
- package/src/drivers/helpers/download_remote_handle.ts +16 -5
- package/src/drivers/helpers/logs_handle.ts +16 -7
- package/src/drivers/helpers/ls_remote_import_handle.ts +2 -2
- package/src/drivers/helpers/ls_storage_entry.ts +15 -17
- package/src/drivers/logs_stream.ts +5 -5
- package/src/drivers/ls.test.ts +4 -4
- package/src/drivers/ls.ts +44 -58
- package/src/drivers/types.ts +3 -1
- package/src/drivers/upload.ts +3 -3
- package/src/drivers/virtual_storages.ts +3 -0
- package/src/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.ts +7 -6
- package/src/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.ts +7 -6
- package/src/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.ts +14 -12
- package/src/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.ts +21 -18
- package/src/proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/uploadapi/protocol.ts +35 -30
- package/src/proto-grpc/google/protobuf/descriptor.ts +5 -2
- package/src/proto-rest/downloadapi.ts +6 -6
- package/src/proto-rest/lsapi.ts +30 -30
- package/src/proto-rest/progressapi.ts +21 -21
- package/src/proto-rest/uploadapi.ts +41 -41
package/src/clients/logs.ts
CHANGED
|
@@ -3,7 +3,13 @@ import type { MiLogger } from "@milaboratories/ts-helpers";
|
|
|
3
3
|
import { notEmpty } from "@milaboratories/ts-helpers";
|
|
4
4
|
import type { Dispatcher } from "undici";
|
|
5
5
|
import type { WireClientProvider, WireClientProviderFactory } from "@milaboratories/pl-client";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
addRTypeToMetadata,
|
|
8
|
+
createRTypeRoutingHeader,
|
|
9
|
+
RestAPI,
|
|
10
|
+
parseSignedResourceId,
|
|
11
|
+
signatureToBase64Url,
|
|
12
|
+
} from "@milaboratories/pl-client";
|
|
7
13
|
import type { StreamingAPI_Response } from "../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol";
|
|
8
14
|
import { StreamingClient } from "../proto-grpc/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.client";
|
|
9
15
|
import type { StreamingApiPaths, StreamingRestClientType } from "../proto-rest";
|
|
@@ -43,11 +49,18 @@ export class ClientLogs {
|
|
|
43
49
|
searchStr?: string,
|
|
44
50
|
options?: RpcOptions,
|
|
45
51
|
): Promise<StreamingAPI_Response> {
|
|
52
|
+
const { globalId: rIdGlobal, signature: rIdSig } = parseSignedResourceId(rId);
|
|
46
53
|
const client = this.wire.get();
|
|
47
54
|
if (client instanceof StreamingClient) {
|
|
48
55
|
return (
|
|
49
56
|
await client.lastLines(
|
|
50
|
-
{
|
|
57
|
+
{
|
|
58
|
+
resourceId: rIdGlobal,
|
|
59
|
+
resourceSignature: rIdSig,
|
|
60
|
+
lineCount: lineCount,
|
|
61
|
+
offset: offsetBytes,
|
|
62
|
+
search: searchStr,
|
|
63
|
+
},
|
|
51
64
|
addRTypeToMetadata(rType, options),
|
|
52
65
|
)
|
|
53
66
|
).response;
|
|
@@ -56,8 +69,8 @@ export class ClientLogs {
|
|
|
56
69
|
const resp = (
|
|
57
70
|
await client.POST("/v1/last-lines", {
|
|
58
71
|
body: {
|
|
59
|
-
resourceId:
|
|
60
|
-
resourceSignature:
|
|
72
|
+
resourceId: rIdGlobal.toString(),
|
|
73
|
+
resourceSignature: signatureToBase64Url(rIdSig),
|
|
61
74
|
lineCount: lineCount,
|
|
62
75
|
offset: offsetBytes.toString(),
|
|
63
76
|
search: searchStr ?? "",
|
|
@@ -84,13 +97,15 @@ export class ClientLogs {
|
|
|
84
97
|
searchStr?: string,
|
|
85
98
|
options?: RpcOptions,
|
|
86
99
|
): Promise<StreamingAPI_Response> {
|
|
100
|
+
const { globalId: rIdGlobal2, signature: rIdSig2 } = parseSignedResourceId(rId);
|
|
87
101
|
const client = this.wire.get();
|
|
88
102
|
|
|
89
103
|
if (client instanceof StreamingClient) {
|
|
90
104
|
return (
|
|
91
105
|
await client.readText(
|
|
92
106
|
{
|
|
93
|
-
resourceId: notEmpty(
|
|
107
|
+
resourceId: notEmpty(rIdGlobal2),
|
|
108
|
+
resourceSignature: rIdSig2,
|
|
94
109
|
readLimit: BigInt(lineCount),
|
|
95
110
|
offset: offsetBytes,
|
|
96
111
|
search: searchStr,
|
|
@@ -103,8 +118,8 @@ export class ClientLogs {
|
|
|
103
118
|
const resp = (
|
|
104
119
|
await client.POST("/v1/read/text", {
|
|
105
120
|
body: {
|
|
106
|
-
resourceId:
|
|
107
|
-
resourceSignature:
|
|
121
|
+
resourceId: rIdGlobal2.toString(),
|
|
122
|
+
resourceSignature: signatureToBase64Url(rIdSig2),
|
|
108
123
|
readLimit: lineCount.toString(),
|
|
109
124
|
offset: offsetBytes.toString(),
|
|
110
125
|
search: searchStr ?? "",
|
package/src/clients/ls_api.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { MiLogger } from "@milaboratories/ts-helpers";
|
|
2
2
|
import type { RpcOptions } from "@protobuf-ts/runtime-rpc";
|
|
3
3
|
import type { WireClientProvider, WireClientProviderFactory } from "@milaboratories/pl-client";
|
|
4
|
-
import { RestAPI } from "@milaboratories/pl-client";
|
|
4
|
+
import { RestAPI, parseSignedResourceId, signatureToBase64Url } from "@milaboratories/pl-client";
|
|
5
5
|
import { addRTypeToMetadata, createRTypeRoutingHeader } from "@milaboratories/pl-client";
|
|
6
6
|
import type {
|
|
7
7
|
LsAPI_List_Response,
|
|
@@ -42,10 +42,12 @@ export class ClientLs {
|
|
|
42
42
|
): Promise<LsAPI_List_Response> {
|
|
43
43
|
const client = this.wire.get();
|
|
44
44
|
|
|
45
|
+
const { globalId, signature } = parseSignedResourceId(rInfo.id);
|
|
45
46
|
if (client instanceof LSClient) {
|
|
46
47
|
return await client.list(
|
|
47
48
|
{
|
|
48
|
-
resourceId:
|
|
49
|
+
resourceId: globalId,
|
|
50
|
+
resourceSignature: signature,
|
|
49
51
|
location: path,
|
|
50
52
|
},
|
|
51
53
|
addRTypeToMetadata(rInfo.type, options),
|
|
@@ -54,8 +56,8 @@ export class ClientLs {
|
|
|
54
56
|
const resp = (
|
|
55
57
|
await client.POST("/v1/list", {
|
|
56
58
|
body: {
|
|
57
|
-
resourceId:
|
|
58
|
-
resourceSignature:
|
|
59
|
+
resourceId: globalId.toString(),
|
|
60
|
+
resourceSignature: signatureToBase64Url(signature),
|
|
59
61
|
location: path,
|
|
60
62
|
},
|
|
61
63
|
headers: { ...createRTypeRoutingHeader(rInfo.type) },
|
package/src/clients/progress.ts
CHANGED
|
@@ -4,7 +4,13 @@ import type {
|
|
|
4
4
|
WireClientProviderFactory,
|
|
5
5
|
PlClient,
|
|
6
6
|
} from "@milaboratories/pl-client";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
addRTypeToMetadata,
|
|
9
|
+
createRTypeRoutingHeader,
|
|
10
|
+
RestAPI,
|
|
11
|
+
parseSignedResourceId,
|
|
12
|
+
signatureToBase64Url,
|
|
13
|
+
} from "@milaboratories/pl-client";
|
|
8
14
|
import type { MiLogger } from "@milaboratories/ts-helpers";
|
|
9
15
|
import { notEmpty } from "@milaboratories/ts-helpers";
|
|
10
16
|
import type { Dispatcher } from "undici";
|
|
@@ -53,16 +59,24 @@ export class ClientProgress {
|
|
|
53
59
|
async getStatus({ id, type }: ResourceInfo, options?: RpcOptions): Promise<ProgressStatus> {
|
|
54
60
|
const client = this.wire.get();
|
|
55
61
|
|
|
62
|
+
const { globalId, signature } = parseSignedResourceId(id);
|
|
56
63
|
let report: ProgressAPI_Report;
|
|
57
64
|
if (client instanceof ProgressClient) {
|
|
58
65
|
report = notEmpty(
|
|
59
|
-
(
|
|
60
|
-
.
|
|
66
|
+
(
|
|
67
|
+
await client.getStatus(
|
|
68
|
+
{ resourceId: globalId, resourceSignature: signature },
|
|
69
|
+
addRTypeToMetadata(type, options),
|
|
70
|
+
).response
|
|
71
|
+
).report,
|
|
61
72
|
);
|
|
62
73
|
} else {
|
|
63
74
|
const resp = (
|
|
64
75
|
await client.POST("/v1/get-progress", {
|
|
65
|
-
body: {
|
|
76
|
+
body: {
|
|
77
|
+
resourceId: globalId.toString(),
|
|
78
|
+
resourceSignature: signatureToBase64Url(signature),
|
|
79
|
+
},
|
|
66
80
|
headers: { ...createRTypeRoutingHeader(type) },
|
|
67
81
|
})
|
|
68
82
|
).data!.report;
|
package/src/clients/upload.ts
CHANGED
|
@@ -3,7 +3,13 @@ import type {
|
|
|
3
3
|
WireClientProviderFactory,
|
|
4
4
|
PlClient,
|
|
5
5
|
} from "@milaboratories/pl-client";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
addRTypeToMetadata,
|
|
8
|
+
createRTypeRoutingHeader,
|
|
9
|
+
RestAPI,
|
|
10
|
+
parseSignedResourceId,
|
|
11
|
+
signatureToBase64Url,
|
|
12
|
+
} from "@milaboratories/pl-client";
|
|
7
13
|
import type { ResourceInfo } from "@milaboratories/pl-tree";
|
|
8
14
|
import type { MiLogger } from "@milaboratories/ts-helpers";
|
|
9
15
|
import type { RpcOptions } from "@protobuf-ts/runtime-rpc";
|
|
@@ -78,11 +84,16 @@ export class ClientUpload {
|
|
|
78
84
|
checksumAlgorithm: UploadAPI_ChecksumAlgorithm;
|
|
79
85
|
checksumHeader: string;
|
|
80
86
|
}> {
|
|
87
|
+
const { globalId, signature } = parseSignedResourceId(id);
|
|
81
88
|
const client = this.wire.get();
|
|
82
89
|
|
|
83
90
|
if (client instanceof UploadClient) {
|
|
84
|
-
const init = (
|
|
85
|
-
.
|
|
91
|
+
const init = (
|
|
92
|
+
await client.init(
|
|
93
|
+
{ resourceId: globalId, resourceSignature: signature },
|
|
94
|
+
addRTypeToMetadata(type, options),
|
|
95
|
+
)
|
|
96
|
+
).response;
|
|
86
97
|
|
|
87
98
|
return {
|
|
88
99
|
overall: init.partsCount,
|
|
@@ -95,8 +106,8 @@ export class ClientUpload {
|
|
|
95
106
|
const init = (
|
|
96
107
|
await client.POST("/v1/upload/init", {
|
|
97
108
|
body: {
|
|
98
|
-
resourceId:
|
|
99
|
-
resourceSignature:
|
|
109
|
+
resourceId: globalId.toString(),
|
|
110
|
+
resourceSignature: signatureToBase64Url(signature),
|
|
100
111
|
},
|
|
101
112
|
headers: { ...createRTypeRoutingHeader(type) },
|
|
102
113
|
})
|
|
@@ -119,6 +130,7 @@ export class ClientUpload {
|
|
|
119
130
|
checksumHeader: string,
|
|
120
131
|
options?: RpcOptions,
|
|
121
132
|
) {
|
|
133
|
+
const { globalId, signature } = parseSignedResourceId(id);
|
|
122
134
|
const client = this.wire.get();
|
|
123
135
|
|
|
124
136
|
let info: UploadAPI_GetPartURL_Response;
|
|
@@ -127,7 +139,8 @@ export class ClientUpload {
|
|
|
127
139
|
info = (
|
|
128
140
|
await client.getPartURL(
|
|
129
141
|
{
|
|
130
|
-
resourceId:
|
|
142
|
+
resourceId: globalId,
|
|
143
|
+
resourceSignature: signature,
|
|
131
144
|
partNumber,
|
|
132
145
|
uploadedPartSize: 0n,
|
|
133
146
|
isInternalUse: false,
|
|
@@ -140,8 +153,8 @@ export class ClientUpload {
|
|
|
140
153
|
const resp = (
|
|
141
154
|
await client.POST("/v1/upload/get-part-url", {
|
|
142
155
|
body: {
|
|
143
|
-
resourceId:
|
|
144
|
-
resourceSignature:
|
|
156
|
+
resourceId: globalId.toString(),
|
|
157
|
+
resourceSignature: signatureToBase64Url(signature),
|
|
145
158
|
partNumber: partNumber.toString(),
|
|
146
159
|
uploadedPartSize: "0",
|
|
147
160
|
isInternalUse: false,
|
|
@@ -216,12 +229,14 @@ export class ClientUpload {
|
|
|
216
229
|
}
|
|
217
230
|
|
|
218
231
|
public async finalize(info: ResourceInfo, options?: RpcOptions) {
|
|
232
|
+
const { globalId, signature } = parseSignedResourceId(info.id);
|
|
219
233
|
const client = this.wire.get();
|
|
220
234
|
|
|
221
235
|
if (client instanceof UploadClient) {
|
|
222
236
|
await client.finalize(
|
|
223
237
|
{
|
|
224
|
-
resourceId:
|
|
238
|
+
resourceId: globalId,
|
|
239
|
+
resourceSignature: signature,
|
|
225
240
|
checksumAlgorithm: UploadAPI_ChecksumAlgorithm.UNSPECIFIED,
|
|
226
241
|
checksum: new Uint8Array(0),
|
|
227
242
|
},
|
|
@@ -230,8 +245,8 @@ export class ClientUpload {
|
|
|
230
245
|
} else {
|
|
231
246
|
await client.POST("/v1/upload/finalize", {
|
|
232
247
|
body: {
|
|
233
|
-
resourceId:
|
|
234
|
-
resourceSignature:
|
|
248
|
+
resourceId: globalId.toString(),
|
|
249
|
+
resourceSignature: signatureToBase64Url(signature),
|
|
235
250
|
checksumAlgorithm: 0,
|
|
236
251
|
checksum: "",
|
|
237
252
|
},
|
|
@@ -258,12 +273,14 @@ export class ClientUpload {
|
|
|
258
273
|
bytesProcessed: bigint,
|
|
259
274
|
options?: RpcOptions,
|
|
260
275
|
): Promise<void> {
|
|
276
|
+
const { globalId, signature } = parseSignedResourceId(id);
|
|
261
277
|
const client = this.wire.get();
|
|
262
278
|
|
|
263
279
|
if (client instanceof UploadClient) {
|
|
264
280
|
await client.updateProgress(
|
|
265
281
|
{
|
|
266
|
-
resourceId:
|
|
282
|
+
resourceId: globalId,
|
|
283
|
+
resourceSignature: signature,
|
|
267
284
|
bytesProcessed,
|
|
268
285
|
},
|
|
269
286
|
addRTypeToMetadata(type, options),
|
|
@@ -273,8 +290,8 @@ export class ClientUpload {
|
|
|
273
290
|
|
|
274
291
|
await client.POST("/v1/upload/update-progress", {
|
|
275
292
|
body: {
|
|
276
|
-
resourceId:
|
|
277
|
-
resourceSignature:
|
|
293
|
+
resourceId: globalId.toString(),
|
|
294
|
+
resourceSignature: signatureToBase64Url(signature),
|
|
278
295
|
bytesProcessed: bytesProcessed.toString(),
|
|
279
296
|
},
|
|
280
297
|
headers: { ...createRTypeRoutingHeader(type) },
|
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { parseSignedResourceId, SignedResourceId } from "@milaboratories/pl-client";
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
|
|
4
|
-
export function blobKey(rId:
|
|
5
|
-
|
|
4
|
+
export function blobKey(rId: SignedResourceId): string {
|
|
5
|
+
const { globalId } = parseSignedResourceId(rId);
|
|
6
|
+
return `${globalId}`;
|
|
6
7
|
}
|
|
7
8
|
|
|
8
9
|
export function pathToKey(fPath: string): string {
|
|
9
10
|
return path.basename(fPath);
|
|
10
11
|
}
|
|
11
|
-
|
|
12
|
-
export function pathToBlobInfo(fPath: string): ResourceId | undefined {
|
|
13
|
-
const base = path.basename(fPath);
|
|
14
|
-
return bigintToResourceId(BigInt(base));
|
|
15
|
-
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ComputableCtx, ComputableStableDefined, Watcher } from "@milaboratories/computable";
|
|
2
2
|
import { ChangeSource, Computable } from "@milaboratories/computable";
|
|
3
|
-
import type {
|
|
3
|
+
import type { SignedResourceId, ResourceType } from "@milaboratories/pl-client";
|
|
4
4
|
import {
|
|
5
5
|
isNotFoundError,
|
|
6
6
|
resourceIdToString,
|
|
@@ -630,7 +630,7 @@ export class DownloadDriver implements BlobDriver, AsyncDisposable {
|
|
|
630
630
|
this.idToProgressLog.delete(blobKey(task.rInfo.id));
|
|
631
631
|
}
|
|
632
632
|
|
|
633
|
-
private async releaseOnDemandBlob(blobId:
|
|
633
|
+
private async releaseOnDemandBlob(blobId: SignedResourceId, callerId: string) {
|
|
634
634
|
const deleted = this.keyToOnDemand.get(blobKey(blobId))?.release(callerId) ?? false;
|
|
635
635
|
if (deleted) this.keyToOnDemand.delete(blobKey(blobId));
|
|
636
636
|
}
|
|
@@ -5,8 +5,12 @@ import { TaskProcessor } from "@milaboratories/ts-helpers";
|
|
|
5
5
|
import { randomUUID } from "node:crypto";
|
|
6
6
|
import * as path from "node:path";
|
|
7
7
|
import { FilesCache } from "../helpers/files_cache";
|
|
8
|
-
import type {
|
|
9
|
-
import {
|
|
8
|
+
import type { SignedResourceId } from "@milaboratories/pl-client";
|
|
9
|
+
import {
|
|
10
|
+
resourceIdToString,
|
|
11
|
+
stringifyWithResourceId,
|
|
12
|
+
parseSignedResourceId,
|
|
13
|
+
} from "@milaboratories/pl-client";
|
|
10
14
|
import {
|
|
11
15
|
type ArchiveFormat,
|
|
12
16
|
type BlobToURLDriver,
|
|
@@ -150,7 +154,7 @@ export class DownloadBlobToURLDriver implements BlobToURLDriver {
|
|
|
150
154
|
|
|
151
155
|
/** Removes a directory and aborts a downloading task when all callers
|
|
152
156
|
* are not interested in it. */
|
|
153
|
-
async releasePath(id:
|
|
157
|
+
async releasePath(id: SignedResourceId, format: ArchiveFormat, callerId: string): Promise<void> {
|
|
154
158
|
const task = this.idToDownload.get(newId(id, format));
|
|
155
159
|
if (task == undefined) return;
|
|
156
160
|
|
|
@@ -224,7 +228,8 @@ export class DownloadBlobToURLDriver implements BlobToURLDriver {
|
|
|
224
228
|
this.idToDownload.delete(newId(task.rInfo.id, task.format));
|
|
225
229
|
}
|
|
226
230
|
|
|
227
|
-
private getFilePath(id:
|
|
228
|
-
|
|
231
|
+
private getFilePath(id: SignedResourceId, format: ArchiveFormat): string {
|
|
232
|
+
const { globalId } = parseSignedResourceId(id);
|
|
233
|
+
return path.join(this.saveDir, `${String(globalId)}_${format}`);
|
|
229
234
|
}
|
|
230
235
|
}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SignedResourceId } from "@milaboratories/pl-client";
|
|
2
|
+
import { parseSignedResourceId } from "@milaboratories/pl-client";
|
|
2
3
|
import type { ArchiveFormat } from "@milaboratories/pl-model-common";
|
|
3
4
|
|
|
4
5
|
/** A key in the driver task queue. */
|
|
5
6
|
export type Id = string;
|
|
6
7
|
|
|
7
|
-
export function newId(id:
|
|
8
|
-
|
|
8
|
+
export function newId(id: SignedResourceId, format: ArchiveFormat): Id {
|
|
9
|
+
const { globalId } = parseSignedResourceId(id);
|
|
10
|
+
return `id:${String(globalId)}-${format}`;
|
|
9
11
|
}
|
|
10
12
|
|
|
11
13
|
// export function
|
|
@@ -56,7 +56,11 @@ export class DownloadByUrlTask {
|
|
|
56
56
|
this.setDone(size);
|
|
57
57
|
this.change.markChanged(`download of ${this.url} finished`);
|
|
58
58
|
} catch (e: unknown) {
|
|
59
|
-
if (
|
|
59
|
+
if (
|
|
60
|
+
e instanceof URLAborted ||
|
|
61
|
+
isDownloadNetworkError400(e) ||
|
|
62
|
+
this.signalCtl.signal.aborted
|
|
63
|
+
) {
|
|
60
64
|
this.setError(e);
|
|
61
65
|
this.change.markChanged(`download of ${this.url} failed`);
|
|
62
66
|
// Just in case we were half-way extracting an archive.
|
|
@@ -4,19 +4,27 @@
|
|
|
4
4
|
import type { Signer } from "@milaboratories/ts-helpers";
|
|
5
5
|
import type { OnDemandBlobResourceSnapshot } from "../types";
|
|
6
6
|
import type { RemoteBlobHandle } from "@milaboratories/pl-model-common";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
createSignedResourceId,
|
|
9
|
+
parseSignedResourceId,
|
|
10
|
+
signatureToBase64Url,
|
|
11
|
+
base64UrlToSignature,
|
|
12
|
+
} from "@milaboratories/pl-client";
|
|
8
13
|
import { ResourceInfo } from "@milaboratories/pl-tree";
|
|
9
14
|
import { getSize } from "../types";
|
|
10
15
|
|
|
11
16
|
// https://regex101.com/r/Q4YdTa/5
|
|
17
|
+
// resourceSig segment is base64url-encoded signature (may be empty)
|
|
12
18
|
const remoteHandleRegex =
|
|
13
|
-
/^blob\+remote:\/\/download\/(?<content>(?<resourceType>.+)\/(?<resourceVersion>.+?)\/(?<resourceId>\d+?)\/(?<size>\d+?))#(?<signature>.*)$/;
|
|
19
|
+
/^blob\+remote:\/\/download\/(?<content>(?<resourceType>.+)\/(?<resourceVersion>.+?)\/(?<resourceId>\d+?)\/(?<resourceSig>[A-Za-z0-9_-]*)\/(?<size>\d+?))#(?<signature>.*)$/;
|
|
14
20
|
|
|
15
21
|
export function newRemoteHandle(
|
|
16
22
|
rInfo: OnDemandBlobResourceSnapshot,
|
|
17
23
|
signer: Signer,
|
|
18
24
|
): RemoteBlobHandle {
|
|
19
|
-
|
|
25
|
+
const { globalId, signature: resourceSig } = parseSignedResourceId(rInfo.id);
|
|
26
|
+
const sigSegment = signatureToBase64Url(resourceSig);
|
|
27
|
+
let content = `${rInfo.type.name}/${rInfo.type.version}/${globalId}/${sigSegment}/${getSize(rInfo)}`;
|
|
20
28
|
|
|
21
29
|
return `blob+remote://download/${content}#${signer.sign(content)}` as RemoteBlobHandle;
|
|
22
30
|
}
|
|
@@ -37,13 +45,16 @@ export function parseRemoteHandle(
|
|
|
37
45
|
throw new Error(`Remote handle is malformed: ${handle}, matches: ${parsed}`);
|
|
38
46
|
}
|
|
39
47
|
|
|
40
|
-
const { content, resourceType, resourceVersion, resourceId, size, signature } =
|
|
48
|
+
const { content, resourceType, resourceVersion, resourceId, resourceSig, size, signature } =
|
|
49
|
+
parsed.groups!;
|
|
41
50
|
|
|
42
51
|
signer.verify(content, signature, `Signature verification failed for ${handle}`);
|
|
43
52
|
|
|
53
|
+
const sig = resourceSig ? base64UrlToSignature(resourceSig) : undefined;
|
|
54
|
+
|
|
44
55
|
return {
|
|
45
56
|
info: {
|
|
46
|
-
id:
|
|
57
|
+
id: createSignedResourceId(BigInt(resourceId), sig),
|
|
47
58
|
type: { name: resourceType, version: resourceVersion },
|
|
48
59
|
},
|
|
49
60
|
size: Number(size),
|
|
@@ -3,14 +3,21 @@
|
|
|
3
3
|
|
|
4
4
|
import type { ResourceInfo } from "@milaboratories/pl-tree";
|
|
5
5
|
import type * as sdk from "@milaboratories/pl-model-common";
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
createSignedResourceId,
|
|
8
|
+
parseSignedResourceId,
|
|
9
|
+
signatureToBase64Url,
|
|
10
|
+
base64UrlToSignature,
|
|
11
|
+
} from "@milaboratories/pl-client";
|
|
7
12
|
|
|
8
13
|
export function newLogHandle(live: boolean, rInfo: ResourceInfo): sdk.AnyLogHandle {
|
|
14
|
+
const { globalId, signature } = parseSignedResourceId(rInfo.id);
|
|
15
|
+
const sigSegment = signatureToBase64Url(signature);
|
|
9
16
|
if (live) {
|
|
10
|
-
return `log+live://log/${rInfo.type.name}/${rInfo.type.version}/${
|
|
17
|
+
return `log+live://log/${rInfo.type.name}/${rInfo.type.version}/${globalId}/${sigSegment}` as sdk.LiveLogHandle;
|
|
11
18
|
}
|
|
12
19
|
|
|
13
|
-
return `log+ready://log/${rInfo.type.name}/${rInfo.type.version}/${
|
|
20
|
+
return `log+ready://log/${rInfo.type.name}/${rInfo.type.version}/${globalId}/${sigSegment}` as sdk.ReadyLogHandle;
|
|
14
21
|
}
|
|
15
22
|
|
|
16
23
|
/** Handle of the live logs of a program.
|
|
@@ -18,7 +25,7 @@ export function newLogHandle(live: boolean, rInfo: ResourceInfo): sdk.AnyLogHand
|
|
|
18
25
|
* in this case the handle should be refreshed. */
|
|
19
26
|
|
|
20
27
|
export const liveHandleRegex =
|
|
21
|
-
/^log\+live:\/\/log\/(?<resourceType
|
|
28
|
+
/^log\+live:\/\/log\/(?<resourceType>.+)\/(?<resourceVersion>[^/]+)\/(?<resourceId>\d+)\/(?<resourceSig>[A-Za-z0-9_\-=]*)$/;
|
|
22
29
|
|
|
23
30
|
export function isLiveLogHandle(handle: string): handle is sdk.LiveLogHandle {
|
|
24
31
|
return liveHandleRegex.test(handle);
|
|
@@ -27,7 +34,7 @@ export function isLiveLogHandle(handle: string): handle is sdk.LiveLogHandle {
|
|
|
27
34
|
/** Handle of the ready logs of a program. */
|
|
28
35
|
|
|
29
36
|
export const readyHandleRegex =
|
|
30
|
-
/^log\+ready:\/\/log\/(?<resourceType
|
|
37
|
+
/^log\+ready:\/\/log\/(?<resourceType>.+)\/(?<resourceVersion>.+)\/(?<resourceId>\d+)\/(?<resourceSig>[A-Za-z0-9_\-=]*)$/;
|
|
31
38
|
|
|
32
39
|
export function isReadyLogHandle(handle: string): handle is sdk.ReadyLogHandle {
|
|
33
40
|
return readyHandleRegex.test(handle);
|
|
@@ -43,10 +50,12 @@ export function getResourceInfoFromLogHandle(handle: sdk.AnyLogHandle): Resource
|
|
|
43
50
|
} else throw new Error(`Log handle is malformed: ${handle}`);
|
|
44
51
|
if (parsed == null) throw new Error(`Log handle wasn't parsed: ${handle}`);
|
|
45
52
|
|
|
46
|
-
const { resourceType, resourceVersion, resourceId } = parsed.groups!;
|
|
53
|
+
const { resourceType, resourceVersion, resourceId, resourceSig } = parsed.groups!;
|
|
54
|
+
|
|
55
|
+
const sig = resourceSig ? base64UrlToSignature(resourceSig) : undefined;
|
|
47
56
|
|
|
48
57
|
return {
|
|
49
|
-
id:
|
|
58
|
+
id: createSignedResourceId(BigInt(resourceId), sig),
|
|
50
59
|
type: { name: resourceType, version: resourceVersion },
|
|
51
60
|
};
|
|
52
61
|
}
|
|
@@ -3,11 +3,11 @@ import type { Signer } from "@milaboratories/ts-helpers";
|
|
|
3
3
|
import { ImportFileHandleIndexData, ImportFileHandleUploadData } from "../types";
|
|
4
4
|
|
|
5
5
|
export function createIndexImportHandle(
|
|
6
|
-
|
|
6
|
+
storageId: string,
|
|
7
7
|
path: string,
|
|
8
8
|
): sdk.ImportFileHandleIndex {
|
|
9
9
|
const data: ImportFileHandleIndexData = {
|
|
10
|
-
storageId:
|
|
10
|
+
storageId: storageId,
|
|
11
11
|
path: path,
|
|
12
12
|
};
|
|
13
13
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type * as sdk from "@milaboratories/pl-model-common";
|
|
2
|
-
import type {
|
|
3
|
-
import {
|
|
2
|
+
import type { ResourceType, SignedResourceId, StorageInfo } from "@milaboratories/pl-client";
|
|
3
|
+
import { resourceTypeToString, parseResourceType } from "@milaboratories/pl-client";
|
|
4
4
|
import { assertNever } from "@milaboratories/ts-helpers";
|
|
5
5
|
|
|
6
6
|
export type StorageHandleData = RemoteStorageHandleData | LocalStorageHandleData;
|
|
@@ -45,9 +45,9 @@ function parseLocalStorageHandle(handle: string): LocalStorageHandleData {
|
|
|
45
45
|
const { name, path } = parsed.groups!;
|
|
46
46
|
|
|
47
47
|
return {
|
|
48
|
+
isRemote: false,
|
|
48
49
|
rootPath: decodeURIComponent(path),
|
|
49
50
|
name,
|
|
50
|
-
isRemote: false,
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
53
|
|
|
@@ -57,12 +57,12 @@ function parseLocalStorageHandle(handle: string): LocalStorageHandleData {
|
|
|
57
57
|
|
|
58
58
|
export type RemoteStorageHandleData = {
|
|
59
59
|
isRemote: true;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
60
|
+
storageId: string;
|
|
61
|
+
resourceType: ResourceType;
|
|
62
|
+
resourceId: SignedResourceId;
|
|
63
63
|
};
|
|
64
64
|
|
|
65
|
-
const remoteHandleRegex = /^remote:\/\/(?<
|
|
65
|
+
const remoteHandleRegex = /^remote:\/\/(?<storageId>.*)\/(?<resourceType>.*)\/(?<resourceId>.*)$/;
|
|
66
66
|
|
|
67
67
|
export function isRemoteStorageHandle(
|
|
68
68
|
handle: sdk.StorageHandle,
|
|
@@ -70,23 +70,21 @@ export function isRemoteStorageHandle(
|
|
|
70
70
|
return remoteHandleRegex.test(handle);
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
export function createRemoteStorageHandle(
|
|
74
|
-
return `remote://${
|
|
73
|
+
export function createRemoteStorageHandle(info: StorageInfo): sdk.StorageHandleRemote {
|
|
74
|
+
return `remote://${info.storageId}/${encodeURIComponent(resourceTypeToString(info.resourceType))}/${encodeURIComponent(info.resourceId)}`;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
function parseRemoteStorageHandle(handle: string): RemoteStorageHandleData {
|
|
78
78
|
const parsed = handle.match(remoteHandleRegex);
|
|
79
79
|
if (parsed == null) throw new Error(`Remote list handle wasn't parsed: ${handle}`);
|
|
80
|
-
const {
|
|
80
|
+
const { storageId, resourceType: encodedRType, resourceId: encodedRId } = parsed.groups!;
|
|
81
81
|
|
|
82
|
+
const resourceType = parseResourceType(decodeURIComponent(encodedRType));
|
|
83
|
+
const resourceId = decodeURIComponent(encodedRId) as SignedResourceId; // lint-allow-cast
|
|
82
84
|
return {
|
|
83
|
-
id: bigintToResourceId(BigInt(resourceId)),
|
|
84
|
-
type: storageType(name),
|
|
85
|
-
name,
|
|
86
85
|
isRemote: true,
|
|
86
|
+
storageId,
|
|
87
|
+
resourceType: resourceType,
|
|
88
|
+
resourceId: resourceId,
|
|
87
89
|
};
|
|
88
90
|
}
|
|
89
|
-
|
|
90
|
-
function storageType(name: string): ResourceType {
|
|
91
|
-
return { name: `LS/${name}`, version: "1" };
|
|
92
|
-
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { ComputableCtx, Watcher } from "@milaboratories/computable";
|
|
2
2
|
import { ChangeSource, Computable, PollingComputableHooks } from "@milaboratories/computable";
|
|
3
|
-
import type {
|
|
3
|
+
import type { SignedResourceId, ResourceType } from "@milaboratories/pl-client";
|
|
4
4
|
import {
|
|
5
5
|
isNotFoundError,
|
|
6
6
|
resourceIdToString,
|
|
@@ -26,10 +26,10 @@ export type LogsStreamDriverOps = PollingOps & {
|
|
|
26
26
|
|
|
27
27
|
export class LogsStreamDriver implements sdk.LogsDriver {
|
|
28
28
|
/** Holds a map of StreamManager Resource Id to all logs of this stream. */
|
|
29
|
-
private readonly idToLastLines: Map<
|
|
29
|
+
private readonly idToLastLines: Map<SignedResourceId, LogGetter> = new Map();
|
|
30
30
|
|
|
31
31
|
/** Holds a map of StreamManager Resource Id to the last log line of this stream. */
|
|
32
|
-
private readonly idToProgressLog: Map<
|
|
32
|
+
private readonly idToProgressLog: Map<SignedResourceId, LogGetter> = new Map();
|
|
33
33
|
|
|
34
34
|
/** Holds a map of StreamManager Resource Id to log id smart object. */
|
|
35
35
|
private readonly hooks: PollingComputableHooks;
|
|
@@ -239,12 +239,12 @@ export class LogsStreamDriver implements sdk.LogsDriver {
|
|
|
239
239
|
}
|
|
240
240
|
}
|
|
241
241
|
|
|
242
|
-
private async releaseLastLogs(rId:
|
|
242
|
+
private async releaseLastLogs(rId: SignedResourceId, callerId: string) {
|
|
243
243
|
const deleted = this.idToLastLines.get(rId)?.release(callerId);
|
|
244
244
|
if (deleted) this.idToLastLines.delete(rId);
|
|
245
245
|
}
|
|
246
246
|
|
|
247
|
-
private async releaseProgressLog(rId:
|
|
247
|
+
private async releaseProgressLog(rId: SignedResourceId, callerId: string) {
|
|
248
248
|
const deleted = this.idToProgressLog.get(rId)?.release(callerId);
|
|
249
249
|
if (deleted) this.idToProgressLog.delete(rId);
|
|
250
250
|
}
|
package/src/drivers/ls.test.ts
CHANGED
|
@@ -19,8 +19,8 @@ test("should ok when get all storages from ls driver", async () => {
|
|
|
19
19
|
const got = await driver.getStorageList();
|
|
20
20
|
|
|
21
21
|
expect(got.length).toBeGreaterThanOrEqual(1);
|
|
22
|
-
expect(got.find((se) => se.
|
|
23
|
-
expect(got.find((se) => se.
|
|
22
|
+
expect(got.find((se) => se.id == env.libraryStorage)?.handle).toContain(env.libraryStorage);
|
|
23
|
+
expect(got.find((se) => se.id == env.libraryStorage)?.initialFullPath).toEqual("");
|
|
24
24
|
// expect(got.find((se) => se.name == 'local')?.handle).toContain('/');
|
|
25
25
|
// expect(got.find((se) => se.name == 'local')?.initialFullPath).toEqual(os.homedir());
|
|
26
26
|
|
|
@@ -39,7 +39,7 @@ test("should ok when list files from remote storage in ls driver", async () => {
|
|
|
39
39
|
const universalPath = (path: string) => (path.startsWith("/") ? path.slice(1) : path);
|
|
40
40
|
|
|
41
41
|
const storages = await driver.getStorageList();
|
|
42
|
-
const library = storages.find((se) => se.
|
|
42
|
+
const library = storages.find((se) => se.id == env.libraryStorage)!.handle;
|
|
43
43
|
|
|
44
44
|
const topLevelDir = await driver.listFiles(library, "");
|
|
45
45
|
expect(topLevelDir.entries.length).toBeGreaterThan(1);
|
|
@@ -75,7 +75,7 @@ test("should ok when list files from local storage in ls driver", async () => {
|
|
|
75
75
|
});
|
|
76
76
|
|
|
77
77
|
const storages = await driver.getStorageList();
|
|
78
|
-
const local = storages.find((se) => se.
|
|
78
|
+
const local = storages.find((se) => se.id == "local")!;
|
|
79
79
|
|
|
80
80
|
const defaultDir = await driver.listFiles(local.handle, local.initialFullPath);
|
|
81
81
|
expect(defaultDir.entries.length).toBeGreaterThan(1);
|