forked from vuestorefront/vue-storefront
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
MTH-250 add sample extension as an exmaple of adding custom entity ty…
…pe, add Docs
- Loading branch information
Showing
7 changed files
with
218 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
## Data Entity Types | ||
|
||
Vue-storefront uses multuiple data entity typos to cover whole scope of storefront | ||
Default entity types are | ||
- Product | ||
- Category | ||
- Attribute | ||
- Taxrule | ||
|
||
Using if these entity types was hardcoded and there were no ability to easy use another custom entity type required for customisation | ||
Now Vue-storefront has a new logic to work with entityes in the data fetching prospective. It uses Entity Types. | ||
|
||
Each search adapter should register entity type to cover search feature. Default API and new Graphql search adapters are updated to register all required exsiting entity types. But develper is able alss inject custom entittypes what allow them to work with some other custom entity type Data (eg get list of offline stores or something else) | ||
|
||
To use it internal graphql server should be updated with adding correspond resolver for new entity type. Or some other external graphql server what already have implemeted resolver for this entity type can be used | ||
|
||
To register such entity type use searchAdapter.registerEntityTypeByQuery method like as on an example below | ||
|
||
|
||
```js | ||
const factory = new SearchAdapterFactory() | ||
let searchAdapter = factory.getSearchAdapter('graphql') | ||
searchAdapter.registerEntityTypeByQuery('testentity', { | ||
url: 'http://localhost:8080/graphql/', | ||
query: require('./queries/testentity.gql'), | ||
queryProcessor: (query) => { | ||
// function that can modify the query each time before it's being executed | ||
return query | ||
}, | ||
resultPorcessor: (resp, start, size) => { | ||
if (resp === null) { | ||
throw new Error('Invalid graphQl result - null not exepcted') | ||
} | ||
if (resp.hasOwnProperty('data')) { | ||
return processESResponseType(resp.data.testentity, start, size) | ||
} else { | ||
if (resp.error) { | ||
throw new Error(JSON.stringify(resp.error)) | ||
} else { | ||
throw new Error('Unknown error with graphQl result in resultPorcessor for entity type \'category\'') | ||
} | ||
} | ||
} | ||
}) | ||
|
||
``` | ||
|
||
Sample extension 'sample-custom-entity-graphql' was added to illustrate how it can be used. It injects custom entity type 'testentity' | ||
and set custom graphql server url( it is the same as a default api host in the example just because resolver for this 'testentity' was added there for testing. But please notice it was removed there) | ||
|
||
To test sample extension with resolver you can add graphql schema file and reolver file in the separate 'src/graphql/elastcisearch/testentity' folder in the Vue-Storefront-Api | ||
|
||
'schema.graphqls' file: | ||
```graphql | ||
type Query { | ||
testentity(filter: TestInput): ESResponse | ||
} | ||
input TestInput @doc(description: "TaxRuleInput specifies the tax rules information to search") { | ||
id: FilterTypeInput @doc(description: "An ID that uniquely identifies the tax rule") | ||
code: FilterTypeInput @doc(description: "The unique identifier for an tax rule. This value should be in lowercase letters without spaces.") | ||
priority: FilterTypeInput @doc(description: "Priority of the tax rule") | ||
position: FilterTypeInput @doc(description: "Position of the tax rule") | ||
customer_tax_class_ids: FilterTypeInput @doc(description: "Cunstomer tax class ids of the tax rule") | ||
product_tax_class_ids: FilterTypeInput @doc(description: "Products tax class ids of the tax rule") | ||
tax_rate_ids: FilterTypeInput @doc(description: "Tax rates ids of the tax rule") | ||
calculate_subtotal: FilterTypeInput @doc(description: "Calculating subtotals of the tax rule") | ||
rates: FilterTypeInput @doc(description: "Rates of the tax rule") | ||
} | ||
``` | ||
|
||
and resolver file 'resolver.js' is | ||
|
||
```js | ||
import config from 'config'; | ||
import client from '../client'; | ||
import { buildQuery } from '../queryBuilder'; | ||
|
||
async function testentity(filter) { | ||
let query = buildQuery({ filter, pageSize: 150, type: 'taxrule' }); | ||
|
||
const response = await client.search({ | ||
index: config.elasticsearch.indices[0], | ||
type: config.elasticsearch.indexTypes[4], | ||
body: query | ||
}); | ||
|
||
return response; | ||
} | ||
|
||
const resolver = { | ||
Query: { | ||
testentity: (_, { filter }) => testentity(filter) | ||
} | ||
}; | ||
|
||
export default resolver; | ||
|
||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import extensionStore from './store' | ||
import extensionRoutes from './router' | ||
import SearchAdapterFactory from 'core/store/lib/search/adapter/factory' | ||
import {processESResponseType} from 'core/store/lib/search/adapter/graphql/processor/processType' | ||
import {currentStoreView} from 'core/store/lib/multistore' | ||
import SearchQuery from 'core/store/lib/search/searchQuery' | ||
|
||
const EXTENSION_KEY = 'sample-custom-entity-graphql-extension' | ||
const TEST_ENTITY_TYPE = 'testentity' | ||
|
||
export default function (app, router, store, config) { | ||
router.addRoutes(extensionRoutes) // add custom routes | ||
store.registerModule(EXTENSION_KEY, extensionStore) // add custom store | ||
|
||
app.$on('application-after-init', () => { | ||
console.debug('Example of custom entity graphql extension') | ||
|
||
// load Search adapter factory to handle graphql search adapter | ||
const factory = new SearchAdapterFactory() | ||
|
||
// create graphQl searchAdapter | ||
let searchAdapter = factory.getSearchAdapter('graphql') | ||
|
||
// register custom entity type using registerEntityTypeByQuery | ||
// differnt graphql servers cold be used for different entity types | ||
// resolver for testentity should be implemented on the graphql server provided | ||
searchAdapter.registerEntityTypeByQuery(TEST_ENTITY_TYPE, { | ||
url: 'http://localhost:8080/graphql/', | ||
query: require('./queries/testentity.gql'), | ||
queryProcessor: (query) => { | ||
// function that can modify the query each time before it's being executed | ||
return query | ||
}, | ||
resultPorcessor: (resp, start, size) => { | ||
if (resp === null) { | ||
throw new Error('Invalid graphQl result - null not exepcted') | ||
} | ||
if (resp.hasOwnProperty('data')) { | ||
return processESResponseType(resp.data.testentity, start, size) | ||
} else { | ||
if (resp.error) { | ||
throw new Error(JSON.stringify(resp.error)) | ||
} else { | ||
throw new Error('Unknown error with graphQl result in resultPorcessor for entity type \'category\'') | ||
} | ||
} | ||
} | ||
}) | ||
|
||
const storeView = currentStoreView() | ||
|
||
// create an empty SearchQuery to get all data for new custom entity | ||
const searchQuery = new SearchQuery() | ||
|
||
// prepare a Request object | ||
const Request = { | ||
store: storeView.storeCode, // TODO: add grouped product and bundled product support | ||
type: TEST_ENTITY_TYPE, | ||
searchQuery: searchQuery, | ||
sort: '' | ||
} | ||
|
||
// apply test search | ||
searchAdapter.search(Request).then((resp) => { // we're always trying to populate cache - when online | ||
const res = searchAdapter.entities[Request.type].resultPorcessor(resp, 0, 200) | ||
console.log('Testentity response: ', res) | ||
}) | ||
}) | ||
|
||
return { EXTENSION_KEY, extensionRoutes, extensionStore } | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{ | ||
"name": "@vue-storefront/extension-sample-custom-entity-graphql", | ||
"version": "1.3.0", | ||
"description": "Extension template for Vue Storefront", | ||
"license": "MIT", | ||
"main": "index.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"publishConfig": { | ||
"access": "public" | ||
} | ||
} |
8 changes: 8 additions & 0 deletions
8
src/extensions/sample-custom-entity-graphql/queries/testentity.gql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
query testentity ($filter: TestInput) { | ||
testentity( | ||
filter: $filter | ||
) | ||
{ | ||
hits | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
export default [ | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
const state = { | ||
} | ||
|
||
const getters = { | ||
} | ||
|
||
// actions | ||
const actions = { | ||
} | ||
|
||
// mutations | ||
const mutations = { | ||
} | ||
|
||
export default { | ||
state, | ||
getters, | ||
actions, | ||
mutations | ||
} |