@milaboratories/pl-client 2.16.13 → 2.16.14
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/__external/.pnpm/{@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3 → @rollup_plugin-typescript@12.3.0_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3}/__external/tslib/tslib.es6.cjs.map +1 -1
- package/dist/__external/.pnpm/{@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3 → @rollup_plugin-typescript@12.3.0_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3}/__external/tslib/tslib.es6.js.map +1 -1
- package/dist/core/client.cjs +31 -16
- package/dist/core/client.cjs.map +1 -1
- package/dist/core/client.d.ts +3 -2
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js +31 -16
- package/dist/core/client.js.map +1 -1
- package/dist/core/default_client.cjs +1 -1
- package/dist/core/default_client.cjs.map +1 -1
- package/dist/core/default_client.js +1 -1
- package/dist/core/default_client.js.map +1 -1
- package/dist/core/errors.cjs +15 -4
- package/dist/core/errors.cjs.map +1 -1
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +15 -4
- package/dist/core/errors.js.map +1 -1
- package/dist/core/ll_client.cjs +44 -14
- package/dist/core/ll_client.cjs.map +1 -1
- package/dist/core/ll_client.d.ts +12 -3
- package/dist/core/ll_client.d.ts.map +1 -1
- package/dist/core/ll_client.js +45 -15
- package/dist/core/ll_client.js.map +1 -1
- package/dist/core/transaction.cjs +1 -1
- package/dist/core/transaction.js +1 -1
- package/dist/core/unauth_client.cjs +6 -2
- package/dist/core/unauth_client.cjs.map +1 -1
- package/dist/core/unauth_client.d.ts +2 -1
- package/dist/core/unauth_client.d.ts.map +1 -1
- package/dist/core/unauth_client.js +6 -2
- package/dist/core/unauth_client.js.map +1 -1
- package/dist/core/websocket_stream.cjs +23 -2
- package/dist/core/websocket_stream.cjs.map +1 -1
- package/dist/core/websocket_stream.d.ts.map +1 -1
- package/dist/core/websocket_stream.js +23 -2
- package/dist/core/websocket_stream.js.map +1 -1
- package/dist/test/test_config.cjs +13 -3
- package/dist/test/test_config.cjs.map +1 -1
- package/dist/test/test_config.d.ts +4 -0
- package/dist/test/test_config.d.ts.map +1 -1
- package/dist/test/test_config.js +12 -4
- package/dist/test/test_config.js.map +1 -1
- package/package.json +4 -4
- package/src/core/client.ts +40 -21
- package/src/core/default_client.ts +1 -1
- package/src/core/errors.ts +14 -4
- package/src/core/ll_client.test.ts +9 -3
- package/src/core/ll_client.ts +56 -18
- package/src/core/unauth_client.test.ts +4 -4
- package/src/core/unauth_client.ts +7 -2
- package/src/core/websocket_stream.ts +22 -1
- package/src/test/test_config.ts +13 -4
- /package/dist/__external/.pnpm/{@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3 → @rollup_plugin-typescript@12.3.0_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3}/__external/tslib/tslib.es6.cjs +0 -0
- /package/dist/__external/.pnpm/{@rollup_plugin-typescript@12.1.4_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3 → @rollup_plugin-typescript@12.3.0_rollup@4.52.4_tslib@2.8.1_typescript@5.6.3}/__external/tslib/tslib.es6.js +0 -0
package/dist/core/client.js
CHANGED
|
@@ -10,6 +10,7 @@ import { LRUCache } from 'lru-cache';
|
|
|
10
10
|
import { DefaultFinalResourceDataPredicate } from './final.js';
|
|
11
11
|
import { initialTxStat, addStat } from './stat.js';
|
|
12
12
|
import { advisoryLock } from './advisory_locks.js';
|
|
13
|
+
import { plAddressToConfig } from './config.js';
|
|
13
14
|
|
|
14
15
|
const defaultTxOps = {
|
|
15
16
|
sync: false,
|
|
@@ -30,6 +31,12 @@ class PlClient {
|
|
|
30
31
|
defaultRetryOptions;
|
|
31
32
|
buildLLPlClient;
|
|
32
33
|
_ll;
|
|
34
|
+
get ll() {
|
|
35
|
+
if (this._ll === undefined) {
|
|
36
|
+
throw new Error('LLPlClient not initialized');
|
|
37
|
+
}
|
|
38
|
+
return this._ll;
|
|
39
|
+
}
|
|
33
40
|
/** Stores client root (this abstraction is intended for future implementation of the security model) */
|
|
34
41
|
_clientRoot = NullResourceId;
|
|
35
42
|
_serverInfo = undefined;
|
|
@@ -44,12 +51,12 @@ class PlClient {
|
|
|
44
51
|
/** Resource data cache, to minimize redundant data rereading from remote db */
|
|
45
52
|
resourceDataCache;
|
|
46
53
|
constructor(configOrAddress, auth, ops = {}) {
|
|
47
|
-
|
|
48
|
-
this.buildLLPlClient = (shouldUseGzip) => {
|
|
49
|
-
|
|
54
|
+
const conf = typeof configOrAddress === 'string' ? plAddressToConfig(configOrAddress) : configOrAddress;
|
|
55
|
+
this.buildLLPlClient = async (shouldUseGzip, wireProtocol) => {
|
|
56
|
+
if (wireProtocol)
|
|
57
|
+
conf.wireProtocol = wireProtocol;
|
|
58
|
+
return await LLPlClient.build(conf, { auth, ...ops, shouldUseGzip });
|
|
50
59
|
};
|
|
51
|
-
this._ll = this.buildLLPlClient(false);
|
|
52
|
-
const conf = this._ll.conf;
|
|
53
60
|
this.txDelay = conf.txDelay;
|
|
54
61
|
this.forceSync = conf.forceSync;
|
|
55
62
|
this.finalPredicate = ops.finalPredicate ?? DefaultFinalResourceDataPredicate;
|
|
@@ -100,19 +107,19 @@ class PlClient {
|
|
|
100
107
|
};
|
|
101
108
|
}
|
|
102
109
|
async ping() {
|
|
103
|
-
return await this.
|
|
110
|
+
return await this.ll.ping();
|
|
104
111
|
}
|
|
105
112
|
async license() {
|
|
106
|
-
return await this.
|
|
113
|
+
return await this.ll.license();
|
|
107
114
|
}
|
|
108
115
|
get conf() {
|
|
109
|
-
return this.
|
|
116
|
+
return this.ll.conf;
|
|
110
117
|
}
|
|
111
118
|
get httpDispatcher() {
|
|
112
|
-
return this.
|
|
119
|
+
return this.ll.httpDispatcher;
|
|
113
120
|
}
|
|
114
121
|
get connectionOpts() {
|
|
115
|
-
return this.
|
|
122
|
+
return this.ll.wireConnection;
|
|
116
123
|
}
|
|
117
124
|
get initialized() {
|
|
118
125
|
return !isNullResourceId(this._clientRoot);
|
|
@@ -133,13 +140,21 @@ class PlClient {
|
|
|
133
140
|
async init() {
|
|
134
141
|
if (this.initialized)
|
|
135
142
|
throw new Error('Already initialized');
|
|
143
|
+
// Initial client is created without gzip to perform server ping and detect optimal wire protocol.
|
|
144
|
+
// LLPlClient.build() internally calls detectOptimalWireProtocol() which starts with default 'grpc',
|
|
145
|
+
// then retries with 'rest' if ping fails, alternating until a working protocol is found.
|
|
146
|
+
// We save the detected wireProtocol here because if the server supports gzip compression,
|
|
147
|
+
// we'll need to reinitialize the client with gzip enabled - passing the already-detected
|
|
148
|
+
// wireProtocol avoids redundant protocol detection on reinit.
|
|
149
|
+
this._ll = await this.buildLLPlClient(false);
|
|
150
|
+
const wireProtocol = this._ll.wireProtocol;
|
|
136
151
|
// calculating reproducible root name from the username
|
|
137
152
|
const user = this._ll.authUser;
|
|
138
153
|
const mainRootName = user === null ? AnonymousClientRoot : createHash('sha256').update(user).digest('hex');
|
|
139
154
|
this._serverInfo = await this.ping();
|
|
140
155
|
if (this._serverInfo.compression === MaintenanceAPI_Ping_Response_Compression.GZIP) {
|
|
141
156
|
await this._ll.close();
|
|
142
|
-
this._ll = this.buildLLPlClient(true);
|
|
157
|
+
this._ll = await this.buildLLPlClient(true, wireProtocol);
|
|
143
158
|
}
|
|
144
159
|
this._clientRoot = await this._withTx('initialization', true, NullResourceId, async (tx) => {
|
|
145
160
|
let mainRoot;
|
|
@@ -170,7 +185,7 @@ class PlClient {
|
|
|
170
185
|
/** Returns true if field existed */
|
|
171
186
|
async deleteAlternativeRoot(alternativeRootName) {
|
|
172
187
|
this.checkInitialized();
|
|
173
|
-
if (this.
|
|
188
|
+
if (this.ll.conf.alternativeRoot !== undefined)
|
|
174
189
|
throw new Error('Initialized with alternative root.');
|
|
175
190
|
return await this.withWriteTx('delete-alternative-root', async (tx) => {
|
|
176
191
|
const fId = {
|
|
@@ -190,7 +205,7 @@ class PlClient {
|
|
|
190
205
|
const release = ops?.lockId ? await advisoryLock(ops.lockId) : () => { };
|
|
191
206
|
try {
|
|
192
207
|
// opening low-level tx
|
|
193
|
-
const llTx = this.
|
|
208
|
+
const llTx = this.ll.createTx(writable, ops);
|
|
194
209
|
// wrapping it into high-level tx (this also asynchronously sends initialization message)
|
|
195
210
|
const tx = new PlTransaction(llTx, name, writable, clientRoot, this.finalPredicate, this.resourceDataCache);
|
|
196
211
|
let ok = false;
|
|
@@ -228,7 +243,7 @@ class PlClient {
|
|
|
228
243
|
if (ok) {
|
|
229
244
|
// syncing on transaction if requested
|
|
230
245
|
if (ops?.sync === undefined ? this.forceSync : ops?.sync)
|
|
231
|
-
await this.
|
|
246
|
+
await this.ll.txSync(txId);
|
|
232
247
|
// introducing artificial delay, if requested
|
|
233
248
|
if (writable && this.txDelay > 0)
|
|
234
249
|
await tp.setTimeout(this.txDelay, undefined, { signal: ops?.abortSignal });
|
|
@@ -258,13 +273,13 @@ class PlClient {
|
|
|
258
273
|
const attached = this.drivers.get(definition.name);
|
|
259
274
|
if (attached !== undefined)
|
|
260
275
|
return attached;
|
|
261
|
-
const driver = definition.init(this, this.
|
|
276
|
+
const driver = definition.init(this, this.ll, this.httpDispatcher);
|
|
262
277
|
this.drivers.set(definition.name, driver);
|
|
263
278
|
return driver;
|
|
264
279
|
}
|
|
265
280
|
/** Closes underlying transport */
|
|
266
281
|
async close() {
|
|
267
|
-
await this.
|
|
282
|
+
await this.ll.close();
|
|
268
283
|
}
|
|
269
284
|
static async init(configOrAddress, auth, ops = {}) {
|
|
270
285
|
const pl = new PlClient(configOrAddress, auth, ops);
|
package/dist/core/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sources":["../../src/core/client.ts"],"sourcesContent":["import type { AuthOps, PlClientConfig, PlConnectionStatusListener } from './config';\nimport type { PlCallOps } from './ll_client';\nimport { LLPlClient } from './ll_client';\nimport type { AnyResourceRef } from './transaction';\nimport { PlTransaction, toGlobalResourceId, TxCommitConflict } from './transaction';\nimport { createHash } from 'node:crypto';\nimport type { OptionalResourceId, ResourceId } from './types';\nimport { ensureResourceIdNotNull, isNullResourceId, NullResourceId } from './types';\nimport { ClientRoot } from '../helpers/pl';\nimport type { RetryOptions } from '@milaboratories/ts-helpers';\nimport { assertNever, createRetryState, nextRetryStateOrError } from '@milaboratories/ts-helpers';\nimport type { PlDriver, PlDriverDefinition } from './driver';\nimport type { MaintenanceAPI_Ping_Response, MaintenanceAPI_License_Response } from '../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api';\nimport { MaintenanceAPI_Ping_Response_Compression } from '../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api';\nimport * as tp from 'node:timers/promises';\nimport type { Dispatcher } from 'undici';\nimport { LRUCache } from 'lru-cache';\nimport type { ResourceDataCacheRecord } from './cache';\nimport type { FinalResourceDataPredicate } from './final';\nimport { DefaultFinalResourceDataPredicate } from './final';\nimport type { AllTxStat, TxStat } from './stat';\nimport { addStat, initialTxStat } from './stat';\nimport type { WireConnection } from './wire';\nimport { advisoryLock } from './advisory_locks';\n\nexport type TxOps = PlCallOps & {\n sync?: boolean;\n retryOptions?: RetryOptions;\n name?: string;\n lockId?: string;\n};\n\nconst defaultTxOps = {\n sync: false,\n};\n\nconst AnonymousClientRoot = 'AnonymousRoot';\n\nfunction alternativeRootFieldName(alternativeRoot: string): string {\n return `alternative_root_${alternativeRoot}`;\n}\n\n/** Client to access core PL API. */\nexport class PlClient {\n private readonly drivers = new Map<string, PlDriver>();\n\n /** Artificial delay introduced after write transactions completion, to\n * somewhat throttle the load on pl. Delay introduced after sync, if requested. */\n private readonly txDelay: number;\n\n /** Last resort measure to solve complicated race conditions in pl. */\n private readonly forceSync: boolean;\n\n /** Last resort measure to solve complicated race conditions in pl. */\n private readonly defaultRetryOptions: RetryOptions;\n\n private readonly buildLLPlClient: (shouldUseGzip: boolean) => LLPlClient;\n private _ll: LLPlClient;\n /** Stores client root (this abstraction is intended for future implementation of the security model) */\n private _clientRoot: OptionalResourceId = NullResourceId;\n\n private _serverInfo: MaintenanceAPI_Ping_Response | undefined = undefined;\n\n private _txCommittedStat: TxStat = initialTxStat();\n private _txConflictStat: TxStat = initialTxStat();\n private _txErrorStat: TxStat = initialTxStat();\n\n //\n // Caching\n //\n\n /** This function determines whether resource data can be cached */\n public readonly finalPredicate: FinalResourceDataPredicate;\n\n /** Resource data cache, to minimize redundant data rereading from remote db */\n private readonly resourceDataCache: LRUCache<ResourceId, ResourceDataCacheRecord>;\n\n private constructor(\n configOrAddress: PlClientConfig | string,\n auth: AuthOps,\n ops: {\n statusListener?: PlConnectionStatusListener;\n finalPredicate?: FinalResourceDataPredicate;\n } = {},\n ) {\n // Will reinitialize client after getting available feature from server.\n this.buildLLPlClient = (shouldUseGzip: boolean) => {\n return new LLPlClient(configOrAddress, { auth, ...ops, shouldUseGzip });\n };\n this._ll = this.buildLLPlClient(false);\n const conf = this._ll.conf;\n this.txDelay = conf.txDelay;\n this.forceSync = conf.forceSync;\n this.finalPredicate = ops.finalPredicate ?? DefaultFinalResourceDataPredicate;\n this.resourceDataCache = new LRUCache({\n maxSize: conf.maxCacheBytes,\n sizeCalculation: (v) => (v.basicData.data?.length ?? 0) + 64,\n });\n switch (conf.retryBackoffAlgorithm) {\n case 'exponential':\n this.defaultRetryOptions = {\n type: 'exponentialBackoff',\n initialDelay: conf.retryInitialDelay,\n maxAttempts: conf.retryMaxAttempts,\n backoffMultiplier: conf.retryExponentialBackoffMultiplier,\n jitter: conf.retryJitter,\n };\n break;\n case 'linear':\n this.defaultRetryOptions = {\n type: 'linearBackoff',\n initialDelay: conf.retryInitialDelay,\n maxAttempts: conf.retryMaxAttempts,\n backoffStep: conf.retryLinearBackoffStep,\n jitter: conf.retryJitter,\n };\n break;\n default:\n assertNever(conf.retryBackoffAlgorithm);\n }\n }\n\n public get txCommittedStat(): TxStat {\n return { ...this._txCommittedStat };\n }\n\n public get txConflictStat(): TxStat {\n return { ...this._txConflictStat };\n }\n\n public get txErrorStat(): TxStat {\n return { ...this._txErrorStat };\n }\n\n public get txTotalStat(): TxStat {\n return addStat(addStat(this._txCommittedStat, this._txConflictStat), this._txErrorStat);\n }\n\n public get allTxStat(): AllTxStat {\n return {\n committed: this.txCommittedStat,\n conflict: this.txConflictStat,\n error: this.txErrorStat,\n };\n }\n\n public async ping(): Promise<MaintenanceAPI_Ping_Response> {\n return await this._ll.ping();\n }\n\n public async license(): Promise<MaintenanceAPI_License_Response> {\n return await this._ll.license();\n }\n\n public get conf(): PlClientConfig {\n return this._ll.conf;\n }\n\n public get httpDispatcher(): Dispatcher {\n return this._ll.httpDispatcher;\n }\n\n public get connectionOpts(): WireConnection {\n return this._ll.wireConnection;\n }\n\n private get initialized() {\n return !isNullResourceId(this._clientRoot);\n }\n\n private checkInitialized() {\n if (!this.initialized) throw new Error('Client not initialized');\n }\n\n public get clientRoot(): ResourceId {\n this.checkInitialized();\n return ensureResourceIdNotNull(this._clientRoot);\n }\n\n public get serverInfo(): MaintenanceAPI_Ping_Response {\n this.checkInitialized();\n return this._serverInfo!;\n }\n\n /** Currently implements custom logic to emulate future behaviour with single root. */\n public async init() {\n if (this.initialized) throw new Error('Already initialized');\n\n // calculating reproducible root name from the username\n const user = this._ll.authUser;\n const mainRootName\n = user === null ? AnonymousClientRoot : createHash('sha256').update(user).digest('hex');\n\n this._serverInfo = await this.ping();\n if (this._serverInfo.compression === MaintenanceAPI_Ping_Response_Compression.GZIP) {\n await this._ll.close();\n this._ll = this.buildLLPlClient(true);\n }\n\n this._clientRoot = await this._withTx('initialization', true, NullResourceId, async (tx) => {\n let mainRoot: AnyResourceRef;\n\n if (await tx.checkResourceNameExists(mainRootName))\n mainRoot = await tx.getResourceByName(mainRootName);\n else {\n mainRoot = tx.createRoot(ClientRoot);\n tx.setResourceName(mainRootName, mainRoot);\n }\n\n if (this.conf.alternativeRoot === undefined) {\n await tx.commit();\n return await toGlobalResourceId(mainRoot);\n } else {\n const aFId = {\n resourceId: mainRoot,\n fieldName: alternativeRootFieldName(this.conf.alternativeRoot),\n };\n\n const altRoot = tx.createEphemeral(ClientRoot);\n tx.lock(altRoot);\n tx.createField(aFId, 'Dynamic');\n tx.setField(aFId, altRoot);\n await tx.commit();\n\n return await altRoot.globalId;\n }\n });\n }\n\n /** Returns true if field existed */\n public async deleteAlternativeRoot(alternativeRootName: string): Promise<boolean> {\n this.checkInitialized();\n if (this._ll.conf.alternativeRoot !== undefined)\n throw new Error('Initialized with alternative root.');\n return await this.withWriteTx('delete-alternative-root', async (tx) => {\n const fId = {\n resourceId: tx.clientRoot,\n fieldName: alternativeRootFieldName(alternativeRootName),\n };\n const exists = tx.fieldExists(fId);\n tx.removeField(fId);\n await tx.commit();\n return await exists;\n });\n }\n\n private async _withTx<T>(\n name: string,\n writable: boolean,\n clientRoot: OptionalResourceId,\n body: (tx: PlTransaction) => Promise<T>,\n ops?: TxOps,\n ): Promise<T> {\n // for exponential / linear backoff\n let retryState = createRetryState(ops?.retryOptions ?? this.defaultRetryOptions);\n\n while (true) {\n const release = ops?.lockId ? await advisoryLock(ops.lockId) : () => {};\n\n try {\n // opening low-level tx\n const llTx = this._ll.createTx(writable, ops);\n // wrapping it into high-level tx (this also asynchronously sends initialization message)\n const tx = new PlTransaction(\n llTx,\n name,\n writable,\n clientRoot,\n this.finalPredicate,\n this.resourceDataCache,\n );\n\n let ok = false;\n let result: T | undefined = undefined;\n let txId;\n\n try {\n // executing transaction body\n result = await body(tx);\n // collecting stat\n this._txCommittedStat = addStat(this._txCommittedStat, tx.stat);\n ok = true;\n } catch (e: unknown) {\n // the only recoverable\n if (e instanceof TxCommitConflict) {\n // ignoring\n // collecting stat\n this._txConflictStat = addStat(this._txConflictStat, tx.stat);\n } else {\n // collecting stat\n this._txErrorStat = addStat(this._txErrorStat, tx.stat);\n throw e;\n }\n } finally {\n // close underlying grpc stream, if not yet done\n\n // even though we can skip two lines below for read-only transactions,\n // we don't do it to simplify reasoning about what is going on in\n // concurrent code, especially in significant latency situations\n await tx.complete();\n await tx.await();\n\n txId = await tx.getGlobalTxId();\n }\n\n if (ok) {\n // syncing on transaction if requested\n if (ops?.sync === undefined ? this.forceSync : ops?.sync)\n await this._ll.txSync(txId);\n\n // introducing artificial delay, if requested\n if (writable && this.txDelay > 0)\n await tp.setTimeout(this.txDelay, undefined, { signal: ops?.abortSignal });\n\n return result!;\n }\n } finally {\n release();\n }\n\n // we only get here after TxCommitConflict error,\n // all other errors terminate this loop instantly\n\n await tp.setTimeout(retryState.nextDelay, undefined, { signal: ops?.abortSignal });\n retryState = nextRetryStateOrError(retryState);\n }\n }\n\n private async withTx<T>(\n name: string,\n writable: boolean,\n body: (tx: PlTransaction) => Promise<T>,\n ops: Partial<TxOps> = {},\n ): Promise<T> {\n this.checkInitialized();\n return await this._withTx(name, writable, this.clientRoot, body, { ...ops, ...defaultTxOps });\n }\n\n public async withWriteTx<T>(\n name: string,\n body: (tx: PlTransaction) => Promise<T>,\n ops: Partial<TxOps> = {},\n ): Promise<T> {\n return await this.withTx(name, true, body, { ...ops, ...defaultTxOps });\n }\n\n public async withReadTx<T>(\n name: string,\n body: (tx: PlTransaction) => Promise<T>,\n ops: Partial<TxOps> = {},\n ): Promise<T> {\n return await this.withTx(name, false, body, { ...ops, ...defaultTxOps });\n }\n\n public getDriver<Drv extends PlDriver>(definition: PlDriverDefinition<Drv>): Drv {\n const attached = this.drivers.get(definition.name);\n if (attached !== undefined) return attached as Drv;\n const driver = definition.init(this, this._ll, this.httpDispatcher);\n this.drivers.set(definition.name, driver);\n return driver;\n }\n\n /** Closes underlying transport */\n public async close() {\n await this._ll.close();\n }\n\n public static async init(\n configOrAddress: PlClientConfig | string,\n auth: AuthOps,\n ops: {\n statusListener?: PlConnectionStatusListener;\n } = {},\n ) {\n const pl = new PlClient(configOrAddress, auth, ops);\n await pl.init();\n return pl;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"client.js","sources":["../../src/core/client.ts"],"sourcesContent":["import type { AuthOps, PlClientConfig, PlConnectionStatusListener, wireProtocol } from './config';\nimport type { PlCallOps } from './ll_client';\nimport { LLPlClient } from './ll_client';\nimport type { AnyResourceRef } from './transaction';\nimport { PlTransaction, toGlobalResourceId, TxCommitConflict } from './transaction';\nimport { createHash } from 'node:crypto';\nimport type { OptionalResourceId, ResourceId } from './types';\nimport { ensureResourceIdNotNull, isNullResourceId, NullResourceId } from './types';\nimport { ClientRoot } from '../helpers/pl';\nimport type { RetryOptions } from '@milaboratories/ts-helpers';\nimport { assertNever, createRetryState, nextRetryStateOrError } from '@milaboratories/ts-helpers';\nimport type { PlDriver, PlDriverDefinition } from './driver';\nimport type { MaintenanceAPI_Ping_Response, MaintenanceAPI_License_Response } from '../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api';\nimport { MaintenanceAPI_Ping_Response_Compression } from '../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api';\nimport * as tp from 'node:timers/promises';\nimport type { Dispatcher } from 'undici';\nimport { LRUCache } from 'lru-cache';\nimport type { ResourceDataCacheRecord } from './cache';\nimport type { FinalResourceDataPredicate } from './final';\nimport { DefaultFinalResourceDataPredicate } from './final';\nimport type { AllTxStat, TxStat } from './stat';\nimport { addStat, initialTxStat } from './stat';\nimport type { WireConnection } from './wire';\nimport { advisoryLock } from './advisory_locks';\nimport { plAddressToConfig } from './config';\n\nexport type TxOps = PlCallOps & {\n sync?: boolean;\n retryOptions?: RetryOptions;\n name?: string;\n lockId?: string;\n};\n\nconst defaultTxOps = {\n sync: false,\n};\n\nconst AnonymousClientRoot = 'AnonymousRoot';\n\nfunction alternativeRootFieldName(alternativeRoot: string): string {\n return `alternative_root_${alternativeRoot}`;\n}\n\n/** Client to access core PL API. */\nexport class PlClient {\n private readonly drivers = new Map<string, PlDriver>();\n\n /** Artificial delay introduced after write transactions completion, to\n * somewhat throttle the load on pl. Delay introduced after sync, if requested. */\n private readonly txDelay: number;\n\n /** Last resort measure to solve complicated race conditions in pl. */\n private readonly forceSync: boolean;\n\n /** Last resort measure to solve complicated race conditions in pl. */\n private readonly defaultRetryOptions: RetryOptions;\n\n private readonly buildLLPlClient: (shouldUseGzip: boolean, wireProtocol?: wireProtocol) => Promise<LLPlClient>;\n private _ll?: LLPlClient;\n\n private get ll(): LLPlClient {\n if (this._ll === undefined) {\n throw new Error('LLPlClient not initialized');\n }\n return this._ll;\n }\n\n /** Stores client root (this abstraction is intended for future implementation of the security model) */\n private _clientRoot: OptionalResourceId = NullResourceId;\n\n private _serverInfo: MaintenanceAPI_Ping_Response | undefined = undefined;\n\n private _txCommittedStat: TxStat = initialTxStat();\n private _txConflictStat: TxStat = initialTxStat();\n private _txErrorStat: TxStat = initialTxStat();\n\n //\n // Caching\n //\n\n /** This function determines whether resource data can be cached */\n public readonly finalPredicate: FinalResourceDataPredicate;\n\n /** Resource data cache, to minimize redundant data rereading from remote db */\n private readonly resourceDataCache: LRUCache<ResourceId, ResourceDataCacheRecord>;\n\n private constructor(\n configOrAddress: PlClientConfig | string,\n auth: AuthOps,\n ops: {\n statusListener?: PlConnectionStatusListener;\n finalPredicate?: FinalResourceDataPredicate;\n } = {},\n ) {\n const conf = typeof configOrAddress === 'string' ? plAddressToConfig(configOrAddress) : configOrAddress;\n\n this.buildLLPlClient = async (shouldUseGzip: boolean, wireProtocol?: wireProtocol): Promise<LLPlClient> => {\n if (wireProtocol) conf.wireProtocol = wireProtocol;\n return await LLPlClient.build(conf, { auth, ...ops, shouldUseGzip });\n };\n\n this.txDelay = conf.txDelay;\n this.forceSync = conf.forceSync;\n this.finalPredicate = ops.finalPredicate ?? DefaultFinalResourceDataPredicate;\n this.resourceDataCache = new LRUCache({\n maxSize: conf.maxCacheBytes,\n sizeCalculation: (v) => (v.basicData.data?.length ?? 0) + 64,\n });\n switch (conf.retryBackoffAlgorithm) {\n case 'exponential':\n this.defaultRetryOptions = {\n type: 'exponentialBackoff',\n initialDelay: conf.retryInitialDelay,\n maxAttempts: conf.retryMaxAttempts,\n backoffMultiplier: conf.retryExponentialBackoffMultiplier,\n jitter: conf.retryJitter,\n };\n break;\n case 'linear':\n this.defaultRetryOptions = {\n type: 'linearBackoff',\n initialDelay: conf.retryInitialDelay,\n maxAttempts: conf.retryMaxAttempts,\n backoffStep: conf.retryLinearBackoffStep,\n jitter: conf.retryJitter,\n };\n break;\n default:\n assertNever(conf.retryBackoffAlgorithm);\n }\n }\n\n public get txCommittedStat(): TxStat {\n return { ...this._txCommittedStat };\n }\n\n public get txConflictStat(): TxStat {\n return { ...this._txConflictStat };\n }\n\n public get txErrorStat(): TxStat {\n return { ...this._txErrorStat };\n }\n\n public get txTotalStat(): TxStat {\n return addStat(addStat(this._txCommittedStat, this._txConflictStat), this._txErrorStat);\n }\n\n public get allTxStat(): AllTxStat {\n return {\n committed: this.txCommittedStat,\n conflict: this.txConflictStat,\n error: this.txErrorStat,\n };\n }\n\n public async ping(): Promise<MaintenanceAPI_Ping_Response> {\n return await this.ll.ping();\n }\n\n public async license(): Promise<MaintenanceAPI_License_Response> {\n return await this.ll.license();\n }\n\n public get conf(): PlClientConfig {\n return this.ll.conf;\n }\n\n public get httpDispatcher(): Dispatcher {\n return this.ll.httpDispatcher;\n }\n\n public get connectionOpts(): WireConnection {\n return this.ll.wireConnection;\n }\n\n private get initialized() {\n return !isNullResourceId(this._clientRoot);\n }\n\n private checkInitialized() {\n if (!this.initialized) throw new Error('Client not initialized');\n }\n\n public get clientRoot(): ResourceId {\n this.checkInitialized();\n return ensureResourceIdNotNull(this._clientRoot);\n }\n\n public get serverInfo(): MaintenanceAPI_Ping_Response {\n this.checkInitialized();\n return this._serverInfo!;\n }\n\n /** Currently implements custom logic to emulate future behaviour with single root. */\n private async init() {\n if (this.initialized) throw new Error('Already initialized');\n\n // Initial client is created without gzip to perform server ping and detect optimal wire protocol.\n // LLPlClient.build() internally calls detectOptimalWireProtocol() which starts with default 'grpc',\n // then retries with 'rest' if ping fails, alternating until a working protocol is found.\n // We save the detected wireProtocol here because if the server supports gzip compression,\n // we'll need to reinitialize the client with gzip enabled - passing the already-detected\n // wireProtocol avoids redundant protocol detection on reinit.\n this._ll = await this.buildLLPlClient(false);\n const wireProtocol = this._ll.wireProtocol;\n\n // calculating reproducible root name from the username\n const user = this._ll.authUser;\n const mainRootName\n = user === null ? AnonymousClientRoot : createHash('sha256').update(user).digest('hex');\n\n this._serverInfo = await this.ping();\n if (this._serverInfo.compression === MaintenanceAPI_Ping_Response_Compression.GZIP) {\n await this._ll.close();\n this._ll = await this.buildLLPlClient(true, wireProtocol);\n }\n\n this._clientRoot = await this._withTx('initialization', true, NullResourceId, async (tx) => {\n let mainRoot: AnyResourceRef;\n\n if (await tx.checkResourceNameExists(mainRootName))\n mainRoot = await tx.getResourceByName(mainRootName);\n else {\n mainRoot = tx.createRoot(ClientRoot);\n tx.setResourceName(mainRootName, mainRoot);\n }\n\n if (this.conf.alternativeRoot === undefined) {\n await tx.commit();\n return await toGlobalResourceId(mainRoot);\n } else {\n const aFId = {\n resourceId: mainRoot,\n fieldName: alternativeRootFieldName(this.conf.alternativeRoot),\n };\n\n const altRoot = tx.createEphemeral(ClientRoot);\n tx.lock(altRoot);\n tx.createField(aFId, 'Dynamic');\n tx.setField(aFId, altRoot);\n await tx.commit();\n\n return await altRoot.globalId;\n }\n });\n }\n\n /** Returns true if field existed */\n public async deleteAlternativeRoot(alternativeRootName: string): Promise<boolean> {\n this.checkInitialized();\n if (this.ll.conf.alternativeRoot !== undefined)\n throw new Error('Initialized with alternative root.');\n return await this.withWriteTx('delete-alternative-root', async (tx) => {\n const fId = {\n resourceId: tx.clientRoot,\n fieldName: alternativeRootFieldName(alternativeRootName),\n };\n const exists = tx.fieldExists(fId);\n tx.removeField(fId);\n await tx.commit();\n return await exists;\n });\n }\n\n private async _withTx<T>(\n name: string,\n writable: boolean,\n clientRoot: OptionalResourceId,\n body: (tx: PlTransaction) => Promise<T>,\n ops?: TxOps,\n ): Promise<T> {\n // for exponential / linear backoff\n let retryState = createRetryState(ops?.retryOptions ?? this.defaultRetryOptions);\n\n while (true) {\n const release = ops?.lockId ? await advisoryLock(ops.lockId) : () => {};\n\n try {\n // opening low-level tx\n const llTx = this.ll.createTx(writable, ops);\n // wrapping it into high-level tx (this also asynchronously sends initialization message)\n const tx = new PlTransaction(\n llTx,\n name,\n writable,\n clientRoot,\n this.finalPredicate,\n this.resourceDataCache,\n );\n\n let ok = false;\n let result: T | undefined = undefined;\n let txId;\n\n try {\n // executing transaction body\n result = await body(tx);\n // collecting stat\n this._txCommittedStat = addStat(this._txCommittedStat, tx.stat);\n ok = true;\n } catch (e: unknown) {\n // the only recoverable\n if (e instanceof TxCommitConflict) {\n // ignoring\n // collecting stat\n this._txConflictStat = addStat(this._txConflictStat, tx.stat);\n } else {\n // collecting stat\n this._txErrorStat = addStat(this._txErrorStat, tx.stat);\n throw e;\n }\n } finally {\n // close underlying grpc stream, if not yet done\n\n // even though we can skip two lines below for read-only transactions,\n // we don't do it to simplify reasoning about what is going on in\n // concurrent code, especially in significant latency situations\n await tx.complete();\n await tx.await();\n\n txId = await tx.getGlobalTxId();\n }\n\n if (ok) {\n // syncing on transaction if requested\n if (ops?.sync === undefined ? this.forceSync : ops?.sync)\n await this.ll.txSync(txId);\n\n // introducing artificial delay, if requested\n if (writable && this.txDelay > 0)\n await tp.setTimeout(this.txDelay, undefined, { signal: ops?.abortSignal });\n\n return result!;\n }\n } finally {\n release();\n }\n\n // we only get here after TxCommitConflict error,\n // all other errors terminate this loop instantly\n\n await tp.setTimeout(retryState.nextDelay, undefined, { signal: ops?.abortSignal });\n retryState = nextRetryStateOrError(retryState);\n }\n }\n\n private async withTx<T>(\n name: string,\n writable: boolean,\n body: (tx: PlTransaction) => Promise<T>,\n ops: Partial<TxOps> = {},\n ): Promise<T> {\n this.checkInitialized();\n return await this._withTx(name, writable, this.clientRoot, body, { ...ops, ...defaultTxOps });\n }\n\n public async withWriteTx<T>(\n name: string,\n body: (tx: PlTransaction) => Promise<T>,\n ops: Partial<TxOps> = {},\n ): Promise<T> {\n return await this.withTx(name, true, body, { ...ops, ...defaultTxOps });\n }\n\n public async withReadTx<T>(\n name: string,\n body: (tx: PlTransaction) => Promise<T>,\n ops: Partial<TxOps> = {},\n ): Promise<T> {\n return await this.withTx(name, false, body, { ...ops, ...defaultTxOps });\n }\n\n public getDriver<Drv extends PlDriver>(definition: PlDriverDefinition<Drv>): Drv {\n const attached = this.drivers.get(definition.name);\n if (attached !== undefined) return attached as Drv;\n const driver = definition.init(this, this.ll, this.httpDispatcher);\n this.drivers.set(definition.name, driver);\n return driver;\n }\n\n /** Closes underlying transport */\n public async close() {\n await this.ll.close();\n }\n\n public static async init(\n configOrAddress: PlClientConfig | string,\n auth: AuthOps,\n ops: {\n statusListener?: PlConnectionStatusListener;\n } = {},\n ) {\n const pl = new PlClient(configOrAddress, auth, ops);\n await pl.init();\n return pl;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -113,7 +113,7 @@ async function defaultPlClient() {
|
|
|
113
113
|
authInformation = cache.authInformation;
|
|
114
114
|
}
|
|
115
115
|
if (authInformation === undefined) {
|
|
116
|
-
const client =
|
|
116
|
+
const client = await unauth_client.UnauthenticatedPlClient.build(config$1);
|
|
117
117
|
if (await client.requireAuth()) {
|
|
118
118
|
if (config$1.user === undefined || config$1.password === undefined)
|
|
119
119
|
throw new Error(`No auth information for found to authenticate with PL server.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default_client.cjs","sources":["../../src/core/default_client.ts"],"sourcesContent":["import fs from 'node:fs';\nimport type { AuthInformation, PlClientConfig } from './config';\nimport { plAddressToConfig } from './config';\nimport canonicalize from 'canonicalize';\nimport YAML from 'yaml';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { notEmpty } from '@milaboratories/ts-helpers';\nimport { UnauthenticatedPlClient } from './unauth_client';\nimport { PlClient } from './client';\nimport { createHash } from 'node:crypto';\nimport { inferAuthRefreshTime } from './auth';\n\nconst CONFIG_FILE_LOCAL_JSON = 'pl.json';\nconst CONFIG_FILE_USER_JSON = path.join(os.homedir(), '.pl.json');\nconst CONFIG_FILE_LOCAL_YAML = 'pl.yaml';\nconst CONFIG_FILE_USER_YAML = path.join(os.homedir(), '.pl.yaml');\nconst CONF_FILE_SEQUENCE = [\n CONFIG_FILE_LOCAL_JSON,\n CONFIG_FILE_LOCAL_YAML,\n CONFIG_FILE_USER_JSON,\n CONFIG_FILE_USER_YAML,\n];\n\nconst AUTH_DATA_FILE = '.pl_auth.json';\n\ntype FileConfigOverrideFields =\n | 'grpcProxy'\n | 'httpProxy'\n | 'user'\n | 'password'\n | 'alternativeRoot'\n | 'defaultROTransactionTimeout'\n | 'defaultRWTransactionTimeout'\n | 'defaultRequestTimeout'\n | 'authTTLSeconds'\n | 'authMaxRefreshSeconds';\nconst FILE_CONFIG_OVERRIDE_FIELDS: FileConfigOverrideFields[] = [\n 'grpcProxy',\n 'httpProxy',\n 'user',\n 'password',\n 'alternativeRoot',\n 'defaultROTransactionTimeout',\n 'defaultRWTransactionTimeout',\n 'defaultRequestTimeout',\n 'authTTLSeconds',\n 'authMaxRefreshSeconds',\n];\n\ntype PlConfigFile = {\n address: string;\n} & Partial<Pick<PlClientConfig, FileConfigOverrideFields>>;\n\ninterface AuthCache {\n /** To check if config changed */\n confHash: string;\n expiration: number;\n authInformation: AuthInformation;\n}\n\nexport function tryGetFileConfig(): [PlConfigFile, string] | undefined {\n for (const confPath of CONF_FILE_SEQUENCE)\n if (fs.existsSync(confPath)) {\n const fileContent = fs.readFileSync(confPath, { encoding: 'utf-8' });\n if (confPath.endsWith('json')) return [JSON.parse(fileContent) as PlConfigFile, confPath];\n else return [YAML.parse(fileContent) as PlConfigFile, confPath];\n }\n return undefined;\n}\n\nfunction saveAuthInfoCallback(\n confHash: string,\n authMaxRefreshSeconds: number,\n): (newAuthInfo: AuthInformation) => void {\n return (newAuthInfo) => {\n fs.writeFileSync(\n AUTH_DATA_FILE,\n Buffer.from(\n JSON.stringify({\n confHash,\n authInformation: newAuthInfo,\n expiration: inferAuthRefreshTime(newAuthInfo, authMaxRefreshSeconds),\n } as AuthCache),\n ),\n 'utf8',\n );\n };\n}\n\nconst cleanAuthInfoCallback = () => {\n fs.rmSync(AUTH_DATA_FILE);\n};\n\n/** Uses default algorithm to construct a pl client from the environment */\nexport async function defaultPlClient(): Promise<PlClient> {\n let config: PlClientConfig | undefined = undefined;\n if (process.env.PL_ADDRESS !== undefined) {\n config = plAddressToConfig(process.env.PL_ADDRESS);\n } else {\n const fromFile = tryGetFileConfig();\n if (fromFile !== undefined) {\n const [fileConfig, configPath] = fromFile;\n const address = notEmpty(fileConfig.address, `no pl address in file: ${configPath}`);\n config = plAddressToConfig(address);\n // applying overrides\n for (const field of FILE_CONFIG_OVERRIDE_FIELDS)\n if (fileConfig[field] !== undefined) (config as any)[field] = fileConfig[field];\n }\n }\n\n if (config === undefined)\n throw new Error('Can\\'t find configuration to create default platform client.');\n\n if (process.env.PL_USER !== undefined) config.user = process.env.PL_USER;\n\n if (process.env.PL_PASSWORD !== undefined) config.user = process.env.PL_PASSWORD;\n\n const confHash = createHash('sha256')\n .update(Buffer.from(canonicalize(config)!))\n .digest('base64');\n\n let authInformation: AuthInformation | undefined = undefined;\n\n // try recover auth information from cache\n if (fs.existsSync(AUTH_DATA_FILE)) {\n const cache: AuthCache = JSON.parse(fs.readFileSync(AUTH_DATA_FILE, { encoding: 'utf-8' }));\n if (cache.confHash === confHash && cache.expiration > Date.now())\n authInformation = cache.authInformation;\n }\n\n if (authInformation === undefined) {\n const client =
|
|
1
|
+
{"version":3,"file":"default_client.cjs","sources":["../../src/core/default_client.ts"],"sourcesContent":["import fs from 'node:fs';\nimport type { AuthInformation, PlClientConfig } from './config';\nimport { plAddressToConfig } from './config';\nimport canonicalize from 'canonicalize';\nimport YAML from 'yaml';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { notEmpty } from '@milaboratories/ts-helpers';\nimport { UnauthenticatedPlClient } from './unauth_client';\nimport { PlClient } from './client';\nimport { createHash } from 'node:crypto';\nimport { inferAuthRefreshTime } from './auth';\n\nconst CONFIG_FILE_LOCAL_JSON = 'pl.json';\nconst CONFIG_FILE_USER_JSON = path.join(os.homedir(), '.pl.json');\nconst CONFIG_FILE_LOCAL_YAML = 'pl.yaml';\nconst CONFIG_FILE_USER_YAML = path.join(os.homedir(), '.pl.yaml');\nconst CONF_FILE_SEQUENCE = [\n CONFIG_FILE_LOCAL_JSON,\n CONFIG_FILE_LOCAL_YAML,\n CONFIG_FILE_USER_JSON,\n CONFIG_FILE_USER_YAML,\n];\n\nconst AUTH_DATA_FILE = '.pl_auth.json';\n\ntype FileConfigOverrideFields =\n | 'grpcProxy'\n | 'httpProxy'\n | 'user'\n | 'password'\n | 'alternativeRoot'\n | 'defaultROTransactionTimeout'\n | 'defaultRWTransactionTimeout'\n | 'defaultRequestTimeout'\n | 'authTTLSeconds'\n | 'authMaxRefreshSeconds';\nconst FILE_CONFIG_OVERRIDE_FIELDS: FileConfigOverrideFields[] = [\n 'grpcProxy',\n 'httpProxy',\n 'user',\n 'password',\n 'alternativeRoot',\n 'defaultROTransactionTimeout',\n 'defaultRWTransactionTimeout',\n 'defaultRequestTimeout',\n 'authTTLSeconds',\n 'authMaxRefreshSeconds',\n];\n\ntype PlConfigFile = {\n address: string;\n} & Partial<Pick<PlClientConfig, FileConfigOverrideFields>>;\n\ninterface AuthCache {\n /** To check if config changed */\n confHash: string;\n expiration: number;\n authInformation: AuthInformation;\n}\n\nexport function tryGetFileConfig(): [PlConfigFile, string] | undefined {\n for (const confPath of CONF_FILE_SEQUENCE)\n if (fs.existsSync(confPath)) {\n const fileContent = fs.readFileSync(confPath, { encoding: 'utf-8' });\n if (confPath.endsWith('json')) return [JSON.parse(fileContent) as PlConfigFile, confPath];\n else return [YAML.parse(fileContent) as PlConfigFile, confPath];\n }\n return undefined;\n}\n\nfunction saveAuthInfoCallback(\n confHash: string,\n authMaxRefreshSeconds: number,\n): (newAuthInfo: AuthInformation) => void {\n return (newAuthInfo) => {\n fs.writeFileSync(\n AUTH_DATA_FILE,\n Buffer.from(\n JSON.stringify({\n confHash,\n authInformation: newAuthInfo,\n expiration: inferAuthRefreshTime(newAuthInfo, authMaxRefreshSeconds),\n } as AuthCache),\n ),\n 'utf8',\n );\n };\n}\n\nconst cleanAuthInfoCallback = () => {\n fs.rmSync(AUTH_DATA_FILE);\n};\n\n/** Uses default algorithm to construct a pl client from the environment */\nexport async function defaultPlClient(): Promise<PlClient> {\n let config: PlClientConfig | undefined = undefined;\n if (process.env.PL_ADDRESS !== undefined) {\n config = plAddressToConfig(process.env.PL_ADDRESS);\n } else {\n const fromFile = tryGetFileConfig();\n if (fromFile !== undefined) {\n const [fileConfig, configPath] = fromFile;\n const address = notEmpty(fileConfig.address, `no pl address in file: ${configPath}`);\n config = plAddressToConfig(address);\n // applying overrides\n for (const field of FILE_CONFIG_OVERRIDE_FIELDS)\n if (fileConfig[field] !== undefined) (config as any)[field] = fileConfig[field];\n }\n }\n\n if (config === undefined)\n throw new Error('Can\\'t find configuration to create default platform client.');\n\n if (process.env.PL_USER !== undefined) config.user = process.env.PL_USER;\n\n if (process.env.PL_PASSWORD !== undefined) config.user = process.env.PL_PASSWORD;\n\n const confHash = createHash('sha256')\n .update(Buffer.from(canonicalize(config)!))\n .digest('base64');\n\n let authInformation: AuthInformation | undefined = undefined;\n\n // try recover auth information from cache\n if (fs.existsSync(AUTH_DATA_FILE)) {\n const cache: AuthCache = JSON.parse(fs.readFileSync(AUTH_DATA_FILE, { encoding: 'utf-8' }));\n if (cache.confHash === confHash && cache.expiration > Date.now())\n authInformation = cache.authInformation;\n }\n\n if (authInformation === undefined) {\n const client = await UnauthenticatedPlClient.build(config);\n\n if (await client.requireAuth()) {\n if (config.user === undefined || config.password === undefined)\n throw new Error(`No auth information for found to authenticate with PL server.`);\n authInformation = await client.login(config.user, config.password);\n } else {\n // No authorization is required\n authInformation = {};\n }\n\n // saving cache\n fs.writeFileSync(\n AUTH_DATA_FILE,\n Buffer.from(\n JSON.stringify({\n confHash,\n authInformation,\n expiration: inferAuthRefreshTime(authInformation, config.authMaxRefreshSeconds),\n } as AuthCache),\n ),\n 'utf8',\n );\n }\n\n return await PlClient.init(config, {\n authInformation,\n onUpdate: (_newAuthInfo) => saveAuthInfoCallback(confHash, config.authMaxRefreshSeconds),\n onUpdateError: cleanAuthInfoCallback,\n onAuthError: cleanAuthInfoCallback,\n });\n}\n"],"names":["path","os","inferAuthRefreshTime","config","plAddressToConfig","notEmpty","createHash","UnauthenticatedPlClient","PlClient"],"mappings":"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"}
|
|
@@ -91,7 +91,7 @@ async function defaultPlClient() {
|
|
|
91
91
|
authInformation = cache.authInformation;
|
|
92
92
|
}
|
|
93
93
|
if (authInformation === undefined) {
|
|
94
|
-
const client =
|
|
94
|
+
const client = await UnauthenticatedPlClient.build(config);
|
|
95
95
|
if (await client.requireAuth()) {
|
|
96
96
|
if (config.user === undefined || config.password === undefined)
|
|
97
97
|
throw new Error(`No auth information for found to authenticate with PL server.`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"default_client.js","sources":["../../src/core/default_client.ts"],"sourcesContent":["import fs from 'node:fs';\nimport type { AuthInformation, PlClientConfig } from './config';\nimport { plAddressToConfig } from './config';\nimport canonicalize from 'canonicalize';\nimport YAML from 'yaml';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { notEmpty } from '@milaboratories/ts-helpers';\nimport { UnauthenticatedPlClient } from './unauth_client';\nimport { PlClient } from './client';\nimport { createHash } from 'node:crypto';\nimport { inferAuthRefreshTime } from './auth';\n\nconst CONFIG_FILE_LOCAL_JSON = 'pl.json';\nconst CONFIG_FILE_USER_JSON = path.join(os.homedir(), '.pl.json');\nconst CONFIG_FILE_LOCAL_YAML = 'pl.yaml';\nconst CONFIG_FILE_USER_YAML = path.join(os.homedir(), '.pl.yaml');\nconst CONF_FILE_SEQUENCE = [\n CONFIG_FILE_LOCAL_JSON,\n CONFIG_FILE_LOCAL_YAML,\n CONFIG_FILE_USER_JSON,\n CONFIG_FILE_USER_YAML,\n];\n\nconst AUTH_DATA_FILE = '.pl_auth.json';\n\ntype FileConfigOverrideFields =\n | 'grpcProxy'\n | 'httpProxy'\n | 'user'\n | 'password'\n | 'alternativeRoot'\n | 'defaultROTransactionTimeout'\n | 'defaultRWTransactionTimeout'\n | 'defaultRequestTimeout'\n | 'authTTLSeconds'\n | 'authMaxRefreshSeconds';\nconst FILE_CONFIG_OVERRIDE_FIELDS: FileConfigOverrideFields[] = [\n 'grpcProxy',\n 'httpProxy',\n 'user',\n 'password',\n 'alternativeRoot',\n 'defaultROTransactionTimeout',\n 'defaultRWTransactionTimeout',\n 'defaultRequestTimeout',\n 'authTTLSeconds',\n 'authMaxRefreshSeconds',\n];\n\ntype PlConfigFile = {\n address: string;\n} & Partial<Pick<PlClientConfig, FileConfigOverrideFields>>;\n\ninterface AuthCache {\n /** To check if config changed */\n confHash: string;\n expiration: number;\n authInformation: AuthInformation;\n}\n\nexport function tryGetFileConfig(): [PlConfigFile, string] | undefined {\n for (const confPath of CONF_FILE_SEQUENCE)\n if (fs.existsSync(confPath)) {\n const fileContent = fs.readFileSync(confPath, { encoding: 'utf-8' });\n if (confPath.endsWith('json')) return [JSON.parse(fileContent) as PlConfigFile, confPath];\n else return [YAML.parse(fileContent) as PlConfigFile, confPath];\n }\n return undefined;\n}\n\nfunction saveAuthInfoCallback(\n confHash: string,\n authMaxRefreshSeconds: number,\n): (newAuthInfo: AuthInformation) => void {\n return (newAuthInfo) => {\n fs.writeFileSync(\n AUTH_DATA_FILE,\n Buffer.from(\n JSON.stringify({\n confHash,\n authInformation: newAuthInfo,\n expiration: inferAuthRefreshTime(newAuthInfo, authMaxRefreshSeconds),\n } as AuthCache),\n ),\n 'utf8',\n );\n };\n}\n\nconst cleanAuthInfoCallback = () => {\n fs.rmSync(AUTH_DATA_FILE);\n};\n\n/** Uses default algorithm to construct a pl client from the environment */\nexport async function defaultPlClient(): Promise<PlClient> {\n let config: PlClientConfig | undefined = undefined;\n if (process.env.PL_ADDRESS !== undefined) {\n config = plAddressToConfig(process.env.PL_ADDRESS);\n } else {\n const fromFile = tryGetFileConfig();\n if (fromFile !== undefined) {\n const [fileConfig, configPath] = fromFile;\n const address = notEmpty(fileConfig.address, `no pl address in file: ${configPath}`);\n config = plAddressToConfig(address);\n // applying overrides\n for (const field of FILE_CONFIG_OVERRIDE_FIELDS)\n if (fileConfig[field] !== undefined) (config as any)[field] = fileConfig[field];\n }\n }\n\n if (config === undefined)\n throw new Error('Can\\'t find configuration to create default platform client.');\n\n if (process.env.PL_USER !== undefined) config.user = process.env.PL_USER;\n\n if (process.env.PL_PASSWORD !== undefined) config.user = process.env.PL_PASSWORD;\n\n const confHash = createHash('sha256')\n .update(Buffer.from(canonicalize(config)!))\n .digest('base64');\n\n let authInformation: AuthInformation | undefined = undefined;\n\n // try recover auth information from cache\n if (fs.existsSync(AUTH_DATA_FILE)) {\n const cache: AuthCache = JSON.parse(fs.readFileSync(AUTH_DATA_FILE, { encoding: 'utf-8' }));\n if (cache.confHash === confHash && cache.expiration > Date.now())\n authInformation = cache.authInformation;\n }\n\n if (authInformation === undefined) {\n const client =
|
|
1
|
+
{"version":3,"file":"default_client.js","sources":["../../src/core/default_client.ts"],"sourcesContent":["import fs from 'node:fs';\nimport type { AuthInformation, PlClientConfig } from './config';\nimport { plAddressToConfig } from './config';\nimport canonicalize from 'canonicalize';\nimport YAML from 'yaml';\nimport * as os from 'node:os';\nimport * as path from 'node:path';\nimport { notEmpty } from '@milaboratories/ts-helpers';\nimport { UnauthenticatedPlClient } from './unauth_client';\nimport { PlClient } from './client';\nimport { createHash } from 'node:crypto';\nimport { inferAuthRefreshTime } from './auth';\n\nconst CONFIG_FILE_LOCAL_JSON = 'pl.json';\nconst CONFIG_FILE_USER_JSON = path.join(os.homedir(), '.pl.json');\nconst CONFIG_FILE_LOCAL_YAML = 'pl.yaml';\nconst CONFIG_FILE_USER_YAML = path.join(os.homedir(), '.pl.yaml');\nconst CONF_FILE_SEQUENCE = [\n CONFIG_FILE_LOCAL_JSON,\n CONFIG_FILE_LOCAL_YAML,\n CONFIG_FILE_USER_JSON,\n CONFIG_FILE_USER_YAML,\n];\n\nconst AUTH_DATA_FILE = '.pl_auth.json';\n\ntype FileConfigOverrideFields =\n | 'grpcProxy'\n | 'httpProxy'\n | 'user'\n | 'password'\n | 'alternativeRoot'\n | 'defaultROTransactionTimeout'\n | 'defaultRWTransactionTimeout'\n | 'defaultRequestTimeout'\n | 'authTTLSeconds'\n | 'authMaxRefreshSeconds';\nconst FILE_CONFIG_OVERRIDE_FIELDS: FileConfigOverrideFields[] = [\n 'grpcProxy',\n 'httpProxy',\n 'user',\n 'password',\n 'alternativeRoot',\n 'defaultROTransactionTimeout',\n 'defaultRWTransactionTimeout',\n 'defaultRequestTimeout',\n 'authTTLSeconds',\n 'authMaxRefreshSeconds',\n];\n\ntype PlConfigFile = {\n address: string;\n} & Partial<Pick<PlClientConfig, FileConfigOverrideFields>>;\n\ninterface AuthCache {\n /** To check if config changed */\n confHash: string;\n expiration: number;\n authInformation: AuthInformation;\n}\n\nexport function tryGetFileConfig(): [PlConfigFile, string] | undefined {\n for (const confPath of CONF_FILE_SEQUENCE)\n if (fs.existsSync(confPath)) {\n const fileContent = fs.readFileSync(confPath, { encoding: 'utf-8' });\n if (confPath.endsWith('json')) return [JSON.parse(fileContent) as PlConfigFile, confPath];\n else return [YAML.parse(fileContent) as PlConfigFile, confPath];\n }\n return undefined;\n}\n\nfunction saveAuthInfoCallback(\n confHash: string,\n authMaxRefreshSeconds: number,\n): (newAuthInfo: AuthInformation) => void {\n return (newAuthInfo) => {\n fs.writeFileSync(\n AUTH_DATA_FILE,\n Buffer.from(\n JSON.stringify({\n confHash,\n authInformation: newAuthInfo,\n expiration: inferAuthRefreshTime(newAuthInfo, authMaxRefreshSeconds),\n } as AuthCache),\n ),\n 'utf8',\n );\n };\n}\n\nconst cleanAuthInfoCallback = () => {\n fs.rmSync(AUTH_DATA_FILE);\n};\n\n/** Uses default algorithm to construct a pl client from the environment */\nexport async function defaultPlClient(): Promise<PlClient> {\n let config: PlClientConfig | undefined = undefined;\n if (process.env.PL_ADDRESS !== undefined) {\n config = plAddressToConfig(process.env.PL_ADDRESS);\n } else {\n const fromFile = tryGetFileConfig();\n if (fromFile !== undefined) {\n const [fileConfig, configPath] = fromFile;\n const address = notEmpty(fileConfig.address, `no pl address in file: ${configPath}`);\n config = plAddressToConfig(address);\n // applying overrides\n for (const field of FILE_CONFIG_OVERRIDE_FIELDS)\n if (fileConfig[field] !== undefined) (config as any)[field] = fileConfig[field];\n }\n }\n\n if (config === undefined)\n throw new Error('Can\\'t find configuration to create default platform client.');\n\n if (process.env.PL_USER !== undefined) config.user = process.env.PL_USER;\n\n if (process.env.PL_PASSWORD !== undefined) config.user = process.env.PL_PASSWORD;\n\n const confHash = createHash('sha256')\n .update(Buffer.from(canonicalize(config)!))\n .digest('base64');\n\n let authInformation: AuthInformation | undefined = undefined;\n\n // try recover auth information from cache\n if (fs.existsSync(AUTH_DATA_FILE)) {\n const cache: AuthCache = JSON.parse(fs.readFileSync(AUTH_DATA_FILE, { encoding: 'utf-8' }));\n if (cache.confHash === confHash && cache.expiration > Date.now())\n authInformation = cache.authInformation;\n }\n\n if (authInformation === undefined) {\n const client = await UnauthenticatedPlClient.build(config);\n\n if (await client.requireAuth()) {\n if (config.user === undefined || config.password === undefined)\n throw new Error(`No auth information for found to authenticate with PL server.`);\n authInformation = await client.login(config.user, config.password);\n } else {\n // No authorization is required\n authInformation = {};\n }\n\n // saving cache\n fs.writeFileSync(\n AUTH_DATA_FILE,\n Buffer.from(\n JSON.stringify({\n confHash,\n authInformation,\n expiration: inferAuthRefreshTime(authInformation, config.authMaxRefreshSeconds),\n } as AuthCache),\n ),\n 'utf8',\n );\n }\n\n return await PlClient.init(config, {\n authInformation,\n onUpdate: (_newAuthInfo) => saveAuthInfoCallback(confHash, config.authMaxRefreshSeconds),\n onUpdateError: cleanAuthInfoCallback,\n onAuthError: cleanAuthInfoCallback,\n });\n}\n"],"names":["fs"],"mappings":"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"}
|
package/dist/core/errors.cjs
CHANGED
|
@@ -34,6 +34,9 @@ function isTimeoutOrCancelError(err, nested = false) {
|
|
|
34
34
|
return true;
|
|
35
35
|
if (err.code == 'ABORT_ERR')
|
|
36
36
|
return true;
|
|
37
|
+
// Check for DOMException with ABORT_ERR code (thrown by AbortSignal.timeout)
|
|
38
|
+
if (err instanceof DOMException && err.code === DOMException.ABORT_ERR)
|
|
39
|
+
return true;
|
|
37
40
|
if (err.code == code.Code.ABORTED)
|
|
38
41
|
return true;
|
|
39
42
|
if (err.name == 'RpcError'
|
|
@@ -90,14 +93,22 @@ class DisconnectedError extends Error {
|
|
|
90
93
|
}
|
|
91
94
|
}
|
|
92
95
|
function rethrowMeaningfulError(error, wrapIfUnknown = false) {
|
|
93
|
-
if (isUnauthenticated(error))
|
|
96
|
+
if (isUnauthenticated(error)) {
|
|
97
|
+
if (error instanceof UnauthenticatedError)
|
|
98
|
+
throw error;
|
|
94
99
|
throw new UnauthenticatedError(error.message);
|
|
95
|
-
|
|
100
|
+
}
|
|
101
|
+
if (isConnectionProblem(error)) {
|
|
102
|
+
if (error instanceof DisconnectedError)
|
|
103
|
+
throw error;
|
|
96
104
|
throw new DisconnectedError(error.message);
|
|
105
|
+
}
|
|
97
106
|
if (isTimeoutOrCancelError(error))
|
|
98
107
|
throw new tsHelpers.Aborted(error);
|
|
99
|
-
if (wrapIfUnknown)
|
|
100
|
-
|
|
108
|
+
if (wrapIfUnknown) {
|
|
109
|
+
const message = error.message || String(error) || 'Unknown error';
|
|
110
|
+
throw new Error(message, { cause: error });
|
|
111
|
+
}
|
|
101
112
|
else
|
|
102
113
|
throw error;
|
|
103
114
|
}
|
package/dist/core/errors.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.cjs","sources":["../../src/core/errors.ts"],"sourcesContent":["import type { Status } from '../proto-grpc/github.com/googleapis/googleapis/google/rpc/status';\nimport { Aborted } from '@milaboratories/ts-helpers';\nimport { Code } from '../proto-grpc/google/rpc/code';\n\nexport function isConnectionProblem(err: unknown, nested: boolean = false): boolean {\n if (err instanceof DisconnectedError) return true;\n if ((err as any).name == 'RpcError' && (err as any).code == 'UNAVAILABLE') return true;\n if ((err as any).code == Code.UNAVAILABLE) return true;\n if ((err as any).cause !== undefined && !nested)\n // nested limits the depth of search\n return isConnectionProblem((err as any).cause, true);\n return false;\n}\n\nexport function isUnauthenticated(err: unknown, nested: boolean = false): boolean {\n if (err instanceof UnauthenticatedError) return true;\n if ((err as any).name == 'RpcError' && (err as any).code == 'UNAUTHENTICATED') return true;\n if ((err as any).code == Code.UNAUTHENTICATED) return true;\n if ((err as any).cause !== undefined && !nested)\n // nested limits the depth of search\n return isUnauthenticated((err as any).cause, true);\n return false;\n}\n\nexport function isTimeoutOrCancelError(err: unknown, nested: boolean = false): boolean {\n if (err instanceof Aborted || (err as any).name == 'AbortError') return true;\n if ((err as any).name == 'TimeoutError') return true;\n if ((err as any).code == 'ABORT_ERR') return true;\n if ((err as any).code == Code.ABORTED) return true;\n if (\n (err as any).name == 'RpcError'\n && ((err as any).code == 'CANCELLED' || (err as any).code == 'DEADLINE_EXCEEDED')\n )\n return true;\n if ((err as any).code == Code.CANCELLED || (err as any).code == Code.DEADLINE_EXCEEDED)\n return true;\n if ((err as any).cause !== undefined && !nested)\n // nested limits the depth of search\n return isTimeoutOrCancelError((err as any).cause, true);\n return false;\n}\n\nexport const PlErrorCodeNotFound = 5;\n\nexport class PlError extends Error {\n name = 'PlError';\n constructor(public readonly status: Status) {\n super(`code=${status.code} ${status.message}`);\n }\n}\n\nexport function throwPlNotFoundError(message: string): never {\n throw new RecoverablePlError({ code: PlErrorCodeNotFound, message, details: [] });\n}\n\nexport class RecoverablePlError extends PlError {\n name = 'RecoverablePlError';\n constructor(status: Status) {\n super(status);\n }\n}\n\nexport class UnrecoverablePlError extends PlError {\n name = 'UnrecoverablePlError';\n constructor(status: Status) {\n super(status);\n }\n}\n\nexport function isNotFoundError(err: unknown, nested: boolean = false): boolean {\n if ((err as any).name == 'RpcError' && (err as any).code == 'NOT_FOUND') return true;\n if ((err as any).cause !== undefined && !nested) return isNotFoundError((err as any).cause, true);\n return err instanceof RecoverablePlError && err.status.code === PlErrorCodeNotFound;\n}\n\nexport class UnauthenticatedError extends Error {\n name = 'UnauthenticatedError';\n constructor(message: string) {\n super('LoginFailed: ' + message);\n }\n}\n\nexport class DisconnectedError extends Error {\n name = 'DisconnectedError';\n constructor(message: string) {\n super('Disconnected: ' + message);\n }\n}\n\nexport function rethrowMeaningfulError(error: any, wrapIfUnknown: boolean = false): never {\n if (isUnauthenticated(error)) throw new UnauthenticatedError(error.message);\n if (isConnectionProblem(error)) throw new DisconnectedError(error.message);\n if (isTimeoutOrCancelError(error)) throw new Aborted(error);\n if (wrapIfUnknown) throw new Error(
|
|
1
|
+
{"version":3,"file":"errors.cjs","sources":["../../src/core/errors.ts"],"sourcesContent":["import type { Status } from '../proto-grpc/github.com/googleapis/googleapis/google/rpc/status';\nimport { Aborted } from '@milaboratories/ts-helpers';\nimport { Code } from '../proto-grpc/google/rpc/code';\n\nexport function isConnectionProblem(err: unknown, nested: boolean = false): boolean {\n if (err instanceof DisconnectedError) return true;\n if ((err as any).name == 'RpcError' && (err as any).code == 'UNAVAILABLE') return true;\n if ((err as any).code == Code.UNAVAILABLE) return true;\n if ((err as any).cause !== undefined && !nested)\n // nested limits the depth of search\n return isConnectionProblem((err as any).cause, true);\n return false;\n}\n\nexport function isUnauthenticated(err: unknown, nested: boolean = false): boolean {\n if (err instanceof UnauthenticatedError) return true;\n if ((err as any).name == 'RpcError' && (err as any).code == 'UNAUTHENTICATED') return true;\n if ((err as any).code == Code.UNAUTHENTICATED) return true;\n if ((err as any).cause !== undefined && !nested)\n // nested limits the depth of search\n return isUnauthenticated((err as any).cause, true);\n return false;\n}\n\nexport function isTimeoutOrCancelError(err: unknown, nested: boolean = false): boolean {\n if (err instanceof Aborted || (err as any).name == 'AbortError') return true;\n if ((err as any).name == 'TimeoutError') return true;\n if ((err as any).code == 'ABORT_ERR') return true;\n // Check for DOMException with ABORT_ERR code (thrown by AbortSignal.timeout)\n if (err instanceof DOMException && err.code === DOMException.ABORT_ERR) return true;\n if ((err as any).code == Code.ABORTED) return true;\n if (\n (err as any).name == 'RpcError'\n && ((err as any).code == 'CANCELLED' || (err as any).code == 'DEADLINE_EXCEEDED')\n )\n return true;\n if ((err as any).code == Code.CANCELLED || (err as any).code == Code.DEADLINE_EXCEEDED)\n return true;\n if ((err as any).cause !== undefined && !nested)\n // nested limits the depth of search\n return isTimeoutOrCancelError((err as any).cause, true);\n return false;\n}\n\nexport const PlErrorCodeNotFound = 5;\n\nexport class PlError extends Error {\n name = 'PlError';\n constructor(public readonly status: Status) {\n super(`code=${status.code} ${status.message}`);\n }\n}\n\nexport function throwPlNotFoundError(message: string): never {\n throw new RecoverablePlError({ code: PlErrorCodeNotFound, message, details: [] });\n}\n\nexport class RecoverablePlError extends PlError {\n name = 'RecoverablePlError';\n constructor(status: Status) {\n super(status);\n }\n}\n\nexport class UnrecoverablePlError extends PlError {\n name = 'UnrecoverablePlError';\n constructor(status: Status) {\n super(status);\n }\n}\n\nexport function isNotFoundError(err: unknown, nested: boolean = false): boolean {\n if ((err as any).name == 'RpcError' && (err as any).code == 'NOT_FOUND') return true;\n if ((err as any).cause !== undefined && !nested) return isNotFoundError((err as any).cause, true);\n return err instanceof RecoverablePlError && err.status.code === PlErrorCodeNotFound;\n}\n\nexport class UnauthenticatedError extends Error {\n name = 'UnauthenticatedError';\n constructor(message: string) {\n super('LoginFailed: ' + message);\n }\n}\n\nexport class DisconnectedError extends Error {\n name = 'DisconnectedError';\n constructor(message: string) {\n super('Disconnected: ' + message);\n }\n}\n\nexport function rethrowMeaningfulError(error: any, wrapIfUnknown: boolean = false): never {\n if (isUnauthenticated(error)) {\n if (error instanceof UnauthenticatedError) throw error;\n throw new UnauthenticatedError(error.message);\n }\n if (isConnectionProblem(error)) {\n if (error instanceof DisconnectedError) throw error;\n throw new DisconnectedError(error.message);\n }\n if (isTimeoutOrCancelError(error)) throw new Aborted(error);\n if (wrapIfUnknown) {\n const message = error.message || String(error) || 'Unknown error';\n throw new Error(message, { cause: error });\n } else throw error;\n}\n"],"names":["Code","Aborted"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kEAAkE,CAAC;AAI/F,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,OAAe,GAAG,OAAO,CAQlF;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,OAAe,GAAG,OAAO,CAQhF;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,OAAe,GAAG,OAAO,
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kEAAkE,CAAC;AAI/F,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,OAAe,GAAG,OAAO,CAQlF;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,OAAe,GAAG,OAAO,CAQhF;AAED,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,OAAe,GAAG,OAAO,CAkBrF;AAED,eAAO,MAAM,mBAAmB,IAAI,CAAC;AAErC,qBAAa,OAAQ,SAAQ,KAAK;aAEJ,MAAM,EAAE,MAAM;IAD1C,IAAI,SAAa;gBACW,MAAM,EAAE,MAAM;CAG3C;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,CAE3D;AAED,qBAAa,kBAAmB,SAAQ,OAAO;IAC7C,IAAI,SAAwB;gBAChB,MAAM,EAAE,MAAM;CAG3B;AAED,qBAAa,oBAAqB,SAAQ,OAAO;IAC/C,IAAI,SAA0B;gBAClB,MAAM,EAAE,MAAM;CAG3B;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,OAAe,GAAG,OAAO,CAI9E;AAED,qBAAa,oBAAqB,SAAQ,KAAK;IAC7C,IAAI,SAA0B;gBAClB,OAAO,EAAE,MAAM;CAG5B;AAED,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,IAAI,SAAuB;gBACf,OAAO,EAAE,MAAM;CAG5B;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,GAAG,EAAE,aAAa,GAAE,OAAe,GAAG,KAAK,CAcxF"}
|
package/dist/core/errors.js
CHANGED
|
@@ -32,6 +32,9 @@ function isTimeoutOrCancelError(err, nested = false) {
|
|
|
32
32
|
return true;
|
|
33
33
|
if (err.code == 'ABORT_ERR')
|
|
34
34
|
return true;
|
|
35
|
+
// Check for DOMException with ABORT_ERR code (thrown by AbortSignal.timeout)
|
|
36
|
+
if (err instanceof DOMException && err.code === DOMException.ABORT_ERR)
|
|
37
|
+
return true;
|
|
35
38
|
if (err.code == Code.ABORTED)
|
|
36
39
|
return true;
|
|
37
40
|
if (err.name == 'RpcError'
|
|
@@ -88,14 +91,22 @@ class DisconnectedError extends Error {
|
|
|
88
91
|
}
|
|
89
92
|
}
|
|
90
93
|
function rethrowMeaningfulError(error, wrapIfUnknown = false) {
|
|
91
|
-
if (isUnauthenticated(error))
|
|
94
|
+
if (isUnauthenticated(error)) {
|
|
95
|
+
if (error instanceof UnauthenticatedError)
|
|
96
|
+
throw error;
|
|
92
97
|
throw new UnauthenticatedError(error.message);
|
|
93
|
-
|
|
98
|
+
}
|
|
99
|
+
if (isConnectionProblem(error)) {
|
|
100
|
+
if (error instanceof DisconnectedError)
|
|
101
|
+
throw error;
|
|
94
102
|
throw new DisconnectedError(error.message);
|
|
103
|
+
}
|
|
95
104
|
if (isTimeoutOrCancelError(error))
|
|
96
105
|
throw new Aborted(error);
|
|
97
|
-
if (wrapIfUnknown)
|
|
98
|
-
|
|
106
|
+
if (wrapIfUnknown) {
|
|
107
|
+
const message = error.message || String(error) || 'Unknown error';
|
|
108
|
+
throw new Error(message, { cause: error });
|
|
109
|
+
}
|
|
99
110
|
else
|
|
100
111
|
throw error;
|
|
101
112
|
}
|
package/dist/core/errors.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"errors.js","sources":["../../src/core/errors.ts"],"sourcesContent":["import type { Status } from '../proto-grpc/github.com/googleapis/googleapis/google/rpc/status';\nimport { Aborted } from '@milaboratories/ts-helpers';\nimport { Code } from '../proto-grpc/google/rpc/code';\n\nexport function isConnectionProblem(err: unknown, nested: boolean = false): boolean {\n if (err instanceof DisconnectedError) return true;\n if ((err as any).name == 'RpcError' && (err as any).code == 'UNAVAILABLE') return true;\n if ((err as any).code == Code.UNAVAILABLE) return true;\n if ((err as any).cause !== undefined && !nested)\n // nested limits the depth of search\n return isConnectionProblem((err as any).cause, true);\n return false;\n}\n\nexport function isUnauthenticated(err: unknown, nested: boolean = false): boolean {\n if (err instanceof UnauthenticatedError) return true;\n if ((err as any).name == 'RpcError' && (err as any).code == 'UNAUTHENTICATED') return true;\n if ((err as any).code == Code.UNAUTHENTICATED) return true;\n if ((err as any).cause !== undefined && !nested)\n // nested limits the depth of search\n return isUnauthenticated((err as any).cause, true);\n return false;\n}\n\nexport function isTimeoutOrCancelError(err: unknown, nested: boolean = false): boolean {\n if (err instanceof Aborted || (err as any).name == 'AbortError') return true;\n if ((err as any).name == 'TimeoutError') return true;\n if ((err as any).code == 'ABORT_ERR') return true;\n if ((err as any).code == Code.ABORTED) return true;\n if (\n (err as any).name == 'RpcError'\n && ((err as any).code == 'CANCELLED' || (err as any).code == 'DEADLINE_EXCEEDED')\n )\n return true;\n if ((err as any).code == Code.CANCELLED || (err as any).code == Code.DEADLINE_EXCEEDED)\n return true;\n if ((err as any).cause !== undefined && !nested)\n // nested limits the depth of search\n return isTimeoutOrCancelError((err as any).cause, true);\n return false;\n}\n\nexport const PlErrorCodeNotFound = 5;\n\nexport class PlError extends Error {\n name = 'PlError';\n constructor(public readonly status: Status) {\n super(`code=${status.code} ${status.message}`);\n }\n}\n\nexport function throwPlNotFoundError(message: string): never {\n throw new RecoverablePlError({ code: PlErrorCodeNotFound, message, details: [] });\n}\n\nexport class RecoverablePlError extends PlError {\n name = 'RecoverablePlError';\n constructor(status: Status) {\n super(status);\n }\n}\n\nexport class UnrecoverablePlError extends PlError {\n name = 'UnrecoverablePlError';\n constructor(status: Status) {\n super(status);\n }\n}\n\nexport function isNotFoundError(err: unknown, nested: boolean = false): boolean {\n if ((err as any).name == 'RpcError' && (err as any).code == 'NOT_FOUND') return true;\n if ((err as any).cause !== undefined && !nested) return isNotFoundError((err as any).cause, true);\n return err instanceof RecoverablePlError && err.status.code === PlErrorCodeNotFound;\n}\n\nexport class UnauthenticatedError extends Error {\n name = 'UnauthenticatedError';\n constructor(message: string) {\n super('LoginFailed: ' + message);\n }\n}\n\nexport class DisconnectedError extends Error {\n name = 'DisconnectedError';\n constructor(message: string) {\n super('Disconnected: ' + message);\n }\n}\n\nexport function rethrowMeaningfulError(error: any, wrapIfUnknown: boolean = false): never {\n if (isUnauthenticated(error)) throw new UnauthenticatedError(error.message);\n if (isConnectionProblem(error)) throw new DisconnectedError(error.message);\n if (isTimeoutOrCancelError(error)) throw new Aborted(error);\n if (wrapIfUnknown) throw new Error(
|
|
1
|
+
{"version":3,"file":"errors.js","sources":["../../src/core/errors.ts"],"sourcesContent":["import type { Status } from '../proto-grpc/github.com/googleapis/googleapis/google/rpc/status';\nimport { Aborted } from '@milaboratories/ts-helpers';\nimport { Code } from '../proto-grpc/google/rpc/code';\n\nexport function isConnectionProblem(err: unknown, nested: boolean = false): boolean {\n if (err instanceof DisconnectedError) return true;\n if ((err as any).name == 'RpcError' && (err as any).code == 'UNAVAILABLE') return true;\n if ((err as any).code == Code.UNAVAILABLE) return true;\n if ((err as any).cause !== undefined && !nested)\n // nested limits the depth of search\n return isConnectionProblem((err as any).cause, true);\n return false;\n}\n\nexport function isUnauthenticated(err: unknown, nested: boolean = false): boolean {\n if (err instanceof UnauthenticatedError) return true;\n if ((err as any).name == 'RpcError' && (err as any).code == 'UNAUTHENTICATED') return true;\n if ((err as any).code == Code.UNAUTHENTICATED) return true;\n if ((err as any).cause !== undefined && !nested)\n // nested limits the depth of search\n return isUnauthenticated((err as any).cause, true);\n return false;\n}\n\nexport function isTimeoutOrCancelError(err: unknown, nested: boolean = false): boolean {\n if (err instanceof Aborted || (err as any).name == 'AbortError') return true;\n if ((err as any).name == 'TimeoutError') return true;\n if ((err as any).code == 'ABORT_ERR') return true;\n // Check for DOMException with ABORT_ERR code (thrown by AbortSignal.timeout)\n if (err instanceof DOMException && err.code === DOMException.ABORT_ERR) return true;\n if ((err as any).code == Code.ABORTED) return true;\n if (\n (err as any).name == 'RpcError'\n && ((err as any).code == 'CANCELLED' || (err as any).code == 'DEADLINE_EXCEEDED')\n )\n return true;\n if ((err as any).code == Code.CANCELLED || (err as any).code == Code.DEADLINE_EXCEEDED)\n return true;\n if ((err as any).cause !== undefined && !nested)\n // nested limits the depth of search\n return isTimeoutOrCancelError((err as any).cause, true);\n return false;\n}\n\nexport const PlErrorCodeNotFound = 5;\n\nexport class PlError extends Error {\n name = 'PlError';\n constructor(public readonly status: Status) {\n super(`code=${status.code} ${status.message}`);\n }\n}\n\nexport function throwPlNotFoundError(message: string): never {\n throw new RecoverablePlError({ code: PlErrorCodeNotFound, message, details: [] });\n}\n\nexport class RecoverablePlError extends PlError {\n name = 'RecoverablePlError';\n constructor(status: Status) {\n super(status);\n }\n}\n\nexport class UnrecoverablePlError extends PlError {\n name = 'UnrecoverablePlError';\n constructor(status: Status) {\n super(status);\n }\n}\n\nexport function isNotFoundError(err: unknown, nested: boolean = false): boolean {\n if ((err as any).name == 'RpcError' && (err as any).code == 'NOT_FOUND') return true;\n if ((err as any).cause !== undefined && !nested) return isNotFoundError((err as any).cause, true);\n return err instanceof RecoverablePlError && err.status.code === PlErrorCodeNotFound;\n}\n\nexport class UnauthenticatedError extends Error {\n name = 'UnauthenticatedError';\n constructor(message: string) {\n super('LoginFailed: ' + message);\n }\n}\n\nexport class DisconnectedError extends Error {\n name = 'DisconnectedError';\n constructor(message: string) {\n super('Disconnected: ' + message);\n }\n}\n\nexport function rethrowMeaningfulError(error: any, wrapIfUnknown: boolean = false): never {\n if (isUnauthenticated(error)) {\n if (error instanceof UnauthenticatedError) throw error;\n throw new UnauthenticatedError(error.message);\n }\n if (isConnectionProblem(error)) {\n if (error instanceof DisconnectedError) throw error;\n throw new DisconnectedError(error.message);\n }\n if (isTimeoutOrCancelError(error)) throw new Aborted(error);\n if (wrapIfUnknown) {\n const message = error.message || String(error) || 'Unknown error';\n throw new Error(message, { cause: error });\n } else throw error;\n}\n"],"names":[],"mappings":"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"}
|