@milaboratories/pl-client 2.4.10
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/README.md +52 -0
- package/dist/index.cjs +14527 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.js +14426 -0
- package/dist/index.js.map +1 -0
- package/package.json +49 -0
- package/src/core/auth.ts +27 -0
- package/src/core/client.test.ts +47 -0
- package/src/core/client.ts +302 -0
- package/src/core/config.test.ts +19 -0
- package/src/core/config.ts +197 -0
- package/src/core/default_client.ts +161 -0
- package/src/core/driver.ts +30 -0
- package/src/core/error.test.ts +14 -0
- package/src/core/errors.ts +84 -0
- package/src/core/http.ts +178 -0
- package/src/core/ll_client.test.ts +111 -0
- package/src/core/ll_client.ts +228 -0
- package/src/core/ll_transaction.test.ts +152 -0
- package/src/core/ll_transaction.ts +333 -0
- package/src/core/transaction.test.ts +173 -0
- package/src/core/transaction.ts +730 -0
- package/src/core/type_conversion.ts +121 -0
- package/src/core/types.test.ts +22 -0
- package/src/core/types.ts +223 -0
- package/src/core/unauth_client.test.ts +21 -0
- package/src/core/unauth_client.ts +48 -0
- package/src/helpers/pl.ts +141 -0
- package/src/helpers/poll.ts +178 -0
- package/src/helpers/rich_resource_types.test.ts +22 -0
- package/src/helpers/rich_resource_types.ts +84 -0
- package/src/helpers/smart_accessors.ts +146 -0
- package/src/helpers/state_helpers.ts +5 -0
- package/src/helpers/tx_helpers.ts +24 -0
- package/src/index.ts +14 -0
- package/src/proto/github.com/googleapis/googleapis/google/rpc/status.ts +125 -0
- package/src/proto/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.client.ts +45 -0
- package/src/proto/github.com/milaboratory/pl/controllers/shared/grpc/downloadapi/protocol.ts +271 -0
- package/src/proto/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.client.ts +51 -0
- package/src/proto/github.com/milaboratory/pl/controllers/shared/grpc/lsapi/protocol.ts +380 -0
- package/src/proto/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.client.ts +59 -0
- package/src/proto/github.com/milaboratory/pl/controllers/shared/grpc/progressapi/protocol.ts +450 -0
- package/src/proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.client.ts +148 -0
- package/src/proto/github.com/milaboratory/pl/controllers/shared/grpc/streamingapi/protocol.ts +706 -0
- package/src/proto/github.com/milaboratory/pl/plapi/plapiproto/api.client.ts +406 -0
- package/src/proto/github.com/milaboratory/pl/plapi/plapiproto/api.ts +12636 -0
- package/src/proto/github.com/milaboratory/pl/plapi/plapiproto/api_types.ts +1384 -0
- package/src/proto/github.com/milaboratory/pl/plapi/plapiproto/base_types.ts +181 -0
- package/src/proto/github.com/milaboratory/pl/plapi/plapiproto/import.ts +251 -0
- package/src/proto/github.com/milaboratory/pl/plapi/plapiproto/resource_types.ts +693 -0
- package/src/proto/google/api/http.ts +687 -0
- package/src/proto/google/protobuf/any.ts +326 -0
- package/src/proto/google/protobuf/descriptor.ts +4502 -0
- package/src/proto/google/protobuf/duration.ts +230 -0
- package/src/proto/google/protobuf/empty.ts +81 -0
- package/src/proto/google/protobuf/struct.ts +482 -0
- package/src/proto/google/protobuf/timestamp.ts +287 -0
- package/src/proto/google/protobuf/wrappers.ts +751 -0
- package/src/test/test_config.test.ts +6 -0
- package/src/test/test_config.ts +166 -0
- package/src/util/branding.ts +4 -0
- package/src/util/pl.ts +11 -0
- package/src/util/util.test.ts +10 -0
- package/src/util/util.ts +9 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import { LLPlClient } from '../core/ll_client';
|
|
3
|
+
import { AuthInformation, AuthOps, plAddressToConfig, PlClientConfig } from '../core/config';
|
|
4
|
+
import { UnauthenticatedPlClient } from '../core/unauth_client';
|
|
5
|
+
import { PlClient } from '../core/client';
|
|
6
|
+
import { randomUUID } from 'crypto';
|
|
7
|
+
import { NullResourceId, OptionalResourceId, ResourceId, resourceIdToString } from '../core/types';
|
|
8
|
+
import { inferAuthRefreshTime } from '../core/auth';
|
|
9
|
+
import * as path from 'node:path';
|
|
10
|
+
|
|
11
|
+
export interface TestConfig {
|
|
12
|
+
address: string;
|
|
13
|
+
test_proxy?: string;
|
|
14
|
+
test_user?: string;
|
|
15
|
+
test_password?: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const CONFIG_FILE = 'test_config.json';
|
|
19
|
+
// const AUTH_DATA_FILE = '.test_auth.json';
|
|
20
|
+
|
|
21
|
+
let authDataFilePath: string | undefined;
|
|
22
|
+
|
|
23
|
+
function getFullAuthDataFilePath() {
|
|
24
|
+
if (authDataFilePath === undefined) authDataFilePath = path.resolve('.test_auth.json');
|
|
25
|
+
return authDataFilePath;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function getTestConfig(): TestConfig {
|
|
29
|
+
let conf: Partial<TestConfig> = {};
|
|
30
|
+
if (fs.existsSync(CONFIG_FILE))
|
|
31
|
+
conf = JSON.parse(fs.readFileSync(CONFIG_FILE, { encoding: 'utf-8' }));
|
|
32
|
+
|
|
33
|
+
if (process.env.PL_ADDRESS !== undefined) conf.address = process.env.PL_ADDRESS;
|
|
34
|
+
|
|
35
|
+
if (process.env.PL_TEST_USER !== undefined) conf.test_user = process.env.PL_TEST_USER;
|
|
36
|
+
|
|
37
|
+
if (process.env.PL_TEST_PASSWORD !== undefined) conf.test_password = process.env.PL_TEST_PASSWORD;
|
|
38
|
+
|
|
39
|
+
if (process.env.PL_TEST_PROXY !== undefined) conf.test_proxy = process.env.PL_TEST_PROXY;
|
|
40
|
+
|
|
41
|
+
if (conf.address === undefined)
|
|
42
|
+
throw new Error(
|
|
43
|
+
`can't resolve platform address (checked ${CONFIG_FILE} file and PL_ADDRESS environment var)`
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
return conf as TestConfig;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
interface AuthCache {
|
|
50
|
+
/** To check if config changed */
|
|
51
|
+
conf: TestConfig;
|
|
52
|
+
expiration: number;
|
|
53
|
+
authInformation: AuthInformation;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function saveAuthInfoCallback(tConf: TestConfig): (authInformation: AuthInformation) => void {
|
|
57
|
+
return (authInformation) => {
|
|
58
|
+
const dst = getFullAuthDataFilePath();
|
|
59
|
+
const tmpDst = getFullAuthDataFilePath() + randomUUID();
|
|
60
|
+
fs.writeFileSync(
|
|
61
|
+
tmpDst,
|
|
62
|
+
Buffer.from(
|
|
63
|
+
JSON.stringify({
|
|
64
|
+
conf: tConf,
|
|
65
|
+
authInformation,
|
|
66
|
+
expiration: inferAuthRefreshTime(authInformation, 24 * 60 * 60)
|
|
67
|
+
} as AuthCache)
|
|
68
|
+
),
|
|
69
|
+
'utf8'
|
|
70
|
+
);
|
|
71
|
+
fs.renameSync(tmpDst, dst);
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const cleanAuthInfoCallback = () => {
|
|
76
|
+
console.warn(`Removing: ${getFullAuthDataFilePath()}`);
|
|
77
|
+
fs.rmSync(getFullAuthDataFilePath());
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
export async function getTestClientConf(): Promise<{ conf: PlClientConfig; auth: AuthOps }> {
|
|
81
|
+
const tConf = getTestConfig();
|
|
82
|
+
|
|
83
|
+
let authInformation: AuthInformation | undefined = undefined;
|
|
84
|
+
|
|
85
|
+
// try recover from cache
|
|
86
|
+
if (fs.existsSync(getFullAuthDataFilePath())) {
|
|
87
|
+
try {
|
|
88
|
+
const cache: AuthCache = JSON.parse(
|
|
89
|
+
fs.readFileSync(getFullAuthDataFilePath(), { encoding: 'utf-8' })
|
|
90
|
+
);
|
|
91
|
+
if (
|
|
92
|
+
cache.conf.address === tConf.address &&
|
|
93
|
+
cache.conf.test_user === tConf.test_user &&
|
|
94
|
+
cache.conf.test_password === tConf.test_password &&
|
|
95
|
+
cache.expiration > Date.now()
|
|
96
|
+
)
|
|
97
|
+
authInformation = cache.authInformation;
|
|
98
|
+
} catch (e: any) {
|
|
99
|
+
// removing cache file on any error
|
|
100
|
+
fs.rmSync(getFullAuthDataFilePath());
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const plConf = plAddressToConfig(tConf.address);
|
|
105
|
+
|
|
106
|
+
const uClient = new UnauthenticatedPlClient(plConf);
|
|
107
|
+
|
|
108
|
+
const requireAuth = await uClient.requireAuth();
|
|
109
|
+
|
|
110
|
+
if (!requireAuth && (tConf.test_user !== undefined || tConf.test_password !== undefined))
|
|
111
|
+
throw new Error(
|
|
112
|
+
`Server require no auth, but test user name or test password are provided via (${CONFIG_FILE}) or env variables: PL_TEST_USER and PL_TEST_PASSWORD`
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
if (requireAuth && (tConf.test_user === undefined || tConf.test_password === undefined))
|
|
116
|
+
throw new Error(
|
|
117
|
+
`No auth information found in config (${CONFIG_FILE}) or env variables: PL_TEST_USER and PL_TEST_PASSWORD`
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
if (authInformation === undefined) {
|
|
121
|
+
if (requireAuth) authInformation = await uClient.login(tConf.test_user!, tConf.test_password!);
|
|
122
|
+
// No authorization is required
|
|
123
|
+
else authInformation = {};
|
|
124
|
+
|
|
125
|
+
// saving cache
|
|
126
|
+
saveAuthInfoCallback(tConf)(authInformation);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
conf: plConf,
|
|
131
|
+
auth: {
|
|
132
|
+
authInformation,
|
|
133
|
+
onUpdate: saveAuthInfoCallback(tConf),
|
|
134
|
+
onAuthError: cleanAuthInfoCallback,
|
|
135
|
+
onUpdateError: cleanAuthInfoCallback
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
export async function getTestLLClient(confOverrides: Partial<PlClientConfig> = {}) {
|
|
141
|
+
const { conf, auth } = await getTestClientConf();
|
|
142
|
+
return new LLPlClient({ ...conf, ...confOverrides }, { auth });
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
export async function getTestClient(alternativeRoot?: string) {
|
|
146
|
+
const { conf, auth } = await getTestClientConf();
|
|
147
|
+
if (alternativeRoot !== undefined && conf.alternativeRoot !== undefined)
|
|
148
|
+
throw new Error('test pl address configured with alternative root');
|
|
149
|
+
return await PlClient.init({ ...conf, alternativeRoot }, auth);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
export async function withTempRoot<T>(body: (pl: PlClient) => Promise<T>): Promise<T> {
|
|
153
|
+
const altRoot = `test_${Date.now()}_${randomUUID()}`;
|
|
154
|
+
let altRootId: OptionalResourceId = NullResourceId;
|
|
155
|
+
try {
|
|
156
|
+
const client = await getTestClient(altRoot);
|
|
157
|
+
altRootId = client.clientRoot;
|
|
158
|
+
const value = await body(client);
|
|
159
|
+
const rawClient = await getTestClient();
|
|
160
|
+
await rawClient.deleteAlternativeRoot(altRoot);
|
|
161
|
+
return value;
|
|
162
|
+
} catch (err: any) {
|
|
163
|
+
console.log(`ALTERNATIVE ROOT: ${altRoot} (${resourceIdToString(altRootId)})`);
|
|
164
|
+
throw new Error(err.message, { cause: err });
|
|
165
|
+
}
|
|
166
|
+
}
|
package/src/util/pl.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { toBytes } from './util';
|
|
2
|
+
|
|
3
|
+
test('test toBytes 1', () => {
|
|
4
|
+
const arr = new Uint8Array([1, 2, 3]);
|
|
5
|
+
expect(toBytes(arr)).toEqual(arr);
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
test('test toBytes 2', () => {
|
|
9
|
+
expect(toBytes('\x01\x02\x03')).toEqual(Buffer.from(new Uint8Array([1, 2, 3])));
|
|
10
|
+
});
|
package/src/util/util.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
function isArrayBufferOrView(value: unknown): value is ArrayBufferLike {
|
|
2
|
+
return value instanceof ArrayBuffer || ArrayBuffer.isView(value);
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function toBytes(value: string | Uint8Array): Uint8Array {
|
|
6
|
+
if (typeof value === 'string') return Buffer.from(value);
|
|
7
|
+
else if (isArrayBufferOrView(value)) return value;
|
|
8
|
+
else throw new Error(`Unexpected type: ${value}`);
|
|
9
|
+
}
|