@ngx-grpc/core
Version:
Angular gRPC framework: core package
281 lines (272 loc) • 12.4 kB
JavaScript
import * as i0 from '@angular/core';
import { InjectionToken, Injectable, Optional, Inject, NgModule } from '@angular/core';
import { GrpcCallType, GrpcDataEvent, GrpcStatusEvent } from '@ngx-grpc/common';
import { isObservable, throwError, of } from 'rxjs';
import { tap, switchMap, filter, map } from 'rxjs/operators';
/**
* Use this injection token to register the GrpcClientFactory
*
* Example:
*
* ```
* providers: [
* { provide: GRPC_CLIENT_FACTORY, useClass: MyClientFactory },
* ]
* ```
*/
const GRPC_CLIENT_FACTORY = new InjectionToken('GRPC_CLIENT_FACTORY');
/**
* Use this injection token to add interceptors
*
* Example:
*
* ```
* providers: [
* { provide: GRPC_INTERCEPTORS, useClass: MyInterceptor, multi: true },
* ]
* ```
*/
const GRPC_INTERCEPTORS = new InjectionToken('GRPC_INTERCEPTORS');
/**
* Core gRPC transport class. Implements creation and binding of RPCs to the clients.
* There is a root GrpcHandler that handles all initial requests;
* however for every interception a new instance of GrpcHandler is created and passed to the interceptor
*/
class GrpcHandler {
constructor(configuredInterceptors) {
this.interceptors = !configuredInterceptors ? [] : Array.isArray(configuredInterceptors) ? configuredInterceptors : [configuredInterceptors];
}
/**
* Handles the gRPC request passing it through the interceptors array
* Recursively calls all interceptors with a new instance of the GrpcHandler
*
* @param request a GrpcRequest to execute
* @returns Observable of events returned by the GrpcClient implementation
*/
handle(request) {
const interceptors = (this.interceptors || []).slice();
const interceptor = interceptors.shift();
if (interceptor) {
return interceptor.intercept(request, new GrpcHandler(interceptors));
}
switch (request.type) {
case GrpcCallType.unary: return request.client.unary(request.path, this.message(request.requestData), request.requestMetadata, request.requestClass, request.responseClass);
case GrpcCallType.serverStream: return request.client.serverStream(request.path, this.message(request.requestData), request.requestMetadata, request.requestClass, request.responseClass);
case GrpcCallType.clientStream: return request.client.clientStream(request.path, this.stream(request.requestData), request.requestMetadata, request.requestClass, request.responseClass);
case GrpcCallType.bidiStream: return request.client.bidiStream(request.path, this.stream(request.requestData), request.requestMetadata, request.requestClass, request.responseClass);
}
}
message(p) {
if (!isObservable(p)) {
return p;
}
throw new Error('Expected Message, got Observable');
}
stream(p) {
if (isObservable(p)) {
return p;
}
throw new Error('Expected Observable, got message');
}
}
GrpcHandler.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: GrpcHandler, deps: [{ token: GRPC_INTERCEPTORS, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
GrpcHandler.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: GrpcHandler });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: GrpcHandler, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [GRPC_INTERCEPTORS]
}] }]; } });
class GrpcCoreModule {
/**
* Create GrpcCoreModule for using in AppModule (application root module)
*/
static forRoot() {
return {
ngModule: GrpcCoreModule,
providers: [
GrpcHandler,
],
};
}
/**
* Create GrpcCoreModule for using in children modules (incl. lazy modules)
*/
static forChild() {
return {
ngModule: GrpcCoreModule,
providers: [
GrpcHandler,
],
};
}
}
GrpcCoreModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: GrpcCoreModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
GrpcCoreModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: GrpcCoreModule });
GrpcCoreModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: GrpcCoreModule });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: GrpcCoreModule, decorators: [{
type: NgModule
}] });
/**
* A configuration for GrpcLoggerInterceptor
*
* Example:
*
* ```
* providers: [
* { provide: GRPC_LOGGER_SETTINGS, useValue: { enabled: true } },
* ]
* ```
*
* or more complex:
*
* ```
* providers: [
* { provide: GRPC_LOGGER_SETTINGS, useFactory: () => { enabled: localStorage.getItem('GRPC_LOGGER_SETTINGS') === 'true' || !environment.prod } },
* ]
* ```
*/
const GRPC_LOGGER_SETTINGS = new InjectionToken('GRPC_LOGGER_SETTINGS');
/**
* Interceptor that implements logging of every request to the browser console
*
* Can be enabled / disabled by GRPC_LOGGER_ENABLED injection token
*/
class GrpcLoggerInterceptor {
constructor(settings = {}) {
this.clientDataStyle = 'color: #eb0edc;';
this.dataStyle = 'color: #5c7ced;';
this.errorStyle = 'color: #f00505;';
this.statusOkStyle = 'color: #0ffcf5;';
this.settings = {
enabled: settings.enabled ?? true,
logClientSettings: settings.logClientSettings ?? true,
logMetadata: settings.logMetadata ?? true,
logStatusCodeOk: settings.logStatusCodeOk ?? false,
requestMapper: settings.requestMapper ?? ((msg) => msg.toObject()),
responseMapper: settings.responseMapper ?? ((msg) => msg.toObject()),
};
}
intercept(request, next) {
if (this.settings.enabled) {
const id = ++GrpcLoggerInterceptor.requestId;
const start = Date.now();
// check if client streaming, then push each value separately
if (isObservable(request.requestData)) {
request.requestData = request.requestData.pipe(tap(msg => {
console.groupCollapsed(`%c#${id}: ${Date.now() - start}ms -> ${request.path}`, this.clientDataStyle);
console.log('%c>>', this.clientDataStyle, this.settings.requestMapper(msg));
console.groupEnd();
}));
}
// handle unary calls and server streaming in the same manner
return next.handle(request).pipe(tap(event => {
const style = event instanceof GrpcDataEvent ? this.dataStyle : event.statusCode !== 0 ? this.errorStyle : this.statusOkStyle;
const openGroup = () => console.groupCollapsed(`%c#${id}: ${Date.now() - start}ms -> ${request.path}`, style);
const printSettings = () => {
if (this.settings.logClientSettings) {
console.log('%csc', style, request.client.getSettings());
}
};
const printMetadata = () => {
if (this.settings.logMetadata) {
console.log('%c**', style, request.requestMetadata.toObject());
}
};
const printRequest = () => console.log('%c>>', style, isObservable(request.requestData) ? '<see above>' : this.settings.requestMapper(request.requestData));
const closeGroup = () => console.groupEnd();
if (event instanceof GrpcDataEvent) {
openGroup();
printSettings();
printRequest();
printMetadata();
console.log('%c<<', style, this.settings.responseMapper(event.data));
closeGroup();
}
else if (event.statusCode !== 0) {
openGroup();
printSettings();
printRequest();
printMetadata();
console.log('%c<<', style, event);
closeGroup();
}
else if (event.statusCode === 0 && this.settings.logStatusCodeOk) {
openGroup();
printSettings();
printRequest();
printMetadata();
console.log('%c<<', style, event);
closeGroup();
}
}));
}
return next.handle(request);
}
}
GrpcLoggerInterceptor.requestId = 0;
GrpcLoggerInterceptor.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: GrpcLoggerInterceptor, deps: [{ token: GRPC_LOGGER_SETTINGS, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
GrpcLoggerInterceptor.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: GrpcLoggerInterceptor });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: GrpcLoggerInterceptor, decorators: [{
type: Injectable
}], ctorParameters: function () { return [{ type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [GRPC_LOGGER_SETTINGS]
}] }]; } });
class GrpcLoggerModule {
/**
* Create GrpcLoggerModule for using in AppModule (application root module)
* You can provide the options here instead of injecting corresponding tokens separately
*/
static forRoot(options) {
const providers = [{ provide: GRPC_INTERCEPTORS, useClass: GrpcLoggerInterceptor, multi: true }];
if (options?.settings) {
providers.push({ provide: GRPC_LOGGER_SETTINGS, useValue: options.settings });
}
return { ngModule: GrpcLoggerModule, providers };
}
/**
* Create GrpcCoreModule for using in children modules (incl. lazy modules)
* You can provide the options here instead of injecting corresponding tokens separately
*/
static forChild(options) {
const providers = [{ provide: GRPC_INTERCEPTORS, useClass: GrpcLoggerInterceptor, multi: true }];
if (options?.settings) {
providers.push({ provide: GRPC_LOGGER_SETTINGS, useValue: options.settings });
}
return { ngModule: GrpcLoggerModule, providers };
}
}
GrpcLoggerModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: GrpcLoggerModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
GrpcLoggerModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: GrpcLoggerModule });
GrpcLoggerModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: GrpcLoggerModule });
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.2.3", ngImport: i0, type: GrpcLoggerModule, decorators: [{
type: NgModule
}] });
/**
* RxJS operator
* When applied to gRPC events emits error for status events with a non-zero code (includes throwStatusErrors)
*
* @return Observable of gRPC events
*/
function throwStatusErrors() {
return (source$) => source$.pipe(switchMap(event => event instanceof GrpcStatusEvent && event.statusCode ? throwError(event) : of(event)));
}
/**
* RxJS operator
* When applied to gRPC events stream extracts and returns only messages
*
* @return Observable of messages
*/
function takeMessages() {
return (source$) => source$.pipe(filter(event => event instanceof GrpcDataEvent), map((event) => event.data));
}
/**
* Generated bundle index. Do not edit.
*/
export { GRPC_CLIENT_FACTORY, GRPC_INTERCEPTORS, GRPC_LOGGER_SETTINGS, GrpcCoreModule, GrpcHandler, GrpcLoggerInterceptor, GrpcLoggerModule, takeMessages, throwStatusErrors };
//# sourceMappingURL=ngx-grpc-core.mjs.map