| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374 |
- import { ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common';
- import { GqlExecutionContext } from '@nestjs/graphql';
- import { Observable } from 'rxjs';
- import { map } from 'rxjs/operators';
- import { Type } from '../../../../shared/shared-types';
- import { AssetStorageStrategy } from '../../config/asset-storage-strategy/asset-storage-strategy';
- import { ConfigService } from '../../config/config.service';
- import { Asset } from '../../entity/asset/asset.entity';
- /**
- * Transforms outputs so that any Asset instances are run through the {@link AssetStorageStrategy.toAbsoluteUrl}
- * method before being returned in the response.
- */
- @Injectable()
- export class AssetInterceptor implements NestInterceptor {
- private readonly toAbsoluteUrl: AssetStorageStrategy['toAbsoluteUrl'] | undefined;
- constructor(private configService: ConfigService) {
- const { assetOptions } = this.configService;
- if (assetOptions.assetStorageStrategy.toAbsoluteUrl) {
- this.toAbsoluteUrl = assetOptions.assetStorageStrategy.toAbsoluteUrl.bind(
- assetOptions.assetStorageStrategy,
- );
- }
- }
- intercept<T = any>(context: ExecutionContext, call$: Observable<T>): Observable<T> {
- const toAbsoluteUrl = this.toAbsoluteUrl;
- if (toAbsoluteUrl === undefined) {
- return call$;
- }
- const ctx = GqlExecutionContext.create(context).getContext();
- const request = ctx.req;
- return call$.pipe(
- map(data => {
- visitType(data, [Asset, 'productPreview', 'productVariantPreview'], asset => {
- if (asset instanceof Asset) {
- asset.preview = toAbsoluteUrl(request, asset.preview);
- asset.source = toAbsoluteUrl(request, asset.source);
- } else {
- asset = toAbsoluteUrl(request, asset);
- }
- return asset;
- });
- return data;
- }),
- );
- }
- }
- /**
- * Traverses the object and when encountering a property with a value which
- * is an instance of class T, invokes the visitor function on that value.
- */
- function visitType<T>(obj: any, types: Array<Type<T> | string>, visit: (instance: T | string) => T | string) {
- const keys = Object.keys(obj || {});
- for (const key of keys) {
- const value = obj[key];
- for (const type of types) {
- if (typeof type === 'string') {
- if (type === key) {
- obj[key] = visit(value);
- }
- } else if (value instanceof type) {
- visit(value);
- }
- }
- if (typeof value === 'object') {
- visitType(value, types, visit);
- }
- }
- }
|