Skip to content

Commit

Permalink
fix(core): Correctly prefix asset urls for resolved properties
Browse files Browse the repository at this point in the history
Closes #146
  • Loading branch information
michaelbromley committed Aug 27, 2019
1 parent f687cc8 commit 0517b6c
Show file tree
Hide file tree
Showing 7 changed files with 106 additions and 296 deletions.
14 changes: 14 additions & 0 deletions packages/core/e2e/__snapshots__/import.e2e-spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,23 @@ Array [
Object {
"id": "T_1",
"name": "pps1.jpg",
"preview": "test-url/test-assets/pps1__preview.jpg",
"source": "test-url/test-assets/pps1.jpg",
},
Object {
"id": "T_2",
"name": "pps2.jpg",
"preview": "test-url/test-assets/pps2__preview.jpg",
"source": "test-url/test-assets/pps2.jpg",
},
],
"description": "A great device for stretching paper.",
"facetValues": Array [],
"featuredAsset": Object {
"id": "T_1",
"name": "pps1.jpg",
"preview": "test-url/test-assets/pps1__preview.jpg",
"source": "test-url/test-assets/pps1.jpg",
},
"id": "T_1",
"name": "Perfect Paper Stretcher",
Expand Down Expand Up @@ -244,6 +250,8 @@ Array [
Object {
"id": "T_3",
"name": "box-of-8.jpg",
"preview": "test-url/test-assets/box-of-8__preview.jpg",
"source": "test-url/test-assets/box-of-8.jpg",
},
],
"facetValues": Array [
Expand All @@ -260,6 +268,8 @@ Array [
"featuredAsset": Object {
"id": "T_3",
"name": "box-of-8.jpg",
"preview": "test-url/test-assets/box-of-8__preview.jpg",
"source": "test-url/test-assets/box-of-8.jpg",
},
"id": "T_5",
"name": "Giotto Mega Pencils Box of 8",
Expand All @@ -286,6 +296,8 @@ Array [
Object {
"id": "T_4",
"name": "box-of-12.jpg",
"preview": "test-url/test-assets/box-of-12__preview.jpg",
"source": "test-url/test-assets/box-of-12.jpg",
},
],
"facetValues": Array [
Expand All @@ -302,6 +314,8 @@ Array [
"featuredAsset": Object {
"id": "T_4",
"name": "box-of-12.jpg",
"preview": "test-url/test-assets/box-of-12__preview.jpg",
"source": "test-url/test-assets/box-of-12.jpg",
},
"id": "T_6",
"name": "Giotto Mega Pencils Box of 12",
Expand Down
10 changes: 9 additions & 1 deletion packages/core/e2e/import.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,14 @@ describe('Import resolver', () => {
featuredAsset {
id
name
preview
source
}
assets {
id
name
preview
source
}
optionGroups {
id
Expand Down Expand Up @@ -91,10 +95,14 @@ describe('Import resolver', () => {
assets {
id
name
preview
source
}
featuredAsset {
id
name
preview
source
}
facetValues {
id
Expand All @@ -109,7 +117,7 @@ describe('Import resolver', () => {
trackInventory
stockMovements {
items {
...on StockMovement {
... on StockMovement {
id
type
quantity
Expand Down
5 changes: 0 additions & 5 deletions packages/core/src/api/api.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { ServiceModule } from '../service/service.module';
import { AdminApiModule, ApiSharedModule, ShopApiModule } from './api-internal-modules';
import { RequestContextService } from './common/request-context.service';
import { configureGraphQLModule } from './config/configure-graphql-module';
import { AssetInterceptor } from './middleware/asset-interceptor';
import { AuthGuard } from './middleware/auth-guard';
import { IdInterceptor } from './middleware/id-interceptor';
import { ValidateCustomFieldsInterceptor } from './middleware/validate-custom-fields-interceptor';
Expand Down Expand Up @@ -48,10 +47,6 @@ import { ValidateCustomFieldsInterceptor } from './middleware/validate-custom-fi
provide: APP_GUARD,
useClass: AuthGuard,
},
{
provide: APP_INTERCEPTOR,
useClass: AssetInterceptor,
},
{
provide: APP_INTERCEPTOR,
useClass: IdInterceptor,
Expand Down
7 changes: 6 additions & 1 deletion packages/core/src/api/config/configure-graphql-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { getDynamicGraphQlModulesForPlugins } from '../../plugin/dynamic-plugin-
import { getPluginAPIExtensions } from '../../plugin/plugin-metadata';
import { ApiSharedModule } from '../api-internal-modules';
import { IdCodecService } from '../common/id-codec.service';
import { AssetInterceptorPlugin } from '../middleware/asset-interceptor-plugin';
import { IdCodecPlugin } from '../middleware/id-codec-plugin';
import { TranslateErrorsPlugin } from '../middleware/translate-errors-plugin';

Expand Down Expand Up @@ -141,7 +142,11 @@ async function createGraphQLOptions(
context: (req: any) => req,
// This is handled by the Express cors plugin
cors: false,
plugins: [new IdCodecPlugin(idCodecService), new TranslateErrorsPlugin(i18nService)],
plugins: [
new IdCodecPlugin(idCodecService),
new TranslateErrorsPlugin(i18nService),
new AssetInterceptorPlugin(configService),
],
} as GqlModuleOptions;

/**
Expand Down
77 changes: 77 additions & 0 deletions packages/core/src/api/middleware/asset-interceptor-plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Asset } from '@vendure/common/lib/generated-types';
import { ApolloServerPlugin, GraphQLRequestListener, GraphQLServiceContext } from 'apollo-server-plugin-base';
import { DocumentNode } from 'graphql';

import { AssetStorageStrategy } from '../../config/asset-storage-strategy/asset-storage-strategy';
import { ConfigService } from '../../config/config.service';
import { GraphqlValueTransformer } from '../common/graphql-value-transformer';

/**
* Transforms outputs so that any Asset instances are run through the {@link AssetStorageStrategy.toAbsoluteUrl}
* method before being returned in the response.
*/
export class AssetInterceptorPlugin implements ApolloServerPlugin {
private graphqlValueTransformer: GraphqlValueTransformer;
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,
);
}
}

serverWillStart(service: GraphQLServiceContext): Promise<void> | void {
this.graphqlValueTransformer = new GraphqlValueTransformer(service.schema);
}

requestDidStart(): GraphQLRequestListener {
return {
willSendResponse: requestContext => {
const { document } = requestContext;
if (document) {
const data = requestContext.response.data;
const req = requestContext.context.req;
if (data) {
this.prefixAssetUrls(req, document, data);
}
}
},
};
}

private prefixAssetUrls(request: any, document: DocumentNode, data: Record<string, any>) {
const typeTree = this.graphqlValueTransformer.getOutputTypeTree(document);
const toAbsoluteUrl = this.toAbsoluteUrl;
if (!toAbsoluteUrl) {
return;
}
this.graphqlValueTransformer.transformValues(typeTree, data, (value, type) => {
const isAssetType = type && type.name === 'Asset';
if (isAssetType) {
if (value && !Array.isArray(value)) {
if (value.preview) {
value.preview = toAbsoluteUrl(request, value.preview);
}
if (value.source) {
value.source = toAbsoluteUrl(request, value.source);
}
}
}
const isSearchResultType = type && type.name === 'SearchResult';
if (isSearchResultType) {
if (value && !Array.isArray(value)) {
if (value.productPreview) {
value.productPreview = toAbsoluteUrl(request, value.productPreview);
}
if (value.productVariantPreview) {
value.productVariantPreview = toAbsoluteUrl(request, value.productVariantPreview);
}
}
}
return value;
});
}
}
Loading

0 comments on commit 0517b6c

Please sign in to comment.