@milaboratories/pl-client 2.16.14 → 2.16.16
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/core/client.cjs.map +1 -1
- package/dist/core/client.d.ts +2 -1
- package/dist/core/client.d.ts.map +1 -1
- package/dist/core/client.js.map +1 -1
- package/dist/core/errors.cjs +71 -23
- package/dist/core/errors.cjs.map +1 -1
- package/dist/core/errors.d.ts +10 -3
- package/dist/core/errors.d.ts.map +1 -1
- package/dist/core/errors.js +68 -24
- package/dist/core/errors.js.map +1 -1
- package/dist/core/ll_client.cjs +30 -6
- package/dist/core/ll_client.cjs.map +1 -1
- package/dist/core/ll_client.d.ts +2 -0
- package/dist/core/ll_client.d.ts.map +1 -1
- package/dist/core/ll_client.js +30 -6
- package/dist/core/ll_client.js.map +1 -1
- package/dist/index.cjs +4 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/proto-rest/index.cjs +1 -1
- package/dist/proto-rest/index.cjs.map +1 -1
- package/dist/proto-rest/index.js +2 -2
- package/dist/proto-rest/index.js.map +1 -1
- package/package.json +10 -8
- package/src/core/client.ts +3 -1
- package/src/core/errors.ts +63 -32
- package/src/core/ll_client.test.ts +9 -0
- package/src/core/ll_client.ts +44 -10
- package/src/proto-rest/index.ts +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ll_client.js","sources":["../../src/core/ll_client.ts"],"sourcesContent":["import { PlatformClient as GrpcPlApiClient } from '../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client';\nimport type { ClientOptions, Interceptor } from '@grpc/grpc-js';\nimport {\n ChannelCredentials,\n InterceptingCall,\n status as GrpcStatus,\n compressionAlgorithms,\n} from '@grpc/grpc-js';\nimport type {\n AuthInformation,\n AuthOps,\n PlClientConfig,\n PlConnectionStatus,\n PlConnectionStatusListener,\n} from './config';\nimport { plAddressToConfig, type wireProtocol, SUPPORTED_WIRE_PROTOCOLS } from './config';\nimport type { GrpcOptions } from '@protobuf-ts/grpc-transport';\nimport { GrpcTransport } from '@protobuf-ts/grpc-transport';\nimport { LLPlTransaction } from './ll_transaction';\nimport { parsePlJwt } from '../util/pl';\nimport { type Dispatcher, interceptors } from 'undici';\nimport type { Middleware } from 'openapi-fetch';\nimport { inferAuthRefreshTime } from './auth';\nimport { defaultHttpDispatcher } from '@milaboratories/pl-http';\nimport type { WireClientProvider, WireClientProviderFactory, WireConnection } from './wire';\nimport { parseHttpAuth } from '@milaboratories/pl-model-common';\nimport type * as grpcTypes from '../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api';\nimport { type PlApiPaths, type PlRestClientType, createClient, parseResponseError } from '../proto-rest';\nimport { notEmpty, retry, withTimeout, type RetryOptions } from '@milaboratories/ts-helpers';\nimport { Code } from '../proto-grpc/google/rpc/code';\nimport { WebSocketBiDiStream } from './websocket_stream';\nimport { TxAPI_ClientMessage, TxAPI_ServerMessage } from '../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api';\n\nexport interface PlCallOps {\n timeout?: number;\n abortSignal?: AbortSignal;\n}\n\nclass WireClientProviderImpl<Client> implements WireClientProvider<Client> {\n private client: Client | undefined = undefined;\n\n constructor(private readonly wireOpts: () => WireConnection, private readonly clientConstructor: (wireOpts: WireConnection) => Client) {}\n\n public reset(): void {\n this.client = undefined;\n }\n\n public get(): Client {\n if (this.client === undefined)\n this.client = this.clientConstructor(this.wireOpts());\n return this.client;\n }\n}\n\n/** Abstract out low level networking and authorization details */\nexport class LLPlClient implements WireClientProviderFactory {\n /** Initial authorization information */\n private authInformation?: AuthInformation;\n /** Will be executed by the client when it is required */\n private readonly onAuthUpdate?: (newInfo: AuthInformation) => void;\n /** Will be executed if auth-related error happens during normal client operation */\n private readonly onAuthError?: () => void;\n /** Will be executed by the client when it is required */\n private readonly onAuthRefreshProblem?: (error: unknown) => void;\n /** Threshold after which auth info refresh is required */\n private refreshTimestamp?: number;\n\n private _status: PlConnectionStatus = 'OK';\n private readonly statusListener?: PlConnectionStatusListener;\n\n private _wireProto: wireProtocol = 'grpc';\n private _wireConn!: WireConnection;\n\n private readonly _restInterceptors: Dispatcher.DispatcherComposeInterceptor[];\n private readonly _restMiddlewares: Middleware[];\n private readonly _grpcInterceptors: Interceptor[];\n private readonly providers: WeakRef<WireClientProviderImpl<any>>[] = [];\n\n public readonly clientProvider: WireClientProvider<PlRestClientType | GrpcPlApiClient>;\n\n public readonly httpDispatcher: Dispatcher;\n\n public static async build(\n configOrAddress: PlClientConfig | string,\n ops: {\n auth?: AuthOps;\n statusListener?: PlConnectionStatusListener;\n shouldUseGzip?: boolean;\n } = {},\n ) {\n const conf = typeof configOrAddress === 'string' ? plAddressToConfig(configOrAddress) : configOrAddress;\n\n const pl = new LLPlClient(conf, ops);\n await pl.detectOptimalWireProtocol();\n return pl;\n }\n\n private constructor(\n public readonly conf: PlClientConfig,\n private readonly ops: {\n auth?: AuthOps;\n statusListener?: PlConnectionStatusListener;\n shouldUseGzip?: boolean;\n } = {},\n ) {\n const { auth, statusListener } = ops;\n\n if (auth !== undefined) {\n this.refreshTimestamp = inferAuthRefreshTime(\n auth.authInformation,\n this.conf.authMaxRefreshSeconds,\n );\n this.authInformation = auth.authInformation;\n this.onAuthUpdate = auth.onUpdate;\n this.onAuthRefreshProblem = auth.onUpdateError;\n this.onAuthError = auth.onAuthError;\n }\n\n this._restInterceptors = [];\n this._restMiddlewares = [];\n this._grpcInterceptors = [];\n\n if (auth !== undefined) {\n this._restInterceptors.push(this.createRestAuthInterceptor());\n this._grpcInterceptors.push(this.createGrpcAuthInterceptor());\n }\n this._restInterceptors.push(interceptors.retry({ statusCodes: [] })); // Handle errors with openapi-fetch middleware.\n this._restMiddlewares.push(this.createRestErrorMiddleware());\n this._grpcInterceptors.push(this.createGrpcErrorInterceptor());\n\n this.httpDispatcher = defaultHttpDispatcher(this.conf.httpProxy);\n if (this.conf.wireProtocol) {\n this._wireProto = this.conf.wireProtocol;\n }\n\n this.initWireConnection(this._wireProto);\n\n if (statusListener !== undefined) {\n this.statusListener = statusListener;\n statusListener(this._status);\n }\n\n this.clientProvider = this.createWireClientProvider((wireConn) => {\n if (wireConn.type === 'grpc') {\n return new GrpcPlApiClient(wireConn.Transport);\n } else {\n return createClient<PlApiPaths>({\n hostAndPort: wireConn.Config.hostAndPort,\n ssl: wireConn.Config.ssl,\n dispatcher: wireConn.Dispatcher,\n middlewares: wireConn.Middlewares,\n });\n }\n });\n }\n\n private initWireConnection(protocol: wireProtocol) {\n switch (protocol) {\n case 'rest':\n this.initRestConnection();\n return;\n case 'grpc':\n this.initGrpcConnection(this.ops.shouldUseGzip ?? false);\n return;\n default:\n ((v: never) => {\n throw new Error(`Unsupported wire protocol '${v as string}'. Use one of: ${SUPPORTED_WIRE_PROTOCOLS.join(', ')}`);\n })(protocol);\n }\n }\n\n private initRestConnection(): void {\n const dispatcher = defaultHttpDispatcher(this.conf.grpcProxy, this._restInterceptors);\n this._replaceWireConnection({ type: 'rest', Config: this.conf, Dispatcher: dispatcher, Middlewares: this._restMiddlewares });\n }\n\n /**\n * Initializes (or reinitializes) _grpcTransport\n * @param gzip - whether to enable gzip compression\n */\n private initGrpcConnection(gzip: boolean) {\n const clientOptions: ClientOptions = {\n 'grpc.keepalive_time_ms': 30_000, // 30 seconds\n 'grpc.service_config_disable_resolution': 1, // Disable DNS TXT lookups for service config\n 'interceptors': this._grpcInterceptors,\n };\n\n if (gzip) clientOptions['grpc.default_compression_algorithm'] = compressionAlgorithms.gzip;\n\n //\n // Leaving it here for now\n // https://github.com/grpc/grpc-node/issues/2788\n //\n // We should implement message pooling algorithm to overcome hardcoded NO_DELAY behaviour\n // of HTTP/2 and allow our small messages to batch together.\n //\n const grpcOptions: GrpcOptions = {\n host: this.conf.hostAndPort,\n timeout: this.conf.defaultRequestTimeout,\n channelCredentials: this.conf.ssl\n ? ChannelCredentials.createSsl()\n : ChannelCredentials.createInsecure(),\n clientOptions,\n };\n\n const grpcProxy = typeof this.conf.grpcProxy === 'string'\n ? { url: this.conf.grpcProxy }\n : this.conf.grpcProxy;\n\n if (grpcProxy?.url) {\n const url = new URL(grpcProxy.url);\n if (grpcProxy.auth) {\n const parsed = parseHttpAuth(grpcProxy.auth);\n if (parsed.scheme !== 'Basic') {\n throw new Error(`Unsupported auth scheme: ${parsed.scheme as string}.`);\n }\n url.username = parsed.username;\n url.password = parsed.password;\n }\n process.env.grpc_proxy = url.toString();\n } else {\n delete process.env.grpc_proxy;\n }\n\n this._replaceWireConnection({ type: 'grpc', Transport: new GrpcTransport(grpcOptions) });\n }\n\n private _replaceWireConnection(newConn: WireConnection): void {\n const oldConn = this._wireConn;\n this._wireConn = newConn;\n this._wireProto = newConn.type;\n\n // Reset all providers to let them reinitialize their clients\n for (let i = 0; i < this.providers.length; i++) {\n const provider = this.providers[i].deref();\n if (provider === undefined) {\n // at the same time we need to remove providers that are no longer valid\n this.providers.splice(i, 1);\n i--;\n } else {\n provider.reset();\n }\n }\n\n if (oldConn !== undefined && oldConn.type === 'grpc') oldConn.Transport.close();\n }\n\n private providerCleanupCounter = 0;\n\n /**\n * Creates a provider for a grpc client. Returned provider will create fresh client whenever the underlying transport is reset.\n *\n * @param clientConstructor - a factory function that creates a grpc client\n */\n public createWireClientProvider<Client>(clientConstructor: (transport: WireConnection) => Client): WireClientProvider<Client> {\n // We need to cleanup providers periodically to avoid memory leaks.\n // This is a simple heuristic to avoid memory leaks.\n // We could use a more sophisticated algorithm, but this is good enough for now.\n this.providerCleanupCounter++;\n if (this.providerCleanupCounter >= 16) {\n for (let i = 0; i < this.providers.length; i++) {\n const provider = this.providers[i].deref();\n if (provider === undefined) {\n this.providers.splice(i, 1);\n i--;\n }\n }\n this.providerCleanupCounter = 0;\n }\n\n const provider = new WireClientProviderImpl<Client>(() => this._wireConn, clientConstructor);\n this.providers.push(new WeakRef(provider));\n return provider;\n }\n\n public get wireConnection(): WireConnection {\n return this._wireConn;\n }\n\n public get wireProtocol(): wireProtocol | undefined {\n return this._wireProto;\n }\n\n /** Returns true if client is authenticated. Even with anonymous auth information\n * connection is considered authenticated. Unauthenticated clients are used for\n * login and similar tasks, see {@link UnauthenticatedPlClient}. */\n public get authenticated(): boolean {\n return this.authInformation !== undefined;\n }\n\n /** null means anonymous connection */\n public get authUser(): string | null {\n if (!this.authenticated) throw new Error('Client is not authenticated');\n if (this.authInformation?.jwtToken)\n return parsePlJwt(this.authInformation?.jwtToken).user.login;\n else return null;\n }\n\n private updateStatus(newStatus: PlConnectionStatus) {\n process.nextTick(() => {\n if (this._status !== newStatus) {\n this._status = newStatus;\n if (this.statusListener !== undefined) this.statusListener(this._status);\n if (this.onAuthError !== undefined) this.onAuthError();\n }\n });\n }\n\n public get status(): PlConnectionStatus {\n return this._status;\n }\n\n private authRefreshInProgress: boolean = false;\n\n private refreshAuthInformationIfNeeded(): void {\n if (\n this.refreshTimestamp === undefined\n || Date.now() < this.refreshTimestamp\n || this.authRefreshInProgress\n || this._status === 'Unauthenticated'\n )\n return;\n\n // Running refresh in background`\n this.authRefreshInProgress = true;\n void (async () => {\n try {\n const token = await this.getJwtToken(BigInt(this.conf.authTTLSeconds));\n this.authInformation = { jwtToken: token };\n this.refreshTimestamp = inferAuthRefreshTime(\n this.authInformation,\n this.conf.authMaxRefreshSeconds,\n );\n if (this.onAuthUpdate) this.onAuthUpdate(this.authInformation);\n } catch (e: unknown) {\n if (this.onAuthRefreshProblem) this.onAuthRefreshProblem(e);\n } finally {\n this.authRefreshInProgress = false;\n }\n })();\n }\n\n /**\n * Creates middleware that parses error responses and handles them centrally.\n * This middleware runs before openapi-fetch parses the response, so we need to\n * manually parse the response body for error responses.\n */\n private createRestErrorMiddleware(): Middleware {\n return {\n onResponse: async ({ request: _request, response, options: _options }) => {\n const { body: body, ...resOptions } = response;\n\n if ([502, 503, 504].includes(response.status)) {\n // Service unavailable, bad gateway, gateway timeout\n this.updateStatus('Disconnected');\n return new Response(body, { ...resOptions, status: response.status });\n }\n\n const respErr = await parseResponseError(response);\n if (!respErr.error) {\n // No error: nice!\n return new Response(respErr.origBody ?? body, { ...resOptions, status: response.status });\n }\n\n if (typeof respErr.error === 'string') {\n // Non-standard error or normal response: let later middleware to deal wit it.\n return new Response(respErr.error, { ...resOptions, status: response.status });\n }\n\n if (respErr.error.code === Code.UNAUTHENTICATED) {\n this.updateStatus('Unauthenticated');\n }\n\n // Let later middleware to deal with standard gRPC error.\n return new Response(respErr.origBody, { ...resOptions, status: response.status });\n },\n };\n }\n\n /** Detects certain errors and update client status accordingly when using GRPC wire connection */\n private createGrpcErrorInterceptor(): Interceptor {\n return (options, nextCall) => {\n return new InterceptingCall(nextCall(options), {\n start: (metadata, listener, next) => {\n next(metadata, {\n onReceiveStatus: (status, next) => {\n if (status.code == GrpcStatus.UNAUTHENTICATED)\n // (!!!) don't change to \"===\"\n this.updateStatus('Unauthenticated');\n if (status.code == GrpcStatus.UNAVAILABLE)\n // (!!!) don't change to \"===\"\n this.updateStatus('Disconnected');\n next(status);\n },\n });\n },\n });\n };\n }\n\n private createRestAuthInterceptor(): Dispatcher.DispatcherComposeInterceptor {\n return (dispatch) => {\n return (options, handler) => {\n if (this.authInformation?.jwtToken !== undefined) {\n // TODO: check this magic really works and gets called\n options.headers = { ...options.headers, authorization: 'Bearer ' + this.authInformation.jwtToken };\n this.refreshAuthInformationIfNeeded();\n }\n\n return dispatch(options, handler);\n };\n };\n }\n\n /** Injects authentication information if needed */\n private createGrpcAuthInterceptor(): Interceptor {\n return (options, nextCall) => {\n return new InterceptingCall(nextCall(options), {\n start: (metadata, listener, next) => {\n if (this.authInformation?.jwtToken !== undefined) {\n metadata.set('authorization', 'Bearer ' + this.authInformation.jwtToken);\n this.refreshAuthInformationIfNeeded();\n next(metadata, listener);\n } else {\n next(metadata, listener);\n }\n },\n });\n };\n }\n\n public async getJwtToken(ttlSeconds: bigint, options?: { authorization?: string }): Promise<string> {\n const cl = this.clientProvider.get();\n\n if (cl instanceof GrpcPlApiClient) {\n const meta: Record<string, string> = {};\n if (options?.authorization) meta.authorization = options.authorization;\n return (await cl.getJWTToken({ expiration: { seconds: ttlSeconds, nanos: 0 } }, { meta }).response).token;\n } else {\n const headers: Record<string, string> = {};\n if (options?.authorization) headers.authorization = options.authorization;\n const resp = cl.POST('/v1/auth/jwt-token', {\n body: { expiration: `${ttlSeconds}s` },\n headers,\n });\n return notEmpty((await resp).data).token;\n }\n }\n\n public async ping(): Promise<grpcTypes.MaintenanceAPI_Ping_Response> {\n const cl = this.clientProvider.get();\n if (cl instanceof GrpcPlApiClient) {\n return (await cl.ping({})).response;\n } else {\n return notEmpty((await cl.GET('/v1/ping')).data);\n }\n }\n\n /**\n * Detects the best available wire protocol.\n * If wireProtocol is explicitly configured, does nothing.\n * Otherwise probes the current protocol via ping; if it fails, switches to the alternative.\n */\n private async detectOptimalWireProtocol() {\n if (this.conf.wireProtocol) {\n return;\n }\n\n const retryOptions: RetryOptions = {\n type: 'exponentialBackoff',\n maxAttempts: 80,\n initialDelay: 30,\n backoffMultiplier: 1.3,\n jitter: 0.2,\n maxDelay: 500,\n };\n\n await retry(() => withTimeout(this.ping(), 500), retryOptions, () => {\n const protocol = this._wireProto === 'grpc' ? 'rest' : 'grpc';\n this.initWireConnection(protocol);\n return true;\n });\n }\n\n public async license(): Promise<grpcTypes.MaintenanceAPI_License_Response> {\n const cl = this.clientProvider.get();\n if (cl instanceof GrpcPlApiClient) {\n return (await cl.license({})).response;\n } else {\n const resp = notEmpty((await cl.GET('/v1/license')).data);\n return {\n status: resp.status,\n isOk: resp.isOk,\n responseBody: Uint8Array.from(Buffer.from(resp.responseBody)),\n };\n }\n }\n\n public async authMethods(): Promise<grpcTypes.AuthAPI_ListMethods_Response> {\n const cl = this.clientProvider.get();\n if (cl instanceof GrpcPlApiClient) {\n return (await cl.authMethods({})).response;\n } else {\n return notEmpty((await cl.GET('/v1/auth/methods')).data);\n }\n }\n\n public async txSync(txId: bigint): Promise<void> {\n const cl = this.clientProvider.get();\n if (cl instanceof GrpcPlApiClient) {\n await cl.txSync({ txId: BigInt(txId) });\n } else {\n (await cl.POST('/v1/tx-sync', { body: { txId: txId.toString() } }));\n }\n }\n\n createTx(rw: boolean, ops: PlCallOps = {}): LLPlTransaction {\n return new LLPlTransaction((abortSignal) => {\n let totalAbortSignal = abortSignal;\n if (ops.abortSignal) totalAbortSignal = AbortSignal.any([totalAbortSignal, ops.abortSignal]);\n\n const timeout = ops.timeout ?? (rw ? this.conf.defaultRWTransactionTimeout : this.conf.defaultROTransactionTimeout);\n\n const cl = this.clientProvider.get();\n if (cl instanceof GrpcPlApiClient) {\n return cl.tx({\n abort: totalAbortSignal,\n timeout,\n });\n }\n\n const wireConn = this.wireConnection;\n if (wireConn.type === 'rest') {\n // For REST/WebSocket protocol, timeout needs to be converted to AbortSignal\n if (timeout !== undefined) {\n totalAbortSignal = AbortSignal.any([totalAbortSignal, AbortSignal.timeout(timeout)]);\n }\n\n // The gRPC transport has the auth interceptor that already handles it, but here we need to refresh the auth information to be safe.\n this.refreshAuthInformationIfNeeded();\n\n const wsUrl = this.conf.ssl\n ? `wss://${this.conf.hostAndPort}/v1/ws/tx`\n : `ws://${this.conf.hostAndPort}/v1/ws/tx`;\n\n return new WebSocketBiDiStream(wsUrl,\n (msg) => TxAPI_ClientMessage.toBinary(msg),\n (data) => TxAPI_ServerMessage.fromBinary(new Uint8Array(data)),\n {\n abortSignal: totalAbortSignal,\n jwtToken: this.authInformation?.jwtToken,\n dispatcher: wireConn.Dispatcher,\n\n onComplete: async (stream) => stream.requests.send({\n // Ask server to gracefully close the stream on its side, if not done yet.\n requestId: 0,\n request: { oneofKind: 'streamClose', streamClose: {} },\n }),\n },\n );\n }\n\n throw new Error(`transactions are not supported for wire protocol ${this._wireProto}`);\n });\n }\n\n /** Closes underlying transport */\n public async close() {\n if (this.wireConnection.type === 'grpc') {\n this.wireConnection.Transport.close();\n } else {\n // TODO: close all WS connections\n }\n await this.httpDispatcher.destroy();\n }\n}\n"],"names":["GrpcPlApiClient","status","GrpcStatus"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ll_client.js","sources":["../../src/core/ll_client.ts"],"sourcesContent":["import { PlatformClient as GrpcPlApiClient } from '../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api.client';\nimport type { ClientOptions, Interceptor } from '@grpc/grpc-js';\nimport {\n ChannelCredentials,\n InterceptingCall,\n status as GrpcStatus,\n compressionAlgorithms,\n} from '@grpc/grpc-js';\nimport type {\n AuthInformation,\n AuthOps,\n PlClientConfig,\n PlConnectionStatus,\n PlConnectionStatusListener,\n} from './config';\nimport { plAddressToConfig, type wireProtocol, SUPPORTED_WIRE_PROTOCOLS } from './config';\nimport type { GrpcOptions } from '@protobuf-ts/grpc-transport';\nimport { GrpcTransport } from '@protobuf-ts/grpc-transport';\nimport { LLPlTransaction } from './ll_transaction';\nimport { parsePlJwt } from '../util/pl';\nimport { type Dispatcher, interceptors } from 'undici';\nimport type { Middleware } from 'openapi-fetch';\nimport { inferAuthRefreshTime } from './auth';\nimport { defaultHttpDispatcher } from '@milaboratories/pl-http';\nimport type { WireClientProvider, WireClientProviderFactory, WireConnection } from './wire';\nimport { parseHttpAuth } from '@milaboratories/pl-model-common';\nimport type * as grpcTypes from '../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api';\nimport { type PlApiPaths, type PlRestClientType, createClient, parseResponseError } from '../proto-rest';\nimport { notEmpty, retry, withTimeout, type RetryOptions } from '@milaboratories/ts-helpers';\nimport { Code } from '../proto-grpc/google/rpc/code';\nimport { WebSocketBiDiStream } from './websocket_stream';\nimport { TxAPI_ClientMessage, TxAPI_ServerMessage } from '../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api';\nimport type { MiLogger } from '@milaboratories/ts-helpers';\nimport { isAbortedError } from './errors';\n\nexport interface PlCallOps {\n timeout?: number;\n abortSignal?: AbortSignal;\n}\n\nclass WireClientProviderImpl<Client> implements WireClientProvider<Client> {\n private client: Client | undefined = undefined;\n\n constructor(private readonly wireOpts: () => WireConnection, private readonly clientConstructor: (wireOpts: WireConnection) => Client) {}\n\n public reset(): void {\n this.client = undefined;\n }\n\n public get(): Client {\n if (this.client === undefined)\n this.client = this.clientConstructor(this.wireOpts());\n return this.client;\n }\n}\n\n/** Abstract out low level networking and authorization details */\nexport class LLPlClient implements WireClientProviderFactory {\n /** Initial authorization information */\n private authInformation?: AuthInformation;\n /** Will be executed by the client when it is required */\n private readonly onAuthUpdate?: (newInfo: AuthInformation) => void;\n /** Will be executed if auth-related error happens during normal client operation */\n private readonly onAuthError?: () => void;\n /** Will be executed by the client when it is required */\n private readonly onAuthRefreshProblem?: (error: unknown) => void;\n /** Threshold after which auth info refresh is required */\n private refreshTimestamp?: number;\n\n private _status: PlConnectionStatus = 'OK';\n private readonly statusListener?: PlConnectionStatusListener;\n\n private _wireProto: wireProtocol = 'grpc';\n private _wireConn!: WireConnection;\n\n private readonly _restInterceptors: Dispatcher.DispatcherComposeInterceptor[];\n private readonly _restMiddlewares: Middleware[];\n private readonly _grpcInterceptors: Interceptor[];\n private readonly providers: WeakRef<WireClientProviderImpl<any>>[] = [];\n\n public readonly clientProvider: WireClientProvider<PlRestClientType | GrpcPlApiClient>;\n\n public readonly httpDispatcher: Dispatcher;\n\n public static async build(\n configOrAddress: PlClientConfig | string,\n ops: {\n auth?: AuthOps;\n statusListener?: PlConnectionStatusListener;\n shouldUseGzip?: boolean;\n logger?: MiLogger;\n } = {},\n ) {\n const conf = typeof configOrAddress === 'string' ? plAddressToConfig(configOrAddress) : configOrAddress;\n\n const pl = new LLPlClient(conf, ops);\n await pl.detectOptimalWireProtocol();\n return pl;\n }\n\n private constructor(\n public readonly conf: PlClientConfig,\n private readonly ops: {\n auth?: AuthOps;\n statusListener?: PlConnectionStatusListener;\n shouldUseGzip?: boolean;\n logger?: MiLogger;\n } = {},\n ) {\n const { auth, statusListener } = ops;\n\n if (auth !== undefined) {\n this.refreshTimestamp = inferAuthRefreshTime(\n auth.authInformation,\n this.conf.authMaxRefreshSeconds,\n );\n this.authInformation = auth.authInformation;\n this.onAuthUpdate = auth.onUpdate;\n this.onAuthRefreshProblem = auth.onUpdateError;\n this.onAuthError = auth.onAuthError;\n }\n\n this._restInterceptors = [];\n this._restMiddlewares = [];\n this._grpcInterceptors = [];\n\n if (auth !== undefined) {\n this._restInterceptors.push(this.createRestAuthInterceptor());\n this._grpcInterceptors.push(this.createGrpcAuthInterceptor());\n }\n this._restInterceptors.push(interceptors.retry({ statusCodes: [] })); // Handle errors with openapi-fetch middleware.\n this._restMiddlewares.push(this.createRestErrorMiddleware());\n this._grpcInterceptors.push(this.createGrpcErrorInterceptor());\n\n this.httpDispatcher = defaultHttpDispatcher(this.conf.httpProxy);\n if (this.conf.wireProtocol) {\n this._wireProto = this.conf.wireProtocol;\n }\n\n this.initWireConnection(this._wireProto);\n\n if (statusListener !== undefined) {\n this.statusListener = statusListener;\n statusListener(this._status);\n }\n\n this.clientProvider = this.createWireClientProvider((wireConn) => {\n if (wireConn.type === 'grpc') {\n return new GrpcPlApiClient(wireConn.Transport);\n } else {\n return createClient<PlApiPaths>({\n hostAndPort: wireConn.Config.hostAndPort,\n ssl: wireConn.Config.ssl,\n dispatcher: wireConn.Dispatcher,\n middlewares: wireConn.Middlewares,\n });\n }\n });\n }\n\n private initWireConnection(protocol: wireProtocol) {\n switch (protocol) {\n case 'rest':\n this.initRestConnection();\n return;\n case 'grpc':\n this.initGrpcConnection(this.ops.shouldUseGzip ?? false);\n return;\n default:\n ((v: never) => {\n throw new Error(`Unsupported wire protocol '${v as string}'. Use one of: ${SUPPORTED_WIRE_PROTOCOLS.join(', ')}`);\n })(protocol);\n }\n }\n\n private initRestConnection(): void {\n const dispatcher = defaultHttpDispatcher(this.conf.grpcProxy, this._restInterceptors);\n this._replaceWireConnection({ type: 'rest', Config: this.conf, Dispatcher: dispatcher, Middlewares: this._restMiddlewares });\n }\n\n /**\n * Initializes (or reinitializes) _grpcTransport\n * @param gzip - whether to enable gzip compression\n */\n private initGrpcConnection(gzip: boolean) {\n const clientOptions: ClientOptions = {\n 'grpc.keepalive_time_ms': 30_000, // 30 seconds\n 'grpc.service_config_disable_resolution': 1, // Disable DNS TXT lookups for service config\n 'interceptors': this._grpcInterceptors,\n };\n\n if (gzip) clientOptions['grpc.default_compression_algorithm'] = compressionAlgorithms.gzip;\n\n //\n // Leaving it here for now\n // https://github.com/grpc/grpc-node/issues/2788\n //\n // We should implement message pooling algorithm to overcome hardcoded NO_DELAY behaviour\n // of HTTP/2 and allow our small messages to batch together.\n //\n const grpcOptions: GrpcOptions = {\n host: this.conf.hostAndPort,\n timeout: this.conf.defaultRequestTimeout,\n channelCredentials: this.conf.ssl\n ? ChannelCredentials.createSsl()\n : ChannelCredentials.createInsecure(),\n clientOptions,\n };\n\n const grpcProxy = typeof this.conf.grpcProxy === 'string'\n ? { url: this.conf.grpcProxy }\n : this.conf.grpcProxy;\n\n if (grpcProxy?.url) {\n const url = new URL(grpcProxy.url);\n if (grpcProxy.auth) {\n const parsed = parseHttpAuth(grpcProxy.auth);\n if (parsed.scheme !== 'Basic') {\n throw new Error(`Unsupported auth scheme: ${parsed.scheme as string}.`);\n }\n url.username = parsed.username;\n url.password = parsed.password;\n }\n process.env.grpc_proxy = url.toString();\n } else {\n delete process.env.grpc_proxy;\n }\n\n this._replaceWireConnection({ type: 'grpc', Transport: new GrpcTransport(grpcOptions) });\n }\n\n private _replaceWireConnection(newConn: WireConnection): void {\n const oldConn = this._wireConn;\n this._wireConn = newConn;\n this._wireProto = newConn.type;\n\n // Reset all providers to let them reinitialize their clients\n for (let i = 0; i < this.providers.length; i++) {\n const provider = this.providers[i].deref();\n if (provider === undefined) {\n // at the same time we need to remove providers that are no longer valid\n this.providers.splice(i, 1);\n i--;\n } else {\n provider.reset();\n }\n }\n\n if (oldConn !== undefined && oldConn.type === 'grpc') oldConn.Transport.close();\n }\n\n private providerCleanupCounter = 0;\n\n /**\n * Creates a provider for a grpc client. Returned provider will create fresh client whenever the underlying transport is reset.\n *\n * @param clientConstructor - a factory function that creates a grpc client\n */\n public createWireClientProvider<Client>(clientConstructor: (transport: WireConnection) => Client): WireClientProvider<Client> {\n // We need to cleanup providers periodically to avoid memory leaks.\n // This is a simple heuristic to avoid memory leaks.\n // We could use a more sophisticated algorithm, but this is good enough for now.\n this.providerCleanupCounter++;\n if (this.providerCleanupCounter >= 16) {\n for (let i = 0; i < this.providers.length; i++) {\n const provider = this.providers[i].deref();\n if (provider === undefined) {\n this.providers.splice(i, 1);\n i--;\n }\n }\n this.providerCleanupCounter = 0;\n }\n\n const provider = new WireClientProviderImpl<Client>(() => this._wireConn, clientConstructor);\n this.providers.push(new WeakRef(provider));\n return provider;\n }\n\n public get wireConnection(): WireConnection {\n return this._wireConn;\n }\n\n public get wireProtocol(): wireProtocol | undefined {\n return this._wireProto;\n }\n\n /** Returns true if client is authenticated. Even with anonymous auth information\n * connection is considered authenticated. Unauthenticated clients are used for\n * login and similar tasks, see {@link UnauthenticatedPlClient}. */\n public get authenticated(): boolean {\n return this.authInformation !== undefined;\n }\n\n /** null means anonymous connection */\n public get authUser(): string | null {\n if (!this.authenticated) throw new Error('Client is not authenticated');\n if (this.authInformation?.jwtToken)\n return parsePlJwt(this.authInformation?.jwtToken).user.login;\n else return null;\n }\n\n private updateStatus(newStatus: PlConnectionStatus) {\n process.nextTick(() => {\n if (this._status !== newStatus) {\n this._status = newStatus;\n if (this.statusListener !== undefined) this.statusListener(this._status);\n if (this.onAuthError !== undefined) this.onAuthError();\n }\n });\n }\n\n public get status(): PlConnectionStatus {\n return this._status;\n }\n\n private authRefreshInProgress: boolean = false;\n\n private refreshAuthInformationIfNeeded(): void {\n if (\n this.refreshTimestamp === undefined\n || Date.now() < this.refreshTimestamp\n || this.authRefreshInProgress\n || this._status === 'Unauthenticated'\n )\n return;\n\n // Running refresh in background`\n this.authRefreshInProgress = true;\n void (async () => {\n try {\n const token = await this.getJwtToken(BigInt(this.conf.authTTLSeconds));\n this.authInformation = { jwtToken: token };\n this.refreshTimestamp = inferAuthRefreshTime(\n this.authInformation,\n this.conf.authMaxRefreshSeconds,\n );\n if (this.onAuthUpdate) this.onAuthUpdate(this.authInformation);\n } catch (e: unknown) {\n if (this.onAuthRefreshProblem) this.onAuthRefreshProblem(e);\n } finally {\n this.authRefreshInProgress = false;\n }\n })();\n }\n\n /**\n * Creates middleware that parses error responses and handles them centrally.\n * This middleware runs before openapi-fetch parses the response, so we need to\n * manually parse the response body for error responses.\n */\n private createRestErrorMiddleware(): Middleware {\n return {\n onResponse: async ({ request: _request, response, options: _options }) => {\n const { body: body, ...resOptions } = response;\n\n if ([502, 503, 504].includes(response.status)) {\n // Service unavailable, bad gateway, gateway timeout\n this.updateStatus('Disconnected');\n return new Response(body, { ...resOptions, status: response.status });\n }\n\n const respErr = await parseResponseError(response);\n if (!respErr.error) {\n // No error: nice!\n return new Response(respErr.origBody ?? body, { ...resOptions, status: response.status });\n }\n\n if (typeof respErr.error === 'string') {\n // Non-standard error or normal response: let later middleware to deal wit it.\n return new Response(respErr.error, { ...resOptions, status: response.status });\n }\n\n if (respErr.error.code === Code.UNAUTHENTICATED) {\n this.updateStatus('Unauthenticated');\n }\n\n // Let later middleware to deal with standard gRPC error.\n return new Response(respErr.origBody, { ...resOptions, status: response.status });\n },\n };\n }\n\n /** Detects certain errors and update client status accordingly when using GRPC wire connection */\n private createGrpcErrorInterceptor(): Interceptor {\n return (options, nextCall) => {\n return new InterceptingCall(nextCall(options), {\n start: (metadata, listener, next) => {\n next(metadata, {\n onReceiveStatus: (status, next) => {\n if (status.code == GrpcStatus.UNAUTHENTICATED)\n // (!!!) don't change to \"===\"\n this.updateStatus('Unauthenticated');\n if (status.code == GrpcStatus.UNAVAILABLE)\n // (!!!) don't change to \"===\"\n this.updateStatus('Disconnected');\n next(status);\n },\n });\n },\n });\n };\n }\n\n private createRestAuthInterceptor(): Dispatcher.DispatcherComposeInterceptor {\n return (dispatch) => {\n return (options, handler) => {\n if (this.authInformation?.jwtToken !== undefined) {\n // TODO: check this magic really works and gets called\n options.headers = { ...options.headers, authorization: 'Bearer ' + this.authInformation.jwtToken };\n this.refreshAuthInformationIfNeeded();\n }\n\n return dispatch(options, handler);\n };\n };\n }\n\n /** Injects authentication information if needed */\n private createGrpcAuthInterceptor(): Interceptor {\n return (options, nextCall) => {\n return new InterceptingCall(nextCall(options), {\n start: (metadata, listener, next) => {\n if (this.authInformation?.jwtToken !== undefined) {\n metadata.set('authorization', 'Bearer ' + this.authInformation.jwtToken);\n this.refreshAuthInformationIfNeeded();\n next(metadata, listener);\n } else {\n next(metadata, listener);\n }\n },\n });\n };\n }\n\n public async getJwtToken(ttlSeconds: bigint, options?: { authorization?: string }): Promise<string> {\n const cl = this.clientProvider.get();\n\n if (cl instanceof GrpcPlApiClient) {\n const meta: Record<string, string> = {};\n if (options?.authorization) meta.authorization = options.authorization;\n return (await cl.getJWTToken({ expiration: { seconds: ttlSeconds, nanos: 0 } }, { meta }).response).token;\n } else {\n const headers: Record<string, string> = {};\n if (options?.authorization) headers.authorization = options.authorization;\n const resp = cl.POST('/v1/auth/jwt-token', {\n body: { expiration: `${ttlSeconds}s` },\n headers,\n });\n return notEmpty((await resp).data, 'REST: empty response for JWT token request').token;\n }\n }\n\n public async ping(): Promise<grpcTypes.MaintenanceAPI_Ping_Response> {\n const cl = this.clientProvider.get();\n if (cl instanceof GrpcPlApiClient) {\n return (await cl.ping({})).response;\n } else {\n return notEmpty((await cl.GET('/v1/ping')).data, 'REST: empty response for ping request');\n }\n }\n\n /**\n * Detects the best available wire protocol.\n * If wireProtocol is explicitly configured, does nothing.\n * Otherwise probes the current protocol via ping; if it fails, switches to the alternative.\n */\n private async detectOptimalWireProtocol() {\n if (this.conf.wireProtocol) {\n return;\n }\n\n // Each retry is:\n // - ping request timeout (100 to 3_000ms)\n // - backoff delay (30 to 500ms)\n //\n // 30 attempts are ~43 seconds of overall waiting time.\n // Think twice on overall time this thing takes to complete when changing these parameters.\n // It may block UI when connecting to the server and loading projects list.\n const pingTimeoutFactor = 1.3;\n const maxPingTimeoutMs = 3_000;\n const retryOptions: RetryOptions = {\n type: 'exponentialBackoff',\n maxAttempts: 30,\n initialDelay: 30,\n backoffMultiplier: 1.3,\n jitter: 0.2,\n maxDelay: 500,\n };\n\n let attempt = 1;\n let pingTimeoutMs = 100;\n await retry(\n () => withTimeout(this.ping(), pingTimeoutMs),\n retryOptions,\n (e: unknown) => {\n if (isAbortedError(e)) {\n this.ops.logger?.info(`Wire proto autodetect: ping timed out after ${pingTimeoutMs}ms: attempt=${attempt}, wire=${this._wireProto}`);\n\n if (attempt % 2 === 0) {\n // We have 2 wire protocols to check. Increase timeout each 2 attempts.\n pingTimeoutMs = Math.min(\n Math.round(pingTimeoutMs * pingTimeoutFactor),\n maxPingTimeoutMs,\n );\n }\n } else {\n this.ops.logger?.info(`Wire proto autodetect: ping failed: attempt=${attempt}, wire=${this._wireProto}, err=${String(e)}`);\n }\n\n attempt++;\n const protocol = this._wireProto === 'grpc' ? 'rest' : 'grpc';\n this.ops.logger?.info(`Wire protocol autodetect next attempt: will try wire '${protocol}' with timeout ${pingTimeoutMs}ms`);\n this.initWireConnection(protocol);\n return true;\n });\n }\n\n public async license(): Promise<grpcTypes.MaintenanceAPI_License_Response> {\n const cl = this.clientProvider.get();\n if (cl instanceof GrpcPlApiClient) {\n return (await cl.license({})).response;\n } else {\n const resp = notEmpty((await cl.GET('/v1/license')).data, 'REST: empty response for license request');\n return {\n status: resp.status,\n isOk: resp.isOk,\n responseBody: Uint8Array.from(Buffer.from(resp.responseBody)),\n };\n }\n }\n\n public async authMethods(): Promise<grpcTypes.AuthAPI_ListMethods_Response> {\n const cl = this.clientProvider.get();\n if (cl instanceof GrpcPlApiClient) {\n return (await cl.authMethods({})).response;\n } else {\n return notEmpty((await cl.GET('/v1/auth/methods')).data, 'REST: empty response for auth methods request');\n }\n }\n\n public async txSync(txId: bigint): Promise<void> {\n const cl = this.clientProvider.get();\n if (cl instanceof GrpcPlApiClient) {\n await cl.txSync({ txId: BigInt(txId) });\n } else {\n (await cl.POST('/v1/tx-sync', { body: { txId: txId.toString() } }));\n }\n }\n\n createTx(rw: boolean, ops: PlCallOps = {}): LLPlTransaction {\n return new LLPlTransaction((abortSignal) => {\n let totalAbortSignal = abortSignal;\n if (ops.abortSignal) totalAbortSignal = AbortSignal.any([totalAbortSignal, ops.abortSignal]);\n\n const timeout = ops.timeout ?? (rw ? this.conf.defaultRWTransactionTimeout : this.conf.defaultROTransactionTimeout);\n\n const cl = this.clientProvider.get();\n if (cl instanceof GrpcPlApiClient) {\n return cl.tx({\n abort: totalAbortSignal,\n timeout,\n });\n }\n\n const wireConn = this.wireConnection;\n if (wireConn.type === 'rest') {\n // For REST/WebSocket protocol, timeout needs to be converted to AbortSignal\n if (timeout !== undefined) {\n totalAbortSignal = AbortSignal.any([totalAbortSignal, AbortSignal.timeout(timeout)]);\n }\n\n // The gRPC transport has the auth interceptor that already handles it, but here we need to refresh the auth information to be safe.\n this.refreshAuthInformationIfNeeded();\n\n const wsUrl = this.conf.ssl\n ? `wss://${this.conf.hostAndPort}/v1/ws/tx`\n : `ws://${this.conf.hostAndPort}/v1/ws/tx`;\n\n return new WebSocketBiDiStream(wsUrl,\n (msg) => TxAPI_ClientMessage.toBinary(msg),\n (data) => TxAPI_ServerMessage.fromBinary(new Uint8Array(data)),\n {\n abortSignal: totalAbortSignal,\n jwtToken: this.authInformation?.jwtToken,\n dispatcher: wireConn.Dispatcher,\n\n onComplete: async (stream) => stream.requests.send({\n // Ask server to gracefully close the stream on its side, if not done yet.\n requestId: 0,\n request: { oneofKind: 'streamClose', streamClose: {} },\n }),\n },\n );\n }\n\n throw new Error(`transactions are not supported for wire protocol ${this._wireProto}`);\n });\n }\n\n /** Closes underlying transport */\n public async close() {\n if (this.wireConnection.type === 'grpc') {\n this.wireConnection.Transport.close();\n } else {\n // TODO: close all WS connections\n }\n await this.httpDispatcher.destroy();\n }\n}\n"],"names":["GrpcPlApiClient","status","GrpcStatus"],"mappings":"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"}
|
package/dist/index.cjs
CHANGED
|
@@ -77,11 +77,15 @@ exports.toResourceId = transaction.toResourceId;
|
|
|
77
77
|
exports.DisconnectedError = errors.DisconnectedError;
|
|
78
78
|
exports.PlError = errors.PlError;
|
|
79
79
|
exports.PlErrorCodeNotFound = errors.PlErrorCodeNotFound;
|
|
80
|
+
exports.RESTError = errors.RESTError;
|
|
80
81
|
exports.RecoverablePlError = errors.RecoverablePlError;
|
|
81
82
|
exports.UnauthenticatedError = errors.UnauthenticatedError;
|
|
82
83
|
exports.UnrecoverablePlError = errors.UnrecoverablePlError;
|
|
84
|
+
exports.isAbortedError = errors.isAbortedError;
|
|
85
|
+
exports.isCancelError = errors.isCancelError;
|
|
83
86
|
exports.isConnectionProblem = errors.isConnectionProblem;
|
|
84
87
|
exports.isNotFoundError = errors.isNotFoundError;
|
|
88
|
+
exports.isTimeoutError = errors.isTimeoutError;
|
|
85
89
|
exports.isTimeoutOrCancelError = errors.isTimeoutOrCancelError;
|
|
86
90
|
exports.isUnauthenticated = errors.isUnauthenticated;
|
|
87
91
|
exports.rethrowMeaningfulError = errors.rethrowMeaningfulError;
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ export { AnonymousAuthInformation, DEFAULT_AUTH_MAX_REFRESH, DEFAULT_MAX_CACHE_B
|
|
|
5
5
|
export { PlClient } from './core/client.js';
|
|
6
6
|
export { addRTypeToMetadata, createRTypeRoutingHeader } from './core/driver.js';
|
|
7
7
|
export { PlTransaction, TxCommitConflict, field, isField, isFieldRef, isResource, isResourceId, isResourceRef, toFieldId, toGlobalFieldId, toGlobalResourceId, toResourceId } from './core/transaction.js';
|
|
8
|
-
export { DisconnectedError, PlError, PlErrorCodeNotFound, RecoverablePlError, UnauthenticatedError, UnrecoverablePlError, isConnectionProblem, isNotFoundError, isTimeoutOrCancelError, isUnauthenticated, rethrowMeaningfulError, throwPlNotFoundError } from './core/errors.js';
|
|
8
|
+
export { DisconnectedError, PlError, PlErrorCodeNotFound, RESTError, RecoverablePlError, UnauthenticatedError, UnrecoverablePlError, isAbortedError, isCancelError, isConnectionProblem, isNotFoundError, isTimeoutError, isTimeoutOrCancelError, isUnauthenticated, rethrowMeaningfulError, throwPlNotFoundError } from './core/errors.js';
|
|
9
9
|
export { defaultPlClient, tryGetFileConfig } from './core/default_client.js';
|
|
10
10
|
export { UnauthenticatedPlClient } from './core/unauth_client.js';
|
|
11
11
|
export { expirationFromAuthInformation, inferAuthRefreshTime } from './core/auth.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../../src/proto-rest/index.ts"],"sourcesContent":["//\n// This file is NOT autogenerated!\n//\n// After generating new clients from openapi specifications, add client types here.\n//\n\nimport type { paths as PlApiPaths } from './plapi';\nimport { default as createOpenApiClient, type Middleware, type Client } from 'openapi-fetch';\nimport { Dispatcher, fetch as undiciFetch } from 'undici';\nimport { rethrowMeaningfulError } from '../core/errors';\nimport { Code } from '../proto-grpc/google/rpc/code';\n\nexport { PlApiPaths };\nexport type PlRestClientType = Client<PlApiPaths>;\n\nexport type RestClientConfig = {\n hostAndPort: string;\n ssl: boolean;\n dispatcher: Dispatcher;\n middlewares: Middleware[];\n}\n\nexport function createClient<Paths extends {}>(opts: RestClientConfig): Client<Paths> {\n const scheme = opts.ssl ? 'https://' : 'http://';\n const client = createOpenApiClient<Paths>({\n baseUrl: `${scheme}${opts.hostAndPort}`,\n fetch: (input: Request): Promise<Response> => {\n // If body has already been consumed, clone the request\n const request = input.bodyUsed ? input.clone() : input;\n\n return undiciFetch(request.url, {\n body: request.body,\n cache: request.cache,\n credentials: request.credentials,\n dispatcher: opts.dispatcher,\n duplex: request.duplex,\n headers: request.headers,\n integrity: request.integrity,\n keepalive: request.keepalive,\n method: request.method,\n mode: request.mode,\n redirect: request.redirect,\n referrer: request.referrer,\n referrerPolicy: request.referrerPolicy,\n signal: request.signal,\n });\n },\n });\n client.use(errorHandlerMiddleware(), ...opts.middlewares);\n return client;\n}\n\nexport type ErrorResponse = {\n code: Code,\n message: string,\n details: any[],\n}\nexport async function parseResponseError(response: Response): Promise<{\n error?: ErrorResponse | string,\n origBody?: string,\n}>{\n if (response.status < 400) {\n return {};\n }\n\n let error: any = await response.clone().text();\n const origBody = error;\n try {\n error = JSON.parse(error) as ErrorResponse;\n } catch {\n }\n return {\n error: error,\n origBody\n };\n}\n\n/**\n * Parses all API responses and thrown error in case of error response.\n * Allows all callers to not bother about .error response field checking.\n */\nfunction errorHandlerMiddleware(): Middleware {\n return {\n onResponse: async ({ request: _request, response, options: _options }) => {\n const respErr = await parseResponseError(response);\n if (!respErr.error) {\n const { body, ...resOptions } = response;\n return new Response(body, { ...resOptions, status: response.status });\n }\n\n if (typeof respErr.error === 'string') {\n throw new Error(respErr.error);\n }\n\n rethrowMeaningfulError(respErr.error);\n },\n };\n}\n"],"names":["undiciFetch","rethrowMeaningfulError"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AAkBM,SAAU,YAAY,CAAmB,IAAsB,EAAA;AACnE,IAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,GAAG,UAAU,GAAG,SAAS;IAChD,MAAM,MAAM,GAAG,mBAAmB,CAAQ;AACxC,QAAA,OAAO,EAAE,CAAA,EAAG,MAAM,GAAG,IAAI,CAAC,WAAW,CAAA,CAAE;AACvC,QAAA,KAAK,EAAE,CAAC,KAAc,KAAuB;;AAE3C,YAAA,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,KAAK,EAAE,GAAG,KAAK;AAEtD,YAAA,OAAOA,YAAW,CAAC,OAAO,CAAC,GAAG,EAAE;gBAC9B,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,cAAc,EAAE,OAAO,CAAC,cAAc;gBACtC,MAAM,EAAE,OAAO,CAAC,MAAM;AACvB,aAAA,CAAC;QACJ,CAAC;AACF,KAAA,CAAC;IACF,MAAM,CAAC,GAAG,CAAC,sBAAsB,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC;AACzD,IAAA,OAAO,MAAM;AACf;AAOO,eAAe,kBAAkB,CAAC,QAAkB,EAAA;AAIzD,IAAA,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE;AACzB,QAAA,OAAO,EAAE;IACX;IAEA,IAAI,KAAK,GAAQ,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE;IAC9C,MAAM,QAAQ,GAAG,KAAK;AACtB,IAAA,IAAI;AACF,QAAA,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAkB;IAC5C;AAAE,IAAA,MAAM;IACR;IACA,OAAO;AACL,QAAA,KAAK,EAAE,KAAK;QACZ;KACD;AACH;AAEA;;;AAGG;AACH,SAAS,sBAAsB,GAAA;IAC7B,OAAO;AACL,QAAA,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAI;AACvE,YAAA,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,QAAQ,CAAC;AAClD,YAAA,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;gBAClB,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,EAAE,GAAG,QAAQ;AACxC,gBAAA,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;YACvE;AAEA,YAAA,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE;AACrC,gBAAA,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAChC;
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../../src/proto-rest/index.ts"],"sourcesContent":["//\n// This file is NOT autogenerated!\n//\n// After generating new clients from openapi specifications, add client types here.\n//\n\nimport type { paths as PlApiPaths } from './plapi';\nimport { default as createOpenApiClient, type Middleware, type Client } from 'openapi-fetch';\nimport { Dispatcher, fetch as undiciFetch } from 'undici';\nimport { RESTError, rethrowMeaningfulError } from '../core/errors';\nimport { Code } from '../proto-grpc/google/rpc/code';\n\nexport { PlApiPaths };\nexport type PlRestClientType = Client<PlApiPaths>;\n\nexport type RestClientConfig = {\n hostAndPort: string;\n ssl: boolean;\n dispatcher: Dispatcher;\n middlewares: Middleware[];\n}\n\nexport function createClient<Paths extends {}>(opts: RestClientConfig): Client<Paths> {\n const scheme = opts.ssl ? 'https://' : 'http://';\n const client = createOpenApiClient<Paths>({\n baseUrl: `${scheme}${opts.hostAndPort}`,\n fetch: (input: Request): Promise<Response> => {\n // If body has already been consumed, clone the request\n const request = input.bodyUsed ? input.clone() : input;\n\n return undiciFetch(request.url, {\n body: request.body,\n cache: request.cache,\n credentials: request.credentials,\n dispatcher: opts.dispatcher,\n duplex: request.duplex,\n headers: request.headers,\n integrity: request.integrity,\n keepalive: request.keepalive,\n method: request.method,\n mode: request.mode,\n redirect: request.redirect,\n referrer: request.referrer,\n referrerPolicy: request.referrerPolicy,\n signal: request.signal,\n });\n },\n });\n client.use(errorHandlerMiddleware(), ...opts.middlewares);\n return client;\n}\n\nexport type ErrorResponse = {\n code: Code,\n message: string,\n details: any[],\n}\nexport async function parseResponseError(response: Response): Promise<{\n error?: ErrorResponse | string,\n origBody?: string,\n}>{\n if (response.status < 400) {\n return {};\n }\n\n let error: any = await response.clone().text();\n const origBody = error;\n try {\n error = JSON.parse(error) as ErrorResponse;\n } catch {\n }\n return {\n error: error,\n origBody\n };\n}\n\n/**\n * Parses all API responses and thrown error in case of error response.\n * Allows all callers to not bother about .error response field checking.\n */\nfunction errorHandlerMiddleware(): Middleware {\n return {\n onResponse: async ({ request: _request, response, options: _options }) => {\n const respErr = await parseResponseError(response);\n if (!respErr.error) {\n const { body, ...resOptions } = response;\n return new Response(body, { ...resOptions, status: response.status });\n }\n\n if (typeof respErr.error === 'string') {\n throw new Error(respErr.error);\n }\n\n rethrowMeaningfulError(new RESTError(respErr.error));\n },\n };\n}\n"],"names":["undiciFetch","rethrowMeaningfulError","RESTError"],"mappings":";;;;;;AAAA;AACA;AACA;AACA;AACA;AAkBM,SAAU,YAAY,CAAmB,IAAsB,EAAA;AACnE,IAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,GAAG,UAAU,GAAG,SAAS;IAChD,MAAM,MAAM,GAAG,mBAAmB,CAAQ;AACxC,QAAA,OAAO,EAAE,CAAA,EAAG,MAAM,GAAG,IAAI,CAAC,WAAW,CAAA,CAAE;AACvC,QAAA,KAAK,EAAE,CAAC,KAAc,KAAuB;;AAE3C,YAAA,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,KAAK,EAAE,GAAG,KAAK;AAEtD,YAAA,OAAOA,YAAW,CAAC,OAAO,CAAC,GAAG,EAAE;gBAC9B,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,cAAc,EAAE,OAAO,CAAC,cAAc;gBACtC,MAAM,EAAE,OAAO,CAAC,MAAM;AACvB,aAAA,CAAC;QACJ,CAAC;AACF,KAAA,CAAC;IACF,MAAM,CAAC,GAAG,CAAC,sBAAsB,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC;AACzD,IAAA,OAAO,MAAM;AACf;AAOO,eAAe,kBAAkB,CAAC,QAAkB,EAAA;AAIzD,IAAA,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE;AACzB,QAAA,OAAO,EAAE;IACX;IAEA,IAAI,KAAK,GAAQ,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE;IAC9C,MAAM,QAAQ,GAAG,KAAK;AACtB,IAAA,IAAI;AACF,QAAA,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAkB;IAC5C;AAAE,IAAA,MAAM;IACR;IACA,OAAO;AACL,QAAA,KAAK,EAAE,KAAK;QACZ;KACD;AACH;AAEA;;;AAGG;AACH,SAAS,sBAAsB,GAAA;IAC7B,OAAO;AACL,QAAA,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAI;AACvE,YAAA,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,QAAQ,CAAC;AAClD,YAAA,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;gBAClB,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,EAAE,GAAG,QAAQ;AACxC,gBAAA,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;YACvE;AAEA,YAAA,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE;AACrC,gBAAA,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAChC;YAEAC,6BAAsB,CAAC,IAAIC,gBAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACtD,CAAC;KACF;AACH;;;;;"}
|
package/dist/proto-rest/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import createOpenApiClient from 'openapi-fetch';
|
|
2
2
|
import { fetch } from 'undici';
|
|
3
|
-
import { rethrowMeaningfulError } from '../core/errors.js';
|
|
3
|
+
import { rethrowMeaningfulError, RESTError } from '../core/errors.js';
|
|
4
4
|
|
|
5
5
|
//
|
|
6
6
|
// This file is NOT autogenerated!
|
|
@@ -66,7 +66,7 @@ function errorHandlerMiddleware() {
|
|
|
66
66
|
if (typeof respErr.error === 'string') {
|
|
67
67
|
throw new Error(respErr.error);
|
|
68
68
|
}
|
|
69
|
-
rethrowMeaningfulError(respErr.error);
|
|
69
|
+
rethrowMeaningfulError(new RESTError(respErr.error));
|
|
70
70
|
},
|
|
71
71
|
};
|
|
72
72
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../src/proto-rest/index.ts"],"sourcesContent":["//\n// This file is NOT autogenerated!\n//\n// After generating new clients from openapi specifications, add client types here.\n//\n\nimport type { paths as PlApiPaths } from './plapi';\nimport { default as createOpenApiClient, type Middleware, type Client } from 'openapi-fetch';\nimport { Dispatcher, fetch as undiciFetch } from 'undici';\nimport { rethrowMeaningfulError } from '../core/errors';\nimport { Code } from '../proto-grpc/google/rpc/code';\n\nexport { PlApiPaths };\nexport type PlRestClientType = Client<PlApiPaths>;\n\nexport type RestClientConfig = {\n hostAndPort: string;\n ssl: boolean;\n dispatcher: Dispatcher;\n middlewares: Middleware[];\n}\n\nexport function createClient<Paths extends {}>(opts: RestClientConfig): Client<Paths> {\n const scheme = opts.ssl ? 'https://' : 'http://';\n const client = createOpenApiClient<Paths>({\n baseUrl: `${scheme}${opts.hostAndPort}`,\n fetch: (input: Request): Promise<Response> => {\n // If body has already been consumed, clone the request\n const request = input.bodyUsed ? input.clone() : input;\n\n return undiciFetch(request.url, {\n body: request.body,\n cache: request.cache,\n credentials: request.credentials,\n dispatcher: opts.dispatcher,\n duplex: request.duplex,\n headers: request.headers,\n integrity: request.integrity,\n keepalive: request.keepalive,\n method: request.method,\n mode: request.mode,\n redirect: request.redirect,\n referrer: request.referrer,\n referrerPolicy: request.referrerPolicy,\n signal: request.signal,\n });\n },\n });\n client.use(errorHandlerMiddleware(), ...opts.middlewares);\n return client;\n}\n\nexport type ErrorResponse = {\n code: Code,\n message: string,\n details: any[],\n}\nexport async function parseResponseError(response: Response): Promise<{\n error?: ErrorResponse | string,\n origBody?: string,\n}>{\n if (response.status < 400) {\n return {};\n }\n\n let error: any = await response.clone().text();\n const origBody = error;\n try {\n error = JSON.parse(error) as ErrorResponse;\n } catch {\n }\n return {\n error: error,\n origBody\n };\n}\n\n/**\n * Parses all API responses and thrown error in case of error response.\n * Allows all callers to not bother about .error response field checking.\n */\nfunction errorHandlerMiddleware(): Middleware {\n return {\n onResponse: async ({ request: _request, response, options: _options }) => {\n const respErr = await parseResponseError(response);\n if (!respErr.error) {\n const { body, ...resOptions } = response;\n return new Response(body, { ...resOptions, status: response.status });\n }\n\n if (typeof respErr.error === 'string') {\n throw new Error(respErr.error);\n }\n\n rethrowMeaningfulError(respErr.error);\n },\n };\n}\n"],"names":["undiciFetch"],"mappings":";;;;AAAA;AACA;AACA;AACA;AACA;AAkBM,SAAU,YAAY,CAAmB,IAAsB,EAAA;AACnE,IAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,GAAG,UAAU,GAAG,SAAS;IAChD,MAAM,MAAM,GAAG,mBAAmB,CAAQ;AACxC,QAAA,OAAO,EAAE,CAAA,EAAG,MAAM,GAAG,IAAI,CAAC,WAAW,CAAA,CAAE;AACvC,QAAA,KAAK,EAAE,CAAC,KAAc,KAAuB;;AAE3C,YAAA,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,KAAK,EAAE,GAAG,KAAK;AAEtD,YAAA,OAAOA,KAAW,CAAC,OAAO,CAAC,GAAG,EAAE;gBAC9B,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,cAAc,EAAE,OAAO,CAAC,cAAc;gBACtC,MAAM,EAAE,OAAO,CAAC,MAAM;AACvB,aAAA,CAAC;QACJ,CAAC;AACF,KAAA,CAAC;IACF,MAAM,CAAC,GAAG,CAAC,sBAAsB,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC;AACzD,IAAA,OAAO,MAAM;AACf;AAOO,eAAe,kBAAkB,CAAC,QAAkB,EAAA;AAIzD,IAAA,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE;AACzB,QAAA,OAAO,EAAE;IACX;IAEA,IAAI,KAAK,GAAQ,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE;IAC9C,MAAM,QAAQ,GAAG,KAAK;AACtB,IAAA,IAAI;AACF,QAAA,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAkB;IAC5C;AAAE,IAAA,MAAM;IACR;IACA,OAAO;AACL,QAAA,KAAK,EAAE,KAAK;QACZ;KACD;AACH;AAEA;;;AAGG;AACH,SAAS,sBAAsB,GAAA;IAC7B,OAAO;AACL,QAAA,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAI;AACvE,YAAA,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,QAAQ,CAAC;AAClD,YAAA,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;gBAClB,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,EAAE,GAAG,QAAQ;AACxC,gBAAA,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;YACvE;AAEA,YAAA,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE;AACrC,gBAAA,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAChC;
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../src/proto-rest/index.ts"],"sourcesContent":["//\n// This file is NOT autogenerated!\n//\n// After generating new clients from openapi specifications, add client types here.\n//\n\nimport type { paths as PlApiPaths } from './plapi';\nimport { default as createOpenApiClient, type Middleware, type Client } from 'openapi-fetch';\nimport { Dispatcher, fetch as undiciFetch } from 'undici';\nimport { RESTError, rethrowMeaningfulError } from '../core/errors';\nimport { Code } from '../proto-grpc/google/rpc/code';\n\nexport { PlApiPaths };\nexport type PlRestClientType = Client<PlApiPaths>;\n\nexport type RestClientConfig = {\n hostAndPort: string;\n ssl: boolean;\n dispatcher: Dispatcher;\n middlewares: Middleware[];\n}\n\nexport function createClient<Paths extends {}>(opts: RestClientConfig): Client<Paths> {\n const scheme = opts.ssl ? 'https://' : 'http://';\n const client = createOpenApiClient<Paths>({\n baseUrl: `${scheme}${opts.hostAndPort}`,\n fetch: (input: Request): Promise<Response> => {\n // If body has already been consumed, clone the request\n const request = input.bodyUsed ? input.clone() : input;\n\n return undiciFetch(request.url, {\n body: request.body,\n cache: request.cache,\n credentials: request.credentials,\n dispatcher: opts.dispatcher,\n duplex: request.duplex,\n headers: request.headers,\n integrity: request.integrity,\n keepalive: request.keepalive,\n method: request.method,\n mode: request.mode,\n redirect: request.redirect,\n referrer: request.referrer,\n referrerPolicy: request.referrerPolicy,\n signal: request.signal,\n });\n },\n });\n client.use(errorHandlerMiddleware(), ...opts.middlewares);\n return client;\n}\n\nexport type ErrorResponse = {\n code: Code,\n message: string,\n details: any[],\n}\nexport async function parseResponseError(response: Response): Promise<{\n error?: ErrorResponse | string,\n origBody?: string,\n}>{\n if (response.status < 400) {\n return {};\n }\n\n let error: any = await response.clone().text();\n const origBody = error;\n try {\n error = JSON.parse(error) as ErrorResponse;\n } catch {\n }\n return {\n error: error,\n origBody\n };\n}\n\n/**\n * Parses all API responses and thrown error in case of error response.\n * Allows all callers to not bother about .error response field checking.\n */\nfunction errorHandlerMiddleware(): Middleware {\n return {\n onResponse: async ({ request: _request, response, options: _options }) => {\n const respErr = await parseResponseError(response);\n if (!respErr.error) {\n const { body, ...resOptions } = response;\n return new Response(body, { ...resOptions, status: response.status });\n }\n\n if (typeof respErr.error === 'string') {\n throw new Error(respErr.error);\n }\n\n rethrowMeaningfulError(new RESTError(respErr.error));\n },\n };\n}\n"],"names":["undiciFetch"],"mappings":";;;;AAAA;AACA;AACA;AACA;AACA;AAkBM,SAAU,YAAY,CAAmB,IAAsB,EAAA;AACnE,IAAA,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,GAAG,UAAU,GAAG,SAAS;IAChD,MAAM,MAAM,GAAG,mBAAmB,CAAQ;AACxC,QAAA,OAAO,EAAE,CAAA,EAAG,MAAM,GAAG,IAAI,CAAC,WAAW,CAAA,CAAE;AACvC,QAAA,KAAK,EAAE,CAAC,KAAc,KAAuB;;AAE3C,YAAA,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,GAAG,KAAK,CAAC,KAAK,EAAE,GAAG,KAAK;AAEtD,YAAA,OAAOA,KAAW,CAAC,OAAO,CAAC,GAAG,EAAE;gBAC9B,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,UAAU,EAAE,IAAI,CAAC,UAAU;gBAC3B,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,OAAO,EAAE,OAAO,CAAC,OAAO;gBACxB,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;gBACtB,IAAI,EAAE,OAAO,CAAC,IAAI;gBAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,cAAc,EAAE,OAAO,CAAC,cAAc;gBACtC,MAAM,EAAE,OAAO,CAAC,MAAM;AACvB,aAAA,CAAC;QACJ,CAAC;AACF,KAAA,CAAC;IACF,MAAM,CAAC,GAAG,CAAC,sBAAsB,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC;AACzD,IAAA,OAAO,MAAM;AACf;AAOO,eAAe,kBAAkB,CAAC,QAAkB,EAAA;AAIzD,IAAA,IAAI,QAAQ,CAAC,MAAM,GAAG,GAAG,EAAE;AACzB,QAAA,OAAO,EAAE;IACX;IAEA,IAAI,KAAK,GAAQ,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE;IAC9C,MAAM,QAAQ,GAAG,KAAK;AACtB,IAAA,IAAI;AACF,QAAA,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAkB;IAC5C;AAAE,IAAA,MAAM;IACR;IACA,OAAO;AACL,QAAA,KAAK,EAAE,KAAK;QACZ;KACD;AACH;AAEA;;;AAGG;AACH,SAAS,sBAAsB,GAAA;IAC7B,OAAO;AACL,QAAA,UAAU,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAI;AACvE,YAAA,MAAM,OAAO,GAAG,MAAM,kBAAkB,CAAC,QAAQ,CAAC;AAClD,YAAA,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;gBAClB,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,EAAE,GAAG,QAAQ;AACxC,gBAAA,OAAO,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,GAAG,UAAU,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;YACvE;AAEA,YAAA,IAAI,OAAO,OAAO,CAAC,KAAK,KAAK,QAAQ,EAAE;AACrC,gBAAA,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;YAChC;YAEA,sBAAsB,CAAC,IAAI,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACtD,CAAC;KACF;AACH;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@milaboratories/pl-client",
|
|
3
|
-
"version": "2.16.
|
|
3
|
+
"version": "2.16.16",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=22.19.0"
|
|
6
6
|
},
|
|
@@ -36,20 +36,22 @@
|
|
|
36
36
|
"utility-types": "^3.11.0",
|
|
37
37
|
"yaml": "^2.8.0",
|
|
38
38
|
"@milaboratories/pl-http": "1.2.0",
|
|
39
|
-
"@milaboratories/
|
|
40
|
-
"@milaboratories/
|
|
39
|
+
"@milaboratories/pl-model-common": "1.21.10",
|
|
40
|
+
"@milaboratories/ts-helpers": "1.5.4"
|
|
41
41
|
},
|
|
42
42
|
"devDependencies": {
|
|
43
43
|
"@protobuf-ts/plugin": "2.11.1",
|
|
44
44
|
"openapi-typescript": "^7.10.0",
|
|
45
45
|
"@types/http-proxy": "^1.17.16",
|
|
46
46
|
"@types/node": "~24.5.2",
|
|
47
|
-
"@vitest/coverage-
|
|
48
|
-
"vitest": "^4.0.
|
|
47
|
+
"@vitest/coverage-istanbul": "^4.0.16",
|
|
48
|
+
"vitest": "^4.0.16",
|
|
49
|
+
"eslint": "^9.25.1",
|
|
49
50
|
"typescript": "~5.6.3",
|
|
50
|
-
"@milaboratories/build-configs": "1.2.
|
|
51
|
-
"@milaboratories/ts-builder": "1.2.
|
|
52
|
-
"@milaboratories/ts-configs": "1.2.0"
|
|
51
|
+
"@milaboratories/build-configs": "1.2.1",
|
|
52
|
+
"@milaboratories/ts-builder": "1.2.1",
|
|
53
|
+
"@milaboratories/ts-configs": "1.2.0",
|
|
54
|
+
"@milaboratories/eslint-config": "1.0.5"
|
|
53
55
|
},
|
|
54
56
|
"scripts": {
|
|
55
57
|
"type-check": "ts-builder types --target node",
|
package/src/core/client.ts
CHANGED
|
@@ -7,7 +7,7 @@ import { createHash } from 'node:crypto';
|
|
|
7
7
|
import type { OptionalResourceId, ResourceId } from './types';
|
|
8
8
|
import { ensureResourceIdNotNull, isNullResourceId, NullResourceId } from './types';
|
|
9
9
|
import { ClientRoot } from '../helpers/pl';
|
|
10
|
-
import type { RetryOptions } from '@milaboratories/ts-helpers';
|
|
10
|
+
import type { MiLogger, RetryOptions } from '@milaboratories/ts-helpers';
|
|
11
11
|
import { assertNever, createRetryState, nextRetryStateOrError } from '@milaboratories/ts-helpers';
|
|
12
12
|
import type { PlDriver, PlDriverDefinition } from './driver';
|
|
13
13
|
import type { MaintenanceAPI_Ping_Response, MaintenanceAPI_License_Response } from '../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api';
|
|
@@ -90,6 +90,7 @@ export class PlClient {
|
|
|
90
90
|
ops: {
|
|
91
91
|
statusListener?: PlConnectionStatusListener;
|
|
92
92
|
finalPredicate?: FinalResourceDataPredicate;
|
|
93
|
+
logger?: MiLogger;
|
|
93
94
|
} = {},
|
|
94
95
|
) {
|
|
95
96
|
const conf = typeof configOrAddress === 'string' ? plAddressToConfig(configOrAddress) : configOrAddress;
|
|
@@ -389,6 +390,7 @@ export class PlClient {
|
|
|
389
390
|
auth: AuthOps,
|
|
390
391
|
ops: {
|
|
391
392
|
statusListener?: PlConnectionStatusListener;
|
|
393
|
+
logger?: MiLogger;
|
|
392
394
|
} = {},
|
|
393
395
|
) {
|
|
394
396
|
const pl = new PlClient(configOrAddress, auth, ops);
|
package/src/core/errors.ts
CHANGED
|
@@ -3,51 +3,81 @@ import { Aborted } from '@milaboratories/ts-helpers';
|
|
|
3
3
|
import { Code } from '../proto-grpc/google/rpc/code';
|
|
4
4
|
|
|
5
5
|
export function isConnectionProblem(err: unknown, nested: boolean = false): boolean {
|
|
6
|
+
if (err === undefined || err === null) return false;
|
|
7
|
+
|
|
6
8
|
if (err instanceof DisconnectedError) return true;
|
|
7
9
|
if ((err as any).name == 'RpcError' && (err as any).code == 'UNAVAILABLE') return true;
|
|
8
|
-
if ((err as any).code == Code.UNAVAILABLE) return true;
|
|
9
|
-
if ((err as any).cause !== undefined && !nested)
|
|
10
|
-
// nested limits the depth of search
|
|
11
|
-
return isConnectionProblem((err as any).cause, true);
|
|
10
|
+
if ((err as any).name == 'RESTError' && (err as any).status.code == Code.UNAVAILABLE) return true;
|
|
11
|
+
if ((err as any).cause !== undefined && !nested) return isConnectionProblem((err as any).cause, true);
|
|
12
12
|
return false;
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
export function isUnauthenticated(err: unknown, nested: boolean = false): boolean {
|
|
16
|
+
if (err === undefined || err === null) return false;
|
|
17
|
+
|
|
16
18
|
if (err instanceof UnauthenticatedError) return true;
|
|
17
19
|
if ((err as any).name == 'RpcError' && (err as any).code == 'UNAUTHENTICATED') return true;
|
|
18
|
-
if ((err as any).code == Code.UNAUTHENTICATED) return true;
|
|
19
|
-
if ((err as any).cause !== undefined && !nested)
|
|
20
|
-
// nested limits the depth of search
|
|
21
|
-
return isUnauthenticated((err as any).cause, true);
|
|
20
|
+
if ((err as any).name == 'RESTError' && (err as any).status.code == Code.UNAUTHENTICATED) return true;
|
|
21
|
+
if ((err as any).cause !== undefined && !nested) return isUnauthenticated((err as any).cause, true);
|
|
22
22
|
return false;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
export function
|
|
26
|
-
if (err
|
|
25
|
+
export function isTimeoutError(err: unknown, nested: boolean = false): boolean {
|
|
26
|
+
if (err === undefined || err === null) return false;
|
|
27
|
+
|
|
27
28
|
if ((err as any).name == 'TimeoutError') return true;
|
|
29
|
+
if ((err as any).name == 'RpcError' && (err as any).code == 'DEADLINE_EXCEEDED') return true;
|
|
30
|
+
if ((err as any).name == 'RESTError' && (err as any).status.code == Code.DEADLINE_EXCEEDED) return true;
|
|
31
|
+
if ((err as any).cause !== undefined && !nested) return isTimeoutError((err as any).cause, true);
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export function isCancelError(err: unknown, nested: boolean = false): boolean {
|
|
36
|
+
if (err === undefined || err === null) return false;
|
|
37
|
+
|
|
38
|
+
if ((err as any).name == 'RpcError' && (err as any).code == 'CANCELLED') return true;
|
|
39
|
+
if ((err as any).name == 'RESTError' && (err as any).status.code == Code.CANCELLED) return true;
|
|
40
|
+
if ((err as any).cause !== undefined && !nested) return isCancelError((err as any).cause, true);
|
|
41
|
+
return false;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function isAbortedError(err: unknown, nested: boolean = false): boolean {
|
|
45
|
+
if (err === undefined || err === null) return false;
|
|
46
|
+
|
|
47
|
+
if (err instanceof Aborted || (err as any).name == 'AbortError') return true;
|
|
28
48
|
if ((err as any).code == 'ABORT_ERR') return true;
|
|
29
|
-
|
|
30
|
-
if (err
|
|
31
|
-
if ((err as any).code == Code.ABORTED) return true;
|
|
32
|
-
if (
|
|
33
|
-
(err as any).name == 'RpcError'
|
|
34
|
-
&& ((err as any).code == 'CANCELLED' || (err as any).code == 'DEADLINE_EXCEEDED')
|
|
35
|
-
)
|
|
36
|
-
return true;
|
|
37
|
-
if ((err as any).code == Code.CANCELLED || (err as any).code == Code.DEADLINE_EXCEEDED)
|
|
38
|
-
return true;
|
|
39
|
-
if ((err as any).cause !== undefined && !nested)
|
|
40
|
-
// nested limits the depth of search
|
|
41
|
-
return isTimeoutOrCancelError((err as any).cause, true);
|
|
49
|
+
if (err instanceof DOMException && err.code === DOMException.ABORT_ERR) return true; // WebSocket error
|
|
50
|
+
if ((err as any).name == 'RpcError' && (err as any).code == 'ABORTED') return true;
|
|
51
|
+
if ((err as any).name == 'RESTError' && (err as any).status.code == Code.ABORTED) return true;
|
|
52
|
+
if ((err as any).cause !== undefined && !nested) isAbortedError((err as any).cause, true);
|
|
42
53
|
return false;
|
|
43
54
|
}
|
|
44
55
|
|
|
45
|
-
export
|
|
56
|
+
export function isTimeoutOrCancelError(err: unknown, nested: boolean = false): boolean {
|
|
57
|
+
if (err === undefined || err === null) return false;
|
|
58
|
+
|
|
59
|
+
if (isAbortedError(err, true)) return true;
|
|
60
|
+
if (isTimeoutError(err, true)) return true;
|
|
61
|
+
if (isCancelError(err, true)) return true;
|
|
62
|
+
if ((err as any).cause !== undefined && !nested) return isTimeoutOrCancelError((err as any).cause, true);
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function isNotFoundError(err: unknown, nested: boolean = false): boolean {
|
|
67
|
+
if (err === undefined || err === null) return false;
|
|
68
|
+
|
|
69
|
+
if ((err as any).name == 'RpcError' && (err as any).code == 'NOT_FOUND') return true;
|
|
70
|
+
if ((err as any).name == 'RESTError' && (err as any).status.code == Code.NOT_FOUND) return true;
|
|
71
|
+
if ((err as any).cause !== undefined && !nested) return isNotFoundError((err as any).cause, true);
|
|
72
|
+
return err instanceof RecoverablePlError && err.status.code === PlErrorCodeNotFound;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export const PlErrorCodeNotFound: number = Code.NOT_FOUND;
|
|
46
76
|
|
|
47
77
|
export class PlError extends Error {
|
|
48
78
|
name = 'PlError';
|
|
49
|
-
constructor(public readonly status: Status) {
|
|
50
|
-
super(`code=${status.code} ${status.message}
|
|
79
|
+
constructor(public readonly status: Status, opts?: ErrorOptions) {
|
|
80
|
+
super(`code=${status.code} ${status.message}`, opts);
|
|
51
81
|
}
|
|
52
82
|
}
|
|
53
83
|
|
|
@@ -69,12 +99,6 @@ export class UnrecoverablePlError extends PlError {
|
|
|
69
99
|
}
|
|
70
100
|
}
|
|
71
101
|
|
|
72
|
-
export function isNotFoundError(err: unknown, nested: boolean = false): boolean {
|
|
73
|
-
if ((err as any).name == 'RpcError' && (err as any).code == 'NOT_FOUND') return true;
|
|
74
|
-
if ((err as any).cause !== undefined && !nested) return isNotFoundError((err as any).cause, true);
|
|
75
|
-
return err instanceof RecoverablePlError && err.status.code === PlErrorCodeNotFound;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
102
|
export class UnauthenticatedError extends Error {
|
|
79
103
|
name = 'UnauthenticatedError';
|
|
80
104
|
constructor(message: string) {
|
|
@@ -89,6 +113,13 @@ export class DisconnectedError extends Error {
|
|
|
89
113
|
}
|
|
90
114
|
}
|
|
91
115
|
|
|
116
|
+
export class RESTError extends PlError {
|
|
117
|
+
name = 'RESTError';
|
|
118
|
+
constructor(status: Status, opts?: ErrorOptions) {
|
|
119
|
+
super(status, opts);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
92
123
|
export function rethrowMeaningfulError(error: any, wrapIfUnknown: boolean = false): never {
|
|
93
124
|
if (isUnauthenticated(error)) {
|
|
94
125
|
if (error instanceof UnauthenticatedError) throw error;
|
|
@@ -7,6 +7,15 @@ import { test, expect } from 'vitest';
|
|
|
7
7
|
|
|
8
8
|
import { UnauthenticatedError } from './errors';
|
|
9
9
|
|
|
10
|
+
test('wire protocol detection', async () => {
|
|
11
|
+
const { conf, auth } = await getTestClientConf();
|
|
12
|
+
const expectedWireProtocol = conf.wireProtocol ?? 'grpc';
|
|
13
|
+
conf.wireProtocol = undefined;
|
|
14
|
+
|
|
15
|
+
const client = await LLPlClient.build(conf, { auth });
|
|
16
|
+
expect(client.wireProtocol).toBe(expectedWireProtocol);
|
|
17
|
+
});
|
|
18
|
+
|
|
10
19
|
test('authenticated instance test', async () => {
|
|
11
20
|
const client = await getTestLLClient();
|
|
12
21
|
const tx = client.createTx(true);
|
package/src/core/ll_client.ts
CHANGED
|
@@ -30,6 +30,8 @@ import { notEmpty, retry, withTimeout, type RetryOptions } from '@milaboratories
|
|
|
30
30
|
import { Code } from '../proto-grpc/google/rpc/code';
|
|
31
31
|
import { WebSocketBiDiStream } from './websocket_stream';
|
|
32
32
|
import { TxAPI_ClientMessage, TxAPI_ServerMessage } from '../proto-grpc/github.com/milaboratory/pl/plapi/plapiproto/api';
|
|
33
|
+
import type { MiLogger } from '@milaboratories/ts-helpers';
|
|
34
|
+
import { isAbortedError } from './errors';
|
|
33
35
|
|
|
34
36
|
export interface PlCallOps {
|
|
35
37
|
timeout?: number;
|
|
@@ -86,6 +88,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
86
88
|
auth?: AuthOps;
|
|
87
89
|
statusListener?: PlConnectionStatusListener;
|
|
88
90
|
shouldUseGzip?: boolean;
|
|
91
|
+
logger?: MiLogger;
|
|
89
92
|
} = {},
|
|
90
93
|
) {
|
|
91
94
|
const conf = typeof configOrAddress === 'string' ? plAddressToConfig(configOrAddress) : configOrAddress;
|
|
@@ -101,6 +104,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
101
104
|
auth?: AuthOps;
|
|
102
105
|
statusListener?: PlConnectionStatusListener;
|
|
103
106
|
shouldUseGzip?: boolean;
|
|
107
|
+
logger?: MiLogger;
|
|
104
108
|
} = {},
|
|
105
109
|
) {
|
|
106
110
|
const { auth, statusListener } = ops;
|
|
@@ -443,7 +447,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
443
447
|
body: { expiration: `${ttlSeconds}s` },
|
|
444
448
|
headers,
|
|
445
449
|
});
|
|
446
|
-
return notEmpty((await resp).data).token;
|
|
450
|
+
return notEmpty((await resp).data, 'REST: empty response for JWT token request').token;
|
|
447
451
|
}
|
|
448
452
|
}
|
|
449
453
|
|
|
@@ -452,7 +456,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
452
456
|
if (cl instanceof GrpcPlApiClient) {
|
|
453
457
|
return (await cl.ping({})).response;
|
|
454
458
|
} else {
|
|
455
|
-
return notEmpty((await cl.GET('/v1/ping')).data);
|
|
459
|
+
return notEmpty((await cl.GET('/v1/ping')).data, 'REST: empty response for ping request');
|
|
456
460
|
}
|
|
457
461
|
}
|
|
458
462
|
|
|
@@ -466,20 +470,50 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
466
470
|
return;
|
|
467
471
|
}
|
|
468
472
|
|
|
473
|
+
// Each retry is:
|
|
474
|
+
// - ping request timeout (100 to 3_000ms)
|
|
475
|
+
// - backoff delay (30 to 500ms)
|
|
476
|
+
//
|
|
477
|
+
// 30 attempts are ~43 seconds of overall waiting time.
|
|
478
|
+
// Think twice on overall time this thing takes to complete when changing these parameters.
|
|
479
|
+
// It may block UI when connecting to the server and loading projects list.
|
|
480
|
+
const pingTimeoutFactor = 1.3;
|
|
481
|
+
const maxPingTimeoutMs = 3_000;
|
|
469
482
|
const retryOptions: RetryOptions = {
|
|
470
483
|
type: 'exponentialBackoff',
|
|
471
|
-
maxAttempts:
|
|
484
|
+
maxAttempts: 30,
|
|
472
485
|
initialDelay: 30,
|
|
473
486
|
backoffMultiplier: 1.3,
|
|
474
487
|
jitter: 0.2,
|
|
475
488
|
maxDelay: 500,
|
|
476
489
|
};
|
|
477
490
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
491
|
+
let attempt = 1;
|
|
492
|
+
let pingTimeoutMs = 100;
|
|
493
|
+
await retry(
|
|
494
|
+
() => withTimeout(this.ping(), pingTimeoutMs),
|
|
495
|
+
retryOptions,
|
|
496
|
+
(e: unknown) => {
|
|
497
|
+
if (isAbortedError(e)) {
|
|
498
|
+
this.ops.logger?.info(`Wire proto autodetect: ping timed out after ${pingTimeoutMs}ms: attempt=${attempt}, wire=${this._wireProto}`);
|
|
499
|
+
|
|
500
|
+
if (attempt % 2 === 0) {
|
|
501
|
+
// We have 2 wire protocols to check. Increase timeout each 2 attempts.
|
|
502
|
+
pingTimeoutMs = Math.min(
|
|
503
|
+
Math.round(pingTimeoutMs * pingTimeoutFactor),
|
|
504
|
+
maxPingTimeoutMs,
|
|
505
|
+
);
|
|
506
|
+
}
|
|
507
|
+
} else {
|
|
508
|
+
this.ops.logger?.info(`Wire proto autodetect: ping failed: attempt=${attempt}, wire=${this._wireProto}, err=${String(e)}`);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
attempt++;
|
|
512
|
+
const protocol = this._wireProto === 'grpc' ? 'rest' : 'grpc';
|
|
513
|
+
this.ops.logger?.info(`Wire protocol autodetect next attempt: will try wire '${protocol}' with timeout ${pingTimeoutMs}ms`);
|
|
514
|
+
this.initWireConnection(protocol);
|
|
515
|
+
return true;
|
|
516
|
+
});
|
|
483
517
|
}
|
|
484
518
|
|
|
485
519
|
public async license(): Promise<grpcTypes.MaintenanceAPI_License_Response> {
|
|
@@ -487,7 +521,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
487
521
|
if (cl instanceof GrpcPlApiClient) {
|
|
488
522
|
return (await cl.license({})).response;
|
|
489
523
|
} else {
|
|
490
|
-
const resp = notEmpty((await cl.GET('/v1/license')).data);
|
|
524
|
+
const resp = notEmpty((await cl.GET('/v1/license')).data, 'REST: empty response for license request');
|
|
491
525
|
return {
|
|
492
526
|
status: resp.status,
|
|
493
527
|
isOk: resp.isOk,
|
|
@@ -501,7 +535,7 @@ export class LLPlClient implements WireClientProviderFactory {
|
|
|
501
535
|
if (cl instanceof GrpcPlApiClient) {
|
|
502
536
|
return (await cl.authMethods({})).response;
|
|
503
537
|
} else {
|
|
504
|
-
return notEmpty((await cl.GET('/v1/auth/methods')).data);
|
|
538
|
+
return notEmpty((await cl.GET('/v1/auth/methods')).data, 'REST: empty response for auth methods request');
|
|
505
539
|
}
|
|
506
540
|
}
|
|
507
541
|
|