@milaboratories/pl-drivers 1.3.0 → 1.3.1
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.d.ts +1 -0
- package/dist/clients/download.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +495 -492
- package/dist/index.mjs.map +1 -1
- package/package.json +4 -4
- package/src/clients/download.test.ts +12 -1
- package/src/clients/download.ts +24 -19
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@milaboratories/pl-drivers",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Drivers and a low-level clients for log streaming, downloading and uploading files from and to pl",
|
|
5
5
|
"types": "./dist/index.d.ts",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -27,10 +27,10 @@
|
|
|
27
27
|
"undici": "^6.19.8",
|
|
28
28
|
"zod": "^3.23.8",
|
|
29
29
|
"@milaboratories/ts-helpers": "^1.1.0",
|
|
30
|
-
"@milaboratories/pl-client": "^2.5.3",
|
|
31
|
-
"@milaboratories/pl-model-common": "^1.4.0",
|
|
32
30
|
"@milaboratories/computable": "^2.2.0",
|
|
33
|
-
"@milaboratories/pl-tree": "^1.4.4"
|
|
31
|
+
"@milaboratories/pl-tree": "^1.4.4",
|
|
32
|
+
"@milaboratories/pl-client": "^2.5.3",
|
|
33
|
+
"@milaboratories/pl-model-common": "^1.4.0"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"typescript": "~5.5.4",
|
|
@@ -6,7 +6,18 @@ import { ConsoleLoggerAdapter } from '@milaboratories/ts-helpers';
|
|
|
6
6
|
import { GrpcTransport } from '@protobuf-ts/grpc-transport';
|
|
7
7
|
import { Dispatcher } from 'undici';
|
|
8
8
|
import { text } from 'node:stream/consumers';
|
|
9
|
-
import { ClientDownload } from '../clients/download';
|
|
9
|
+
import { ClientDownload, parseLocalFileUrl } from '../clients/download';
|
|
10
|
+
import { test, expect } from '@jest/globals';
|
|
11
|
+
|
|
12
|
+
test('should parse local file url even on Windows', () => {
|
|
13
|
+
const url = "storage://main/67z%5C2vy%5C65i%5C67z2vy65i0xwhjwsfsef_ex3k3hxe7qdc2cvtdfkdnhdp9kwlt7-7dmcy0kthe6u.json";
|
|
14
|
+
const expectedFullPath = 'C:\\Users\\test\\67z\\2vy\\65i\\67z2vy65i0xwhjwsfsef_ex3k3hxe7qdc2cvtdfkdnhdp9kwlt7-7dmcy0kthe6u.json';
|
|
15
|
+
|
|
16
|
+
const got = parseLocalFileUrl(url, new Map([['main', 'C:\\Users\\test']]))
|
|
17
|
+
.replace(path.sep, '\\'); // for testing on *nix systems
|
|
18
|
+
|
|
19
|
+
expect(got).toEqual(expectedFullPath);
|
|
20
|
+
})
|
|
10
21
|
|
|
11
22
|
test('client download from a local file', async () => {
|
|
12
23
|
await TestHelpers.withTempRoot(async (client) => {
|
package/src/clients/download.ts
CHANGED
|
@@ -18,7 +18,6 @@ import { LocalStorageProjection } from '../drivers/types';
|
|
|
18
18
|
import { validateAbsolute } from '../helpers/validate';
|
|
19
19
|
|
|
20
20
|
const storageProtocol = 'storage://';
|
|
21
|
-
const localPathRegex = /storage:\/\/(?<storageId>.*?)\/(?<localPath>.*)/;
|
|
22
21
|
|
|
23
22
|
export class UnknownStorageError extends Error {}
|
|
24
23
|
|
|
@@ -74,29 +73,16 @@ export class ClientDownload {
|
|
|
74
73
|
return this.isLocal(downloadUrl)
|
|
75
74
|
? await this.readLocalFile(downloadUrl)
|
|
76
75
|
: await this.downloadHelper.downloadRemoteFile(
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
76
|
+
downloadUrl,
|
|
77
|
+
headersFromProto(headers),
|
|
78
|
+
signal
|
|
79
|
+
);
|
|
81
80
|
}
|
|
82
81
|
|
|
83
82
|
private isLocal = (url: string) => url.startsWith(storageProtocol);
|
|
84
83
|
|
|
85
84
|
async readLocalFile(url: string): Promise<DownloadResponse> {
|
|
86
|
-
const
|
|
87
|
-
if (parsed === null || parsed.length != 3) {
|
|
88
|
-
throw new WrongLocalFileUrl(
|
|
89
|
-
`url for local filepath ${url} does not match regex ${localPathRegex}, parsed: ${parsed}`
|
|
90
|
-
);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const [_, storageId, localPath] = parsed;
|
|
94
|
-
|
|
95
|
-
const storageRoot = this.localStorageIdsToRoot.get(storageId);
|
|
96
|
-
if (storageRoot === undefined)
|
|
97
|
-
throw new UnknownStorageError(`Unknown storage location: ${storageId}`);
|
|
98
|
-
|
|
99
|
-
const fullPath = storageRoot === '' ? localPath : path.join(storageRoot, localPath);
|
|
85
|
+
const fullPath = parseLocalFileUrl(url, this.localStorageIdsToRoot);
|
|
100
86
|
const stat = await fsp.stat(fullPath);
|
|
101
87
|
const size = stat.size;
|
|
102
88
|
|
|
@@ -107,6 +93,25 @@ export class ClientDownload {
|
|
|
107
93
|
}
|
|
108
94
|
}
|
|
109
95
|
|
|
96
|
+
export function parseLocalFileUrl(
|
|
97
|
+
url: string,
|
|
98
|
+
localStorageIdsToRoot: Map<string, string>,
|
|
99
|
+
): string {
|
|
100
|
+
const parsed = new URL(url);
|
|
101
|
+
if (parsed.pathname == '')
|
|
102
|
+
throw new WrongLocalFileUrl(`url for local filepath ${url} does not match url scheme`);
|
|
103
|
+
|
|
104
|
+
const storageId = parsed.host;
|
|
105
|
+
const storageRoot = localStorageIdsToRoot.get(storageId);
|
|
106
|
+
if (storageRoot === undefined)
|
|
107
|
+
throw new UnknownStorageError(`Unknown storage location: ${storageId}`);
|
|
108
|
+
|
|
109
|
+
const localPath = decodeURIComponent(parsed.pathname.slice(1));
|
|
110
|
+
const fullPath = storageRoot === '' ? localPath : path.join(storageRoot, localPath);
|
|
111
|
+
|
|
112
|
+
return fullPath;
|
|
113
|
+
}
|
|
114
|
+
|
|
110
115
|
export function headersFromProto(
|
|
111
116
|
headers: DownloadAPI_GetDownloadURL_HTTPHeader[]
|
|
112
117
|
): Record<string, string> {
|