Browse Source

Merge branch 'master' into minor

Michael Bromley 3 years ago
parent
commit
177b9f3577
28 changed files with 3410 additions and 3219 deletions
  1. 2 0
      packages/admin-ui/src/lib/core/src/common/generated-types.ts
  2. 4 2
      packages/admin-ui/src/lib/core/src/shared/components/facet-value-selector/facet-value-selector.component.ts
  3. 1 0
      packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/facet-value-form-input/facet-value-form-input.component.html
  4. 10 0
      packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/facet-value-form-input/facet-value-form-input.component.ts
  5. 503 489
      packages/asset-server-plugin/e2e/graphql/generated-e2e-asset-server-plugin-types.ts
  6. 751 736
      packages/common/src/generated-shop-types.ts
  7. 2 0
      packages/common/src/generated-types.ts
  8. 83 65
      packages/core/e2e/custom-field-relations.e2e-spec.ts
  9. 2 0
      packages/core/e2e/graphql/generated-e2e-admin-types.ts
  10. 714 699
      packages/core/e2e/graphql/generated-e2e-shop-types.ts
  11. 2 0
      packages/core/src/api/api-internal-modules.ts
  12. 5 0
      packages/core/src/api/resolvers/entity/collection-entity.resolver.ts
  13. 5 0
      packages/core/src/api/resolvers/entity/country-entity.resolver.ts
  14. 5 0
      packages/core/src/api/resolvers/entity/facet-entity.resolver.ts
  15. 5 0
      packages/core/src/api/resolvers/entity/facet-value-entity.resolver.ts
  16. 5 0
      packages/core/src/api/resolvers/entity/product-entity.resolver.ts
  17. 5 0
      packages/core/src/api/resolvers/entity/product-option-entity.resolver.ts
  18. 5 0
      packages/core/src/api/resolvers/entity/product-option-group-entity.resolver.ts
  19. 8 0
      packages/core/src/api/resolvers/entity/product-variant-entity.resolver.ts
  20. 26 0
      packages/core/src/api/resolvers/entity/shipping-method-entity.resolver.ts
  21. 1 0
      packages/core/src/api/schema/common/shipping-method.type.graphql
  22. 9 3
      packages/core/src/service/helpers/locale-string-hydrator/locale-string-hydrator.ts
  23. 503 489
      packages/elasticsearch-plugin/e2e/graphql/generated-e2e-elasticsearch-plugin-types.ts
  24. 2 0
      packages/payments-plugin/e2e/graphql/generated-admin-types.ts
  25. 1 0
      packages/payments-plugin/e2e/graphql/generated-shop-types.ts
  26. 751 736
      packages/payments-plugin/src/mollie/graphql/generated-shop-types.ts
  27. 0 0
      schema-admin.json
  28. 0 0
      schema-shop.json

+ 2 - 0
packages/admin-ui/src/lib/core/src/common/generated-types.ts

@@ -4708,6 +4708,7 @@ export type ShippingMethod = Node & {
   id: Scalars['ID'];
   createdAt: Scalars['DateTime'];
   updatedAt: Scalars['DateTime'];
+  languageCode: LanguageCode;
   code: Scalars['String'];
   name: Scalars['String'];
   description: Scalars['String'];
@@ -4722,6 +4723,7 @@ export type ShippingMethodFilterParameter = {
   id?: Maybe<IdOperators>;
   createdAt?: Maybe<DateOperators>;
   updatedAt?: Maybe<DateOperators>;
+  languageCode?: Maybe<StringOperators>;
   code?: Maybe<StringOperators>;
   name?: Maybe<StringOperators>;
   description?: Maybe<StringOperators>;

+ 4 - 2
packages/admin-ui/src/lib/core/src/shared/components/facet-value-selector/facet-value-selector.component.ts

@@ -60,6 +60,7 @@ export class FacetValueSelectorComponent implements OnInit, ControlValueAccessor
     @Output() selectedValuesChange = new EventEmitter<FacetValue.Fragment[]>();
     @Input() facets: FacetWithValues.Fragment[];
     @Input() readonly = false;
+    @Input() transformControlValueAccessorValue: (value: FacetValueSeletorItem[]) => any[] = value => value;
 
     @ViewChild(NgSelectComponent) private ngSelect: NgSelectComponent;
 
@@ -67,7 +68,7 @@ export class FacetValueSelectorComponent implements OnInit, ControlValueAccessor
     onChangeFn: (val: any) => void;
     onTouchFn: () => void;
     disabled = false;
-    value: string[];
+    value: Array<string | FacetValue.Fragment>;
     constructor(private dataService: DataService) {}
 
     ngOnInit() {
@@ -80,7 +81,8 @@ export class FacetValueSelectorComponent implements OnInit, ControlValueAccessor
         }
         this.selectedValuesChange.emit(selected.map(s => s.value));
         if (this.onChangeFn) {
-            this.onChangeFn(JSON.stringify(selected.map(s => s.id)));
+            const transformedValue = this.transformControlValueAccessorValue(selected);
+            this.onChangeFn(transformedValue);
         }
     }
 

+ 1 - 0
packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/facet-value-form-input/facet-value-form-input.component.html

@@ -3,4 +3,5 @@
     [readonly]="readonly"
     [facets]="facets"
     [formControl]="formControl"
+    [transformControlValueAccessorValue]="valueTransformFn"
 ></vdr-facet-value-selector>

+ 10 - 0
packages/admin-ui/src/lib/core/src/shared/dynamic-form-inputs/facet-value-form-input/facet-value-form-input.component.ts

@@ -7,6 +7,7 @@ import { shareReplay } from 'rxjs/operators';
 import { FormInputComponent, InputComponentConfig } from '../../../common/component-registry-types';
 import { FacetWithValues } from '../../../common/generated-types';
 import { DataService } from '../../../data/providers/data.service';
+import { FacetValueSeletorItem } from '../../components/facet-value-selector/facet-value-selector.component';
 
 /**
  * @description
@@ -37,4 +38,13 @@ export class FacetValueFormInputComponent implements FormInputComponent, OnInit
             .mapSingle(data => data.facets.items)
             .pipe(shareReplay(1));
     }
+
+    valueTransformFn = (values: FacetValueSeletorItem[]) => {
+        const isUsedInConfigArg = this.config.__typename === 'ConfigArgDefinition';
+        if (isUsedInConfigArg) {
+            return JSON.stringify(values.map(s => s.id));
+        } else {
+            return values;
+        }
+    };
 }

File diff suppressed because it is too large
+ 503 - 489
packages/asset-server-plugin/e2e/graphql/generated-e2e-asset-server-plugin-types.ts


File diff suppressed because it is too large
+ 751 - 736
packages/common/src/generated-shop-types.ts


+ 2 - 0
packages/common/src/generated-types.ts

@@ -4640,6 +4640,7 @@ export type ShippingMethod = Node & {
   id: Scalars['ID'];
   createdAt: Scalars['DateTime'];
   updatedAt: Scalars['DateTime'];
+  languageCode: LanguageCode;
   code: Scalars['String'];
   name: Scalars['String'];
   description: Scalars['String'];
@@ -4654,6 +4655,7 @@ export type ShippingMethodFilterParameter = {
   id?: Maybe<IdOperators>;
   createdAt?: Maybe<DateOperators>;
   updatedAt?: Maybe<DateOperators>;
+  languageCode?: Maybe<StringOperators>;
   code?: Maybe<StringOperators>;
   name?: Maybe<StringOperators>;
   description?: Maybe<StringOperators>;

+ 83 - 65
packages/core/e2e/custom-field-relations.e2e-spec.ts

@@ -93,6 +93,7 @@ customFieldConfig.Product?.push(
 );
 
 const testResolverSpy = jest.fn();
+
 @Resolver()
 class TestResolver1636 {
     constructor(private connection: TransactionalConnection) {}
@@ -185,6 +186,76 @@ describe('Custom field relations', () => {
 
     describe('special data resolution', () => {
         let productId: string;
+        const productCustomFieldRelationsSelection = `
+        id
+        customFields {
+            cfCollection {
+                languageCode
+                name
+            }
+            cfCountry {
+                languageCode
+                name
+            }
+            cfFacetValue {
+                languageCode
+                name
+            }
+            cfFacet {
+                languageCode
+                name
+            }
+            cfProductOptionGroup {
+                languageCode
+                name
+            }
+            cfProductOption {
+                languageCode
+                name
+            }
+            cfProductVariant {
+                languageCode
+                name
+            }
+            cfProduct {
+                languageCode
+                name
+            }
+            cfShippingMethod {
+                languageCode
+                name
+            }
+        }`;
+
+        function assertTranslatableCustomFieldValues(product: { customFields: any }) {
+            expect(product.customFields.cfCollection).toEqual({
+                languageCode: 'en',
+                name: '__root_collection__',
+            });
+            expect(product.customFields.cfCountry).toEqual({ languageCode: 'en', name: 'Australia' });
+            expect(product.customFields.cfFacetValue).toEqual({
+                languageCode: 'en',
+                name: 'electronics',
+            });
+            expect(product.customFields.cfFacet).toEqual({ languageCode: 'en', name: 'category' });
+            expect(product.customFields.cfProductOptionGroup).toEqual({
+                languageCode: 'en',
+                name: 'screen size',
+            });
+            expect(product.customFields.cfProductOption).toEqual({
+                languageCode: 'en',
+                name: '13 inch',
+            });
+            expect(product.customFields.cfProductVariant).toEqual({
+                languageCode: 'en',
+                name: 'Laptop 13 inch 8GB',
+            });
+            expect(product.customFields.cfProduct).toEqual({ languageCode: 'en', name: 'Laptop' });
+            expect(product.customFields.cfShippingMethod).toEqual({
+                languageCode: 'en',
+                name: 'Standard Shipping',
+            });
+        }
 
         it('translatable entities get translated', async () => {
             const { createProduct } = await adminClient.query(gql`
@@ -211,75 +282,22 @@ describe('Custom field relations', () => {
                                 cfShippingMethodId: "T_1"
                             }
                         }
-                    ) {
-                        id
-                        customFields {
-                            cfCollection {
-                                languageCode
-                                name
-                            }
-                            cfCountry {
-                                languageCode
-                                name
-                            }
-                            cfFacetValue {
-                                languageCode
-                                name
-                            }
-                            cfFacet {
-                                languageCode
-                                name
-                            }
-                            cfProductOptionGroup {
-                                languageCode
-                                name
-                            }
-                            cfProductOption {
-                                languageCode
-                                name
-                            }
-                            cfProductVariant {
-                                languageCode
-                                name
-                            }
-                            cfProduct {
-                                languageCode
-                                name
-                            }
-                            cfShippingMethod {
-                                name
-                            }
-                        }
-                    }
+                    ) { ${productCustomFieldRelationsSelection} }
                 }
             `);
 
             productId = createProduct.id;
+            assertTranslatableCustomFieldValues(createProduct);
+        });
 
-            expect(createProduct.customFields.cfCollection).toEqual({
-                languageCode: 'en',
-                name: '__root_collection__',
-            });
-            expect(createProduct.customFields.cfCountry).toEqual({ languageCode: 'en', name: 'Australia' });
-            expect(createProduct.customFields.cfFacetValue).toEqual({
-                languageCode: 'en',
-                name: 'electronics',
-            });
-            expect(createProduct.customFields.cfFacet).toEqual({ languageCode: 'en', name: 'category' });
-            expect(createProduct.customFields.cfProductOptionGroup).toEqual({
-                languageCode: 'en',
-                name: 'screen size',
-            });
-            expect(createProduct.customFields.cfProductOption).toEqual({
-                languageCode: 'en',
-                name: '13 inch',
-            });
-            expect(createProduct.customFields.cfProductVariant).toEqual({
-                languageCode: 'en',
-                name: 'Laptop 13 inch 8GB',
-            });
-            expect(createProduct.customFields.cfProduct).toEqual({ languageCode: 'en', name: 'Laptop' });
-            expect(createProduct.customFields.cfShippingMethod).toEqual({ name: 'Standard Shipping' });
+        it('translatable entities get translated on findOneInChannel', async () => {
+            const { product } = await adminClient.query(gql`
+                query {
+                    product(id: "${productId}") { ${productCustomFieldRelationsSelection} }
+                }
+            `);
+
+            assertTranslatableCustomFieldValues(product);
         });
 
         it('ProductVariant prices get resolved', async () => {
@@ -979,7 +997,7 @@ describe('Custom field relations', () => {
                             ${customFieldsSelection}
                         }
                     }
-                            `);
+                `);
 
                 assertCustomFieldIds(updateAsset.customFields, 'T_2', ['T_3', 'T_4']);
             });

+ 2 - 0
packages/core/e2e/graphql/generated-e2e-admin-types.ts

@@ -4400,6 +4400,7 @@ export type ShippingMethod = Node & {
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
+    languageCode: LanguageCode;
     code: Scalars['String'];
     name: Scalars['String'];
     description: Scalars['String'];
@@ -4414,6 +4415,7 @@ export type ShippingMethodFilterParameter = {
     id?: Maybe<IdOperators>;
     createdAt?: Maybe<DateOperators>;
     updatedAt?: Maybe<DateOperators>;
+    languageCode?: Maybe<StringOperators>;
     code?: Maybe<StringOperators>;
     name?: Maybe<StringOperators>;
     description?: Maybe<StringOperators>;

File diff suppressed because it is too large
+ 714 - 699
packages/core/e2e/graphql/generated-e2e-shop-types.ts


+ 2 - 0
packages/core/src/api/api-internal-modules.ts

@@ -72,6 +72,7 @@ import {
 import { RefundEntityResolver } from './resolvers/entity/refund-entity.resolver';
 import { RoleEntityResolver } from './resolvers/entity/role-entity.resolver';
 import { ShippingLineEntityResolver } from './resolvers/entity/shipping-line-entity.resolver';
+import { ShippingMethodEntityResolver } from './resolvers/entity/shipping-method-entity.resolver';
 import { TaxRateEntityResolver } from './resolvers/entity/tax-rate-entity.resolver';
 import { UserEntityResolver } from './resolvers/entity/user-entity.resolver';
 import { ShopAuthResolver } from './resolvers/shop/shop-auth.resolver';
@@ -136,6 +137,7 @@ export const entityResolvers = [
     ShippingLineEntityResolver,
     UserEntityResolver,
     TaxRateEntityResolver,
+    ShippingMethodEntityResolver,
 ];
 
 export const adminEntityResolvers = [

+ 5 - 0
packages/core/src/api/resolvers/entity/collection-entity.resolver.ts

@@ -39,6 +39,11 @@ export class CollectionEntityResolver {
         return this.localeStringHydrator.hydrateLocaleStringField(ctx, collection, 'description');
     }
 
+    @ResolveField()
+    languageCode(@Ctx() ctx: RequestContext, @Parent() collection: Collection): Promise<string> {
+        return this.localeStringHydrator.hydrateLocaleStringField(ctx, collection, 'languageCode');
+    }
+
     @ResolveField()
     async productVariants(
         @Ctx() ctx: RequestContext,

+ 5 - 0
packages/core/src/api/resolvers/entity/country-entity.resolver.ts

@@ -13,4 +13,9 @@ export class CountryEntityResolver {
     name(@Ctx() ctx: RequestContext, @Parent() country: Country): Promise<string> {
         return this.localeStringHydrator.hydrateLocaleStringField(ctx, country, 'name');
     }
+
+    @ResolveField()
+    languageCode(@Ctx() ctx: RequestContext, @Parent() country: Country): Promise<string> {
+        return this.localeStringHydrator.hydrateLocaleStringField(ctx, country, 'languageCode');
+    }
 }

+ 5 - 0
packages/core/src/api/resolvers/entity/facet-entity.resolver.ts

@@ -21,6 +21,11 @@ export class FacetEntityResolver {
         return this.localeStringHydrator.hydrateLocaleStringField(ctx, facetValue, 'name');
     }
 
+    @ResolveField()
+    languageCode(@Ctx() ctx: RequestContext, @Parent() facetValue: FacetValue): Promise<string> {
+        return this.localeStringHydrator.hydrateLocaleStringField(ctx, facetValue, 'languageCode');
+    }
+
     @ResolveField()
     async values(@Ctx() ctx: RequestContext, @Parent() facet: Facet): Promise<FacetValue[]> {
         if (facet.values) {

+ 5 - 0
packages/core/src/api/resolvers/entity/facet-value-entity.resolver.ts

@@ -21,6 +21,11 @@ export class FacetValueEntityResolver {
         return this.localeStringHydrator.hydrateLocaleStringField(ctx, facetValue, 'name');
     }
 
+    @ResolveField()
+    languageCode(@Ctx() ctx: RequestContext, @Parent() facetValue: FacetValue): Promise<string> {
+        return this.localeStringHydrator.hydrateLocaleStringField(ctx, facetValue, 'languageCode');
+    }
+
     @ResolveField()
     async facet(@Ctx() ctx: RequestContext, @Parent() facetValue: FacetValue): Promise<Facet | undefined> {
         if (facetValue.facet) {

+ 5 - 0
packages/core/src/api/resolvers/entity/product-entity.resolver.ts

@@ -50,6 +50,11 @@ export class ProductEntityResolver {
         return this.localeStringHydrator.hydrateLocaleStringField(ctx, product, 'description');
     }
 
+    @ResolveField()
+    languageCode(@Ctx() ctx: RequestContext, @Parent() product: Product): Promise<string> {
+        return this.localeStringHydrator.hydrateLocaleStringField(ctx, product, 'languageCode');
+    }
+
     @ResolveField()
     async variants(
         @Ctx() ctx: RequestContext,

+ 5 - 0
packages/core/src/api/resolvers/entity/product-option-entity.resolver.ts

@@ -25,6 +25,11 @@ export class ProductOptionEntityResolver {
         return this.localeStringHydrator.hydrateLocaleStringField(ctx, productOption, 'name');
     }
 
+    @ResolveField()
+    languageCode(@Ctx() ctx: RequestContext, @Parent() productOption: ProductOption): Promise<string> {
+        return this.localeStringHydrator.hydrateLocaleStringField(ctx, productOption, 'languageCode');
+    }
+
     @ResolveField()
     @Allow(Permission.ReadCatalog, Permission.Public, Permission.ReadProduct)
     async group(

+ 5 - 0
packages/core/src/api/resolvers/entity/product-option-group-entity.resolver.ts

@@ -22,6 +22,11 @@ export class ProductOptionGroupEntityResolver {
         return this.localeStringHydrator.hydrateLocaleStringField(ctx, optionGroup, 'name');
     }
 
+    @ResolveField()
+    languageCode(@Ctx() ctx: RequestContext, @Parent() optionGroup: ProductOptionGroup): Promise<string> {
+        return this.localeStringHydrator.hydrateLocaleStringField(ctx, optionGroup, 'languageCode');
+    }
+
     @ResolveField()
     @Allow(Permission.ReadCatalog, Permission.Public, Permission.ReadProduct)
     async options(

+ 8 - 0
packages/core/src/api/resolvers/entity/product-variant-entity.resolver.ts

@@ -32,6 +32,14 @@ export class ProductVariantEntityResolver {
         return this.localeStringHydrator.hydrateLocaleStringField(ctx, productVariant, 'name');
     }
 
+    @ResolveField()
+    async languageCode(
+        @Ctx() ctx: RequestContext,
+        @Parent() productVariant: ProductVariant,
+    ): Promise<string> {
+        return this.localeStringHydrator.hydrateLocaleStringField(ctx, productVariant, 'languageCode');
+    }
+
     @ResolveField()
     async price(@Ctx() ctx: RequestContext, @Parent() productVariant: ProductVariant): Promise<number> {
         return this.productVariantService.hydratePriceFields(ctx, productVariant, 'price');

+ 26 - 0
packages/core/src/api/resolvers/entity/shipping-method-entity.resolver.ts

@@ -0,0 +1,26 @@
+import { Parent, ResolveField, Resolver } from '@nestjs/graphql';
+
+import { ShippingMethod } from '../../../entity/index';
+import { LocaleStringHydrator } from '../../../service/helpers/locale-string-hydrator/locale-string-hydrator';
+import { RequestContext } from '../../common/request-context';
+import { Ctx } from '../../decorators/request-context.decorator';
+
+@Resolver('ShippingMethod')
+export class ShippingMethodEntityResolver {
+    constructor(private localeStringHydrator: LocaleStringHydrator) {}
+
+    @ResolveField()
+    name(@Ctx() ctx: RequestContext, @Parent() shippingMethod: ShippingMethod): Promise<string> {
+        return this.localeStringHydrator.hydrateLocaleStringField(ctx, shippingMethod, 'name');
+    }
+
+    @ResolveField()
+    description(@Ctx() ctx: RequestContext, @Parent() shippingMethod: ShippingMethod): Promise<string> {
+        return this.localeStringHydrator.hydrateLocaleStringField(ctx, shippingMethod, 'description');
+    }
+
+    @ResolveField()
+    languageCode(@Ctx() ctx: RequestContext, @Parent() shippingMethod: ShippingMethod): Promise<string> {
+        return this.localeStringHydrator.hydrateLocaleStringField(ctx, shippingMethod, 'languageCode');
+    }
+}

+ 1 - 0
packages/core/src/api/schema/common/shipping-method.type.graphql

@@ -2,6 +2,7 @@ type ShippingMethod implements Node {
     id: ID!
     createdAt: DateTime!
     updatedAt: DateTime!
+    languageCode: LanguageCode!
     code: String!
     name: String!
     description: String!

+ 9 - 3
packages/core/src/service/helpers/locale-string-hydrator/locale-string-hydrator.ts

@@ -1,4 +1,5 @@
 import { Injectable } from '@nestjs/common';
+import { LanguageCode } from '@vendure/common/lib/generated-types';
 
 import { RequestContext } from '../../../api/common/request-context';
 import { RequestContextCacheService } from '../../../cache/request-context-cache.service';
@@ -19,10 +20,10 @@ export class LocaleStringHydrator {
         private requestCache: RequestContextCacheService,
     ) {}
 
-    async hydrateLocaleStringField<T extends VendureEntity & Translatable>(
+    async hydrateLocaleStringField<T extends VendureEntity & Translatable & { languageCode?: LanguageCode }>(
         ctx: RequestContext,
         entity: T,
-        fieldName: TranslatableKeys<T>,
+        fieldName: TranslatableKeys<T> | 'languageCode',
     ): Promise<string> {
         if (entity[fieldName]) {
             // Already hydrated, so return the value
@@ -61,7 +62,12 @@ export class LocaleStringHydrator {
         if (entity.translations.length) {
             const translated = translateDeep(entity, ctx.languageCode);
             for (const localeStringProp of Object.keys(entity.translations[0])) {
-                if (localeStringProp === 'base' || localeStringProp === 'languageCode') {
+                if (
+                    localeStringProp === 'base' ||
+                    localeStringProp === 'id' ||
+                    localeStringProp === 'createdAt' ||
+                    localeStringProp === 'updatedAt'
+                ) {
                     continue;
                 }
                 if (localeStringProp === 'customFields') {

File diff suppressed because it is too large
+ 503 - 489
packages/elasticsearch-plugin/e2e/graphql/generated-e2e-elasticsearch-plugin-types.ts


+ 2 - 0
packages/payments-plugin/e2e/graphql/generated-admin-types.ts

@@ -4400,6 +4400,7 @@ export type ShippingMethod = Node & {
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
+    languageCode: LanguageCode;
     code: Scalars['String'];
     name: Scalars['String'];
     description: Scalars['String'];
@@ -4414,6 +4415,7 @@ export type ShippingMethodFilterParameter = {
     id?: Maybe<IdOperators>;
     createdAt?: Maybe<DateOperators>;
     updatedAt?: Maybe<DateOperators>;
+    languageCode?: Maybe<StringOperators>;
     code?: Maybe<StringOperators>;
     name?: Maybe<StringOperators>;
     description?: Maybe<StringOperators>;

+ 1 - 0
packages/payments-plugin/e2e/graphql/generated-shop-types.ts

@@ -2804,6 +2804,7 @@ export type ShippingMethod = Node & {
     id: Scalars['ID'];
     createdAt: Scalars['DateTime'];
     updatedAt: Scalars['DateTime'];
+    languageCode: LanguageCode;
     code: Scalars['String'];
     name: Scalars['String'];
     description: Scalars['String'];

File diff suppressed because it is too large
+ 751 - 736
packages/payments-plugin/src/mollie/graphql/generated-shop-types.ts


File diff suppressed because it is too large
+ 0 - 0
schema-admin.json


File diff suppressed because it is too large
+ 0 - 0
schema-shop.json


Some files were not shown because too many files changed in this diff