druxt-router
Advanced tools
Comparing version 0.15.0 to 0.16.0
@@ -7,7 +7,105 @@ import { resolve } from 'path'; | ||
/** | ||
* @vuepress | ||
* --- | ||
* title: DruxtRouterModule | ||
* --- | ||
*/ | ||
/** | ||
* The Nuxt.js module function. | ||
* | ||
* - Extends the Vue router, adding the Druxt wildcard route. | ||
* - Adds the Druxt router plugin. | ||
* - Adds the Druxt router Vuex store. | ||
* | ||
* The module function should not be used directly, but rather installed via yout Nuxt.js configuration file. | ||
* | ||
* Options are set on the root level `druxt` Nuxt.js config object. | ||
* | ||
* @example @lang js | ||
* // `nuxt.config.js` | ||
* module.exports = { | ||
* modules: [ | ||
* 'druxt-router' | ||
* ], | ||
* druxt: { | ||
* baseUrl: 'https://example.com' | ||
* } | ||
* } | ||
* | ||
* @todo [Add module level options]{@link https://github.com/druxt/druxt-router/issues/53} | ||
* | ||
* @property {object} options.druxt - Druxt.js root level options. | ||
* @property {string} options.druxt.baseUrl - Base URL of Drupal JSON:API backend. | ||
* @property {string} options.druxt.router.component - File to custom Router component. | ||
*/ | ||
var DruxtRouterModule = function (moduleOptions) { | ||
var this$1 = this; | ||
// Use root level Druxt options. | ||
if (typeof this.options === 'undefined' || !this.options.druxt) { | ||
throw new TypeError('Druxt settings missing.') | ||
} | ||
var options = this.options.druxt; | ||
options.router = options.router || {}; | ||
this.extendRoutes(function (routes, resolve) { | ||
// Only add router component if custom component is undefined. | ||
// @TODO - Validate custom component. | ||
// @TODO - Add test for custom component. | ||
// @TODO - Document usage. | ||
if (!options.router.component) { | ||
options.router.component = resolve(this$1.options.buildDir, 'components/druxt-router.js'); | ||
this$1.addTemplate({ | ||
src: resolve(__dirname, '../nuxt/component.js'), | ||
fileName: 'components/druxt-router.js', | ||
options: options | ||
}); | ||
} | ||
// Add Druxt router custom wildcard route. | ||
routes.push({ | ||
name: 'druxt-router', | ||
path: '*', | ||
component: options.router.component, | ||
chunkName: 'druxt-router' | ||
}); | ||
}); | ||
// Add plugin. | ||
this.addPlugin({ | ||
src: resolve(__dirname, '../nuxt/plugin.js'), | ||
fileName: 'druxt-router.js', | ||
options: options | ||
}); | ||
// Add Vuex plugin. | ||
// @TODO - Ensure Vuex store is available. | ||
this.addPlugin({ | ||
src: resolve(__dirname, '../nuxt/store.js'), | ||
fileName: 'store/druxt-router.js', | ||
options: options | ||
}); | ||
}; | ||
// | ||
/** | ||
* The DruxtRouter Vue.js component. | ||
* | ||
* @example @lang vue | ||
* <druxt-router /> | ||
*/ | ||
var script = { | ||
name: 'DruxtRouter', | ||
/** | ||
* Nuxt.js fetch method. | ||
* | ||
* - Loads the route and redirect information from the Vuex store. | ||
* - Resolves redirects. | ||
* | ||
* @see {@link https://nuxtjs.org/api/pages-fetch/} | ||
*/ | ||
fetch: async function fetch (ref) { | ||
@@ -26,2 +124,8 @@ var store = ref.store; | ||
/** | ||
* Vue.js Computed properties. | ||
* | ||
* @vue-computed {object} redirect The current Redirect, if applicable. | ||
* @vue-computed {object} route The current Route. | ||
*/ | ||
computed: Object.assign({}, {component: function component () { | ||
@@ -31,2 +135,7 @@ return this.route.component || false | ||
/** | ||
* Route title. | ||
* @type {boolean|string} | ||
* @default false | ||
*/ | ||
title: function title () { | ||
@@ -36,2 +145,7 @@ return this.route.label || false | ||
/** | ||
* Route component property data. | ||
* @type {object|string} | ||
* @default false | ||
*/ | ||
props: function props () { | ||
@@ -46,2 +160,11 @@ return this.route.props || false | ||
/** | ||
* Nuxt.js head method. | ||
* | ||
* - Sets the page title. | ||
* - Sets the canonical link. | ||
* | ||
* @see {@link https://nuxtjs.org/api/pages-head/} | ||
* @todo Improve metatag support. | ||
*/ | ||
head: function head () { | ||
@@ -172,2 +295,14 @@ return { | ||
/** | ||
* @vuepress | ||
* --- | ||
* title: DruxtRouter | ||
* --- | ||
*/ | ||
/** | ||
* DruxtRouter class. | ||
* | ||
* Provides core Drupal JSON:API query functionality. | ||
*/ | ||
var DruxtRouter = function DruxtRouter (baseURL, options) { | ||
@@ -187,4 +322,15 @@ if ( options === void 0 ) options = {}; | ||
} | ||
/** | ||
* Axios instance. | ||
* @see {@link https://github.com/axios/axios#instance-methods} | ||
* @type {object} | ||
*/ | ||
this.axios = axios.create(axiosSettings); | ||
/** | ||
* Druxt router options. | ||
* @type {object} | ||
* @private | ||
*/ | ||
this.options = Object.assign({}, {endpoint: '/jsonapi', | ||
@@ -219,2 +365,7 @@ jsonapiResourceConfig: 'jsonapi_resource_config--jsonapi_resource_config', | ||
/** | ||
* Drupal JSON:API index. | ||
* @type {object} | ||
* @private | ||
*/ | ||
this.index = null; | ||
@@ -226,3 +377,6 @@ }; | ||
* | ||
* @param {*} headers | ||
* @example @lang js | ||
* router.addHeaders({ 'Authorization': `Basic ${token}` }) | ||
* | ||
* @param {object} headers - An object containing HTTP headers. | ||
*/ | ||
@@ -242,4 +396,11 @@ DruxtRouter.prototype.addHeaders = function addHeaders (headers) { | ||
* | ||
* @param string url | ||
* @param {*} query | ||
* @example @lang js | ||
* const query = new DrupalJsonApiParams() | ||
* query.addFilter('status', '1') | ||
* const queryUrl = router.buildQueryUrl(resourceUrl, query) | ||
* | ||
* @param {string} url - The base query URL. | ||
* @param {string|object} [query] - A correctly formatted JSON:API query string or object. | ||
* | ||
* @return {string} The URL with query string. | ||
*/ | ||
@@ -273,3 +434,7 @@ DruxtRouter.prototype.buildQueryUrl = function buildQueryUrl (url, query) { | ||
* | ||
* @param {*} res | ||
* @todo - Move this to utils? | ||
* | ||
* @param {object} res - Axios GET request response object. | ||
* | ||
* @private | ||
*/ | ||
@@ -295,5 +460,10 @@ DruxtRouter.prototype.checkPermissions = function checkPermissions (res) { | ||
/** | ||
* Returns Drupal entity and route for given path. | ||
* Returns route and redirect data for a given path. | ||
* | ||
* @param string path | ||
* @example @lang js | ||
* const { redirect, route } = await router.get('/node/1') | ||
* | ||
* @param {string} path - The route path. | ||
* | ||
* @returns {object} The route and redirect data. | ||
*/ | ||
@@ -312,3 +482,10 @@ DruxtRouter.prototype.get = async function get (path) { | ||
/** | ||
* Get index of all available resources. | ||
* Get index of all available resources, or the optionally specified resource. | ||
* | ||
* @example @lang js | ||
* const { href } = await router.getIndex('node--article') | ||
* | ||
* @param {string} resource - (Optional) A specific resource to query. | ||
* | ||
* @returns {object} The resource index object or the specified resource. | ||
*/ | ||
@@ -355,3 +532,15 @@ DruxtRouter.prototype.getIndex = async function getIndex (resource) { | ||
/** | ||
* @param object route | ||
* Get redirect data for a given route. | ||
* | ||
* @example @lang js | ||
* const route = await router.getRoute(path) | ||
* const redirect = router.getRedirect(path, route) | ||
* | ||
* @todo Move this to a DruxtRouterRedirect class. | ||
* @todo Remove the path parameter. | ||
* | ||
* @param {string} path - The route path. | ||
* @param {object} route - Druxt route object. | ||
* | ||
* @returns {boolean|string} The redirect path or false. | ||
*/ | ||
@@ -388,4 +577,9 @@ DruxtRouter.prototype.getRedirect = function getRedirect (path, route) { | ||
* | ||
* @param string type | ||
* @param string id | ||
* @example @lang js | ||
* const data = await router.get({ type: 'node--article', id }) | ||
* | ||
* @param {string} type - The JSON:API resource type. | ||
* @param {string} id - The Drupal resource UUID. | ||
* | ||
* @returns {object} The JSON:API resource data. | ||
*/ | ||
@@ -408,14 +602,26 @@ DruxtRouter.prototype.getResource = async function getResource (query) { | ||
var url = href + "/" + id; | ||
var resource = await this.axios.get(url); | ||
return resource.data.data | ||
try { | ||
var resource = await this.axios.get(url); | ||
return resource.data.data | ||
} catch (e) { | ||
return false | ||
} | ||
}; | ||
/** | ||
* Get all resources based on resource and query. | ||
* Gets a collection of resources. | ||
* | ||
* @todo Add pagination. | ||
* @todo Add granular pagination. | ||
* | ||
* @param {*} resource | ||
* @param {*} query | ||
* @example @lang js | ||
* // Load all currently published Articles. | ||
* const query = new DrupalJsonApiParams() | ||
* query.addFilter('status', '1') | ||
* const resources = await router.getResources('node--article', query, { all: true }) | ||
* | ||
* @param {string} resource - The JSON:API resource type. | ||
* @param {string|object} query - A JSON:API query string or object. | ||
* @param {object} [options] | ||
* @param {boolean} [options.all=false] - Load all results. | ||
* @return {object[]} Array of resources. | ||
*/ | ||
@@ -458,3 +664,9 @@ DruxtRouter.prototype.getResources = async function getResources (resource, query, options) { | ||
* | ||
* @param object route | ||
* @example @lang js | ||
* const route = await router.getRoute('/') | ||
* const data = await router.getResourceByRoute(route) | ||
* | ||
* @param {object} route - Druxt Router route object. | ||
* | ||
* @returns {object} The JSON:API resource data. | ||
*/ | ||
@@ -468,3 +680,8 @@ DruxtRouter.prototype.getResourceByRoute = function getResourceByRoute (route) { | ||
* | ||
* @param string path | ||
* @example @lang js | ||
* const route = await router.getRoute('/') | ||
* | ||
* @param {string} path - The route path. | ||
* | ||
* @returns {object} The route object. | ||
*/ | ||
@@ -539,9 +756,41 @@ DruxtRouter.prototype.getRoute = async function getRoute (path) { | ||
/** | ||
* @vuepress | ||
* --- | ||
* title: DruxtRouterEntityMixin | ||
* --- | ||
*/ | ||
/** | ||
* The DruxtRouterEntityMixin Vue.js mixin provides easy integration with the Druxt.js Router Vuex store, including on-demand loading of JSON:API resources. | ||
* | ||
* @mixin | ||
* | ||
* @example @lang vue | ||
* <template> | ||
* <div v-if="entity && !loading"> | ||
* {{ entity }} | ||
* </div> | ||
* </template> | ||
* | ||
* <script> | ||
* // Import mixin. | ||
* import { DruxtRouterEntityMixin } from 'druxt-router' | ||
* | ||
* export default { | ||
* // Set mixin. | ||
* mixins: [DruxtRouterEntityMixin] | ||
* } | ||
* </script> | ||
*/ | ||
var DruxtRouterEntityMixin = { | ||
/** | ||
* Props. | ||
* Vue.js Properties. | ||
*/ | ||
props: { | ||
/** | ||
* The Drupal display mode. | ||
* | ||
* @type {string} | ||
* @default default | ||
*/ | ||
mode: { | ||
@@ -552,2 +801,7 @@ type: String, | ||
/** | ||
* The JSON:API resource type. | ||
* | ||
* @type {string} | ||
*/ | ||
type: { | ||
@@ -560,2 +814,4 @@ type: String, | ||
* The Drupal entity UUID. | ||
* | ||
* @type {string} | ||
*/ | ||
@@ -568,10 +824,7 @@ uuid: { | ||
data: function () { return ({ | ||
entity: false, | ||
loading: true | ||
}); }, | ||
created: function created () { | ||
var this$1 = this; | ||
/** | ||
* Loads the JSON:API resource via the Vuex store. | ||
*/ | ||
fetch: async function fetch () { | ||
// Use resource from Vuex store if available. | ||
if (typeof this.entities[this.uuid] !== 'undefined') { | ||
@@ -582,10 +835,30 @@ this.entity = this.entities[this.uuid]; | ||
// Otherwise invoke getEntity() to retrieve it from Drupal. | ||
if (!this.entity && this.uuid && this.type) { | ||
this.getEntity({ id: this.uuid, type: this.type }).then(function (res) { | ||
this$1.entity = res; | ||
this$1.loading = false; | ||
}); | ||
this.entity = await this.getEntity({ id: this.uuid, type: this.type }); | ||
this.loading = false; | ||
} | ||
}, | ||
/** | ||
* Vue.js Data object. | ||
* | ||
* Used for on-demand JSON:API resource loading. | ||
* | ||
* @property {object} entity - The Drupal entity JSON:API resource. | ||
* @property {boolean} loading - The loading state. | ||
*/ | ||
data: function () { return ({ | ||
entity: false, | ||
loading: true | ||
}); }, | ||
/** | ||
* Vue.js Computed properties. | ||
* | ||
* - Maps Vuex `entities` state to `this->entities`. | ||
* | ||
* @property {object} entities - The mapped Druxt.js Router Vuex `entities` state. | ||
* @see {@link store|src/store.js} | ||
*/ | ||
computed: Object.assign({}, mapState({ | ||
@@ -595,2 +868,9 @@ entities: function (state) { return state.druxtRouter.entities; } | ||
/** | ||
* Vue.js Methods. | ||
* | ||
* - Maps Vuex `druxtRouter/getEntity` action to `this->getEntity()`. | ||
* | ||
* @see {@link store|src/store.js} | ||
*/ | ||
methods: Object.assign({}, mapActions({ | ||
@@ -601,3 +881,2 @@ getEntity: 'druxtRouter/getEntity' | ||
// @TODO - Add Vuex test coverage. | ||
var DruxtRouterStore = function (ref) { | ||
@@ -610,6 +889,31 @@ var store = ref.store; | ||
/** | ||
* @namespace | ||
*/ | ||
var namespace = 'druxtRouter'; | ||
/** | ||
* The druxtRouter Vuex module. | ||
* | ||
* Provides a Vuex state object, mutations and actions for interacting with the Drupal JSON:API. | ||
* | ||
* @name druxtRouter | ||
* @module druxtRouter | ||
* | ||
* @todo Replace 'entit(y|ies)' with 'resource(s)' | ||
*/ | ||
var module = { | ||
namespaced: true, | ||
/** | ||
* Vuex State object. | ||
* | ||
* @name state | ||
* @type {object} | ||
* @property {object} entities - Drupal entity store. | ||
* @property {boolean|object} redirect - Active redirect. | ||
* @property {object} route - Active route. | ||
* @property {object} routes - Route store. | ||
* @readonly | ||
*/ | ||
state: function () { return ({ | ||
@@ -622,3 +926,14 @@ entities: {}, | ||
/** | ||
* Vuex Mutations. | ||
*/ | ||
mutations: { | ||
/** | ||
* @name addEntity | ||
* @mutator {object} addEntity=entities Adds specified Drupal entity JSON:API resource data to the Vuex state object. | ||
* @param {object} entity - The Drupal entity JSON:API resource data. | ||
* | ||
* @example @lang js | ||
* this.$store.commit('druxtRouter/addEntity', entity) | ||
*/ | ||
addEntity: function addEntity (state, entity) { | ||
@@ -632,2 +947,10 @@ if (!entity || typeof entity.id === 'undefined') { | ||
/** | ||
* @name setRedirect | ||
* @mutator {object} setRedirect=redirect Sets the active redirect. | ||
* @param {object} redirect - The Redirect object. | ||
* | ||
* @example @lang js | ||
* this.$store.commit('druxtRouter/setRedirect', redirect) | ||
*/ | ||
setRedirect: function setRedirect (state, redirect) { | ||
@@ -637,2 +960,12 @@ state.redirect = redirect; | ||
/** | ||
* @name addRoute | ||
* @mutator {object} addRoute=routes Adds the supplied route to the Vuex state object. | ||
* @param {object} context | ||
* @param {string} context.path - The route path. | ||
* @param {object} context.route - The route object. | ||
* | ||
* @example @lang js | ||
* this.$store.commit('druxtRouter/addRoute', { path, route }) | ||
*/ | ||
addRoute: function addRoute (state, ref) { | ||
@@ -650,2 +983,10 @@ var path = ref.path; | ||
/** | ||
* @name setRoute | ||
* @mutator {string} setRoute=route Sets the active route by path. | ||
* @param {string} path - The route path | ||
* | ||
* @example @lang js | ||
* this.$store.commit('druxtRouter/setRoute', '/') | ||
*/ | ||
setRoute: function setRoute (state, path) { | ||
@@ -661,3 +1002,21 @@ if (typeof path !== 'string' || typeof state.routes[path] === 'undefined') { | ||
/** | ||
* Vuex Actions. | ||
*/ | ||
actions: { | ||
/** | ||
* Get route and redirect information. | ||
* | ||
* - Dispatches `druxtRouter/getRoute` action. | ||
* - Sets the active route. | ||
* - Sets the active redirect. | ||
* | ||
* @name get | ||
* @action get=route | ||
* @param {string} path The router path. | ||
* @return {object} The route and redirect information. | ||
* | ||
* @example @lang js | ||
* const { redirect, route } = await this.$store.dispatch('druxtRouter/get', '/') | ||
*/ | ||
get: async function get (ref, path) { | ||
@@ -676,4 +1035,6 @@ var commit = ref.commit; | ||
// Set active route. | ||
commit('setRoute', path); | ||
// Set active redirect. | ||
var redirect = this.$druxtRouter().getRedirect(path, route); | ||
@@ -685,3 +1046,19 @@ commit('setRedirect', redirect); | ||
// @TODO - Move this into druxt-entity. | ||
/** | ||
* Get Entity. | ||
* | ||
* - Executes query against Drupal JSON:API. | ||
* - Caches result in the Vuex store. | ||
* - Returns cached result from Vuex store when available. | ||
* | ||
* @name getEntity | ||
* @action getEntity=entities | ||
* @param {object} query | ||
* @return {object} The Drupal entity JSON:API resource data. | ||
* | ||
* @example @lang js | ||
* const entity = await this.$store.dispatch('druxtRouter/getEntity', { type: 'node--article', id }) | ||
* | ||
* @todo Rename getEntity to getResource. | ||
*/ | ||
getEntity: async function getEntity (ref, query) { | ||
@@ -702,2 +1079,26 @@ var commit = ref.commit; | ||
/** | ||
* Get multiple resources. | ||
* | ||
* @name getResources | ||
* @action getResources | ||
* @param {object} context Object containing `druxtRouter.getResources()` parameters. | ||
* @param {string} context.resource - The JSON:API resource type. | ||
* @param {string|object} context.query - A JSON:API query string or object. | ||
* @param {object} [context.options] | ||
* @param {boolean} [context.options.all=false] - Load all results. | ||
* @return {object[]} Array of Drupal JSON:API resource data. | ||
* | ||
* @example @lang js | ||
* // Load all currently published Articles. | ||
* const query = new DrupalJsonApiParams() | ||
* query.addFilter('status', '1') | ||
* const resources = await this.$store.dispatch('druxtRouter/getResources', { | ||
* resource: 'node--article', | ||
* query, | ||
* options: { all: true } | ||
* }) | ||
* | ||
* @todo Add Vuex store caching for getResources. | ||
*/ | ||
getResources: async function getResources (ref, ref$1) { | ||
@@ -715,2 +1116,17 @@ var commit = ref.commit; | ||
/** | ||
* Get Route. | ||
* | ||
* - Executes query against Drupal Decoupled router. | ||
* - Caches result in the Vuex store. | ||
* - Returns cached result from Vuex store when available. | ||
* | ||
* @name getRoute | ||
* @action getRoute=route | ||
* @param {string} path - The route path. | ||
* @return {object} The route object. | ||
* | ||
* @example @lang js | ||
* const route = await this.$store.dispatch('druxtRouter/getRoute', '/') | ||
*/ | ||
getRoute: async function getRoute (ref, path) { | ||
@@ -738,52 +1154,3 @@ var commit = ref.commit; | ||
function index (moduleOptions) { | ||
var this$1 = this; | ||
// Use root level Druxt options. | ||
if (typeof this.options === 'undefined' || !this.options.druxt) { | ||
throw new TypeError('Druxt settings missing.') | ||
} | ||
var options = this.options.druxt; | ||
options.router = options.router || {}; | ||
this.extendRoutes(function (routes, resolve) { | ||
// Only add router component if custom component is undefined. | ||
// @TODO - Validate custom component. | ||
// @TODO - Add test for custom component. | ||
// @TODO - Document usage. | ||
if (!options.router.component) { | ||
options.router.component = resolve(this$1.options.buildDir, 'components/druxt-router.js'); | ||
this$1.addTemplate({ | ||
src: resolve(__dirname, '../nuxt/component.js'), | ||
fileName: 'components/druxt-router.js', | ||
options: options | ||
}); | ||
} | ||
// Add Druxt router custom wildcard route. | ||
routes.push({ | ||
name: 'druxt-router', | ||
path: '*', | ||
component: options.router.component, | ||
chunkName: 'druxt-router' | ||
}); | ||
}); | ||
// Add plugin. | ||
this.addPlugin({ | ||
src: resolve(__dirname, '../nuxt/plugin.js'), | ||
fileName: 'druxt-router.js', | ||
options: options | ||
}); | ||
// Add Vuex plugin. | ||
// @TODO - Ensure Vuex store is available. | ||
this.addPlugin({ | ||
src: resolve(__dirname, '../nuxt/store.js'), | ||
fileName: 'store/druxt-router.js', | ||
options: options | ||
}); | ||
} | ||
export default index; | ||
export default DruxtRouterModule; | ||
export { DruxtRouter, __vue_component__ as DruxtRouterComponent, DruxtRouterEntityMixin, DruxtRouterStore }; |
@@ -1,1 +0,1 @@ | ||
var DruxtRouter=function(t,e,r,i,o,n){"use strict";function s(t,e,r,i,o,n,s,a,u,d){"boolean"!=typeof s&&(u=a,a=s,s=!1);var c,p="function"==typeof r?r.options:r;if(t&&t.render&&(p.render=t.render,p.staticRenderFns=t.staticRenderFns,p._compiled=!0,o&&(p.functional=!0)),i&&(p._scopeId=i),n?(c=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),e&&e.call(this,u(t)),t&&t._registeredComponents&&t._registeredComponents.add(n)},p._ssrRegister=c):e&&(c=s?function(t){e.call(this,d(t,this.$root.$options.shadowRoot))}:function(t){e.call(this,a(t))}),c)if(p.functional){var h=p.render;p.render=function(t,e){return c.call(e),h(t,e)}}else{var f=p.beforeCreate;p.beforeCreate=f?[].concat(f,c):[c]}return r}o=o&&Object.prototype.hasOwnProperty.call(o,"default")?o.default:o,n=n&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n;var a=s({render:function(){var t=this.$createElement,e=this._self._c||t;return e("div",[this.route?e(this.component,this._b({tag:"component"},"component",this.props,!1)):this._e()],1)},staticRenderFns:[]},void 0,{name:"DruxtRouter",fetch:async function(t){var e=t.store,r=t.redirect,i=t.route,o=await e.dispatch("druxtRouter/get",i.fullPath);o.redirect&&r(o.redirect)},computed:Object.assign({},{component:function(){return this.route.component||!1},title:function(){return this.route.label||!1},props:function(){return this.route.props||!1}},r.mapState({redirect:function(t){return t.druxtRouter.redirect},route:function(t){return t.druxtRouter.route}})),head:function(){return{title:this.title,link:[{rel:"canonical",href:this.canonical||this.route.canonical}],meta:this.metatags||!1}}},void 0,!1,void 0,!1,void 0,void 0,void 0),u=function(t,e){if(void 0===e&&(e={}),!t)throw new Error("The 'baseURL' parameter is required.");var r={baseURL:t};"object"==typeof e.axios&&(r=Object.assign(r,e.axios),delete e.axios),this.axios=o.create(r),this.options=Object.assign({},{endpoint:"/jsonapi",jsonapiResourceConfig:"jsonapi_resource_config--jsonapi_resource_config",types:[{type:"entity",canonical:function(t){return t.entity.canonical},component:"druxt-entity",property:"entity",props:function(t){return{type:t.jsonapi.resourceName,uuid:t.entity.uuid}}},{type:"views",canonical:function(t){return t.resolved},component:"druxt-view",property:"view",props:function(t){return{displayId:t.view.display_id,type:t.jsonapi.resourceName,uuid:t.view.uuid,viewId:t.view.view_id}}}]},e),this.index=null};u.prototype.addHeaders=function(t){if(void 0===t)return!1;for(var e in t)this.axios.defaults.headers.common[e]=t[e]},u.prototype.buildQueryUrl=function(t,e){return e?"string"==typeof e?"?"===e.charAt(0)?t+e:[t,e].join("?"):"object"==typeof e&&"function"==typeof e.getQueryString?[t,e.getQueryString()].join("?"):"object"==typeof e&&Object.keys(e).length?[t,i.stringify(e)].join("?"):t:t},u.prototype.checkPermissions=function(t){if(t.data.meta&&t.data.meta.omitted){var e={};for(var r in delete t.data.meta.omitted.links.help,t.data.meta.omitted.links){var i=t.data.meta.omitted.links[r].meta.detail.match(/'(.*?)'/);i[1]&&(e[i[1]]=!0)}throw new TypeError(t.data.meta.omitted.detail+"\n\n Required permissions: "+Object.keys(e).join(", ")+".")}},u.prototype.get=async function(t){var e=await this.getRoute(t);return e.error?{route:e}:{redirect:this.getRedirect(t,e),route:e}},u.prototype.getIndex=async function(t){if(this.index&&!t)return this.index;if(this.index&&t)return!!this.index[t]&&this.index[t];var e=await this.axios.get(this.options.endpoint);if(this.index=e.data.links,this.index[this.options.jsonapiResourceConfig]){var r=await this.axios.get(this.index[this.options.jsonapiResourceConfig].href);for(var i in r.data.data){var o=r.data.data[i],n=o.attributes.drupal_internal__id.split("--"),s={resourceType:o.attributes.resourceType,entityType:n[0],bundle:n[1],resourceFields:o.attributes.resourceFields},a=[s.entityType,s.bundle].join("--");this.index[a]=Object.assign({},s,this.index[a])}}return t?!!this.index[t]&&this.index[t]:this.index},u.prototype.getRedirect=function(t,e){if(Array.isArray(e.redirect)&&void 0!==e.redirect[0].to)return e.redirect[0].to;if(e.isHomePath)return"/"!==t&&"/";if("string"==typeof e.canonical){var r=new n(e.canonical);if(t!==r.pathname)return r.pathname}return!1},u.prototype.getResource=async function(t){void 0===t&&(t={});var e=t.id,r=t.type;if(!e||!r)return!1;var i=(await this.getIndex(r)).href;i||(i=this.options.endpoint+"/"+r.replace("--","/"));var o=i+"/"+e;return(await this.axios.get(o)).data.data},u.prototype.getResources=async function(t,e,r){void 0===r&&(r={});var i=[],o=(await this.getIndex(t)).href;if(!o)return!1;var n=this.buildQueryUrl(o,e);this.addHeaders(r.headers);for(var s=!0;s;){var a=await this.axios.get(n);this.checkPermissions(a),i=i.concat(a.data.data),r.all&&a.data&&a.data.links&&a.data.links.next?n=a.data.links.next.href:s=!1}return i},u.prototype.getResourceByRoute=function(t){return this.getResource({id:t.entity.uuid,type:t.jsonapi.resourceName})},u.prototype.getRoute=async function(t){var e="/router/translate-path?path="+t,r=await this.axios.get(e,{validateStatus:function(t){return t<500}}),i=Object.assign({},{isHomePath:!1,jsonapi:{},label:!1,redirect:!1},r.data),o={error:!1,type:!1,canonical:!1,component:!1,isHomePath:i.isHomePath,jsonapi:i.jsonapi,label:i.label,props:!1,redirect:i.redirect,resolvedPath:n(i.resolved).pathname};for(var s in this.options.types){var a=Object.assign({},this.options.types[s]);if("string"==typeof a.property&&void 0!==i[a.property]){delete a.property,"function"==typeof a.canonical&&(a.canonical=a.canonical(i)),"function"==typeof a.props&&(a.props=a.props(i)),o=Object.assign({},o,a);break}}return r.status>=200&&r.status<300||(o.error={statusCode:r.status,message:r.statusText}),o};var d={props:{mode:{type:String,default:"default"},type:{type:String,required:!0},uuid:{type:String,required:!0}},data:function(){return{entity:!1,loading:!0}},created:function(){var t=this;void 0===this.entities[this.uuid]?!this.entity&&this.uuid&&this.type&&this.getEntity({id:this.uuid,type:this.type}).then((function(e){t.entity=e,t.loading=!1})):this.entity=this.entities[this.uuid]},computed:Object.assign({},r.mapState({entities:function(t){return t.druxtRouter.entities}})),methods:Object.assign({},r.mapActions({getEntity:"druxtRouter/getEntity"}))};return t.DruxtRouter=u,t.DruxtRouterComponent=a,t.DruxtRouterEntityMixin=d,t.DruxtRouterStore=function(t){var e=t.store;if(void 0===e)throw new TypeError("Vuex store not found.");e.registerModule("druxtRouter",{namespaced:!0,state:function(){return{entities:{},redirect:!1,route:{},routes:{}}},mutations:{addEntity:function(t,e){e&&void 0!==e.id&&(t.entities[e.id]=e)},setRedirect:function(t,e){t.redirect=e},addRoute:function(t,e){var r=e.path,i=e.route;"string"==typeof r&&void 0!==i&&(t.routes[r]=i)},setRoute:function(t,e){"string"==typeof e&&void 0!==t.routes[e]&&(t.route=t.routes[e])}},actions:{get:async function(t,e){var r=t.commit,i=t.dispatch,o=(t.state,await i("getRoute",e));if(o.error&&void 0!==o.error.statusCode)return this.app.context.error(o.error);r("setRoute",e);var n=this.$druxtRouter().getRedirect(e,o);return r("setRedirect",n),{redirect:n,route:o}},getEntity:async function(t,e){var r=t.commit,i=t.state;if(void 0!==i.entities[e.id])return i.entities[e.id];var o=await this.$druxtRouter().getResource(e);return r("addEntity",o),o},getResources:async function(t,e){t.commit,t.state;var r=e.resource,i=e.query,o=e.options;return await this.$druxtRouter().getResources(r,i,o)},getRoute:async function(t,e){var r=t.commit,i=t.state;if(void 0!==i.routes[e])return i.routes[e];var o=await this.$druxtRouter().getRoute(e);return r("addRoute",{path:e,route:o}),o}}},{preserveState:Boolean(e.state.druxtRouter)})},t.default=function(t){var r=this;if(void 0===this.options||!this.options.druxt)throw new TypeError("Druxt settings missing.");var i=this.options.druxt;i.router=i.router||{},this.extendRoutes((function(t,e){i.router.component||(i.router.component=e(r.options.buildDir,"components/druxt-router.js"),r.addTemplate({src:e(__dirname,"../nuxt/component.js"),fileName:"components/druxt-router.js",options:i})),t.push({name:"druxt-router",path:"*",component:i.router.component,chunkName:"druxt-router"})})),this.addPlugin({src:e.resolve(__dirname,"../nuxt/plugin.js"),fileName:"druxt-router.js",options:i}),this.addPlugin({src:e.resolve(__dirname,"../nuxt/store.js"),fileName:"store/druxt-router.js",options:i})},t}({},path,vuex,querystring,axios,Url); | ||
var DruxtRouter=function(t,e,r,i,n,o){"use strict";n=n&&Object.prototype.hasOwnProperty.call(n,"default")?n.default:n,o=o&&Object.prototype.hasOwnProperty.call(o,"default")?o.default:o;function s(t,e,r,i,n,o,s,a,u,d){"boolean"!=typeof s&&(u=a,a=s,s=!1);var c,p="function"==typeof r?r.options:r;if(t&&t.render&&(p.render=t.render,p.staticRenderFns=t.staticRenderFns,p._compiled=!0,n&&(p.functional=!0)),i&&(p._scopeId=i),o?(c=function(t){(t=t||this.$vnode&&this.$vnode.ssrContext||this.parent&&this.parent.$vnode&&this.parent.$vnode.ssrContext)||"undefined"==typeof __VUE_SSR_CONTEXT__||(t=__VUE_SSR_CONTEXT__),e&&e.call(this,u(t)),t&&t._registeredComponents&&t._registeredComponents.add(o)},p._ssrRegister=c):e&&(c=s?function(t){e.call(this,d(t,this.$root.$options.shadowRoot))}:function(t){e.call(this,a(t))}),c)if(p.functional){var f=p.render;p.render=function(t,e){return c.call(e),f(t,e)}}else{var h=p.beforeCreate;p.beforeCreate=h?[].concat(h,c):[c]}return r}var a=s({render:function(){var t=this,e=t.$createElement,r=t._self._c||e;return r("div",[t.route?r(t.component,t._b({tag:"component"},"component",t.props,!1)):t._e()],1)},staticRenderFns:[]},undefined,{name:"DruxtRouter",fetch:async function(t){var e=t.store,r=t.redirect,i=t.route,n=await e.dispatch("druxtRouter/get",i.fullPath);n.redirect&&r(n.redirect)},computed:Object.assign({},{component:function(){return this.route.component||!1},title:function(){return this.route.label||!1},props:function(){return this.route.props||!1}},r.mapState({redirect:function(t){return t.druxtRouter.redirect},route:function(t){return t.druxtRouter.route}})),head:function(){return{title:this.title,link:[{rel:"canonical",href:this.canonical||this.route.canonical}],meta:this.metatags||!1}}},undefined,false,undefined,!1,void 0,void 0,void 0),u=function(t,e){if(void 0===e&&(e={}),!t)throw new Error("The 'baseURL' parameter is required.");var r={baseURL:t};"object"==typeof e.axios&&(r=Object.assign(r,e.axios),delete e.axios),this.axios=n.create(r),this.options=Object.assign({},{endpoint:"/jsonapi",jsonapiResourceConfig:"jsonapi_resource_config--jsonapi_resource_config",types:[{type:"entity",canonical:function(t){return t.entity.canonical},component:"druxt-entity",property:"entity",props:function(t){return{type:t.jsonapi.resourceName,uuid:t.entity.uuid}}},{type:"views",canonical:function(t){return t.resolved},component:"druxt-view",property:"view",props:function(t){return{displayId:t.view.display_id,type:t.jsonapi.resourceName,uuid:t.view.uuid,viewId:t.view.view_id}}}]},e),this.index=null};u.prototype.addHeaders=function(t){if(void 0===t)return!1;for(var e in t)this.axios.defaults.headers.common[e]=t[e]},u.prototype.buildQueryUrl=function(t,e){return e?"string"==typeof e?"?"===e.charAt(0)?t+e:[t,e].join("?"):"object"==typeof e&&"function"==typeof e.getQueryString?[t,e.getQueryString()].join("?"):"object"==typeof e&&Object.keys(e).length?[t,i.stringify(e)].join("?"):t:t},u.prototype.checkPermissions=function(t){if(t.data.meta&&t.data.meta.omitted){var e={};for(var r in delete t.data.meta.omitted.links.help,t.data.meta.omitted.links){var i=t.data.meta.omitted.links[r].meta.detail.match(/'(.*?)'/);i[1]&&(e[i[1]]=!0)}throw new TypeError(t.data.meta.omitted.detail+"\n\n Required permissions: "+Object.keys(e).join(", ")+".")}},u.prototype.get=async function(t){var e=await this.getRoute(t);return e.error?{route:e}:{redirect:this.getRedirect(t,e),route:e}},u.prototype.getIndex=async function(t){if(this.index&&!t)return this.index;if(this.index&&t)return!!this.index[t]&&this.index[t];var e=await this.axios.get(this.options.endpoint);if(this.index=e.data.links,this.index[this.options.jsonapiResourceConfig]){var r=await this.axios.get(this.index[this.options.jsonapiResourceConfig].href);for(var i in r.data.data){var n=r.data.data[i],o=n.attributes.drupal_internal__id.split("--"),s={resourceType:n.attributes.resourceType,entityType:o[0],bundle:o[1],resourceFields:n.attributes.resourceFields},a=[s.entityType,s.bundle].join("--");this.index[a]=Object.assign({},s,this.index[a])}}return t?!!this.index[t]&&this.index[t]:this.index},u.prototype.getRedirect=function(t,e){if(Array.isArray(e.redirect)&&void 0!==e.redirect[0].to)return e.redirect[0].to;if(e.isHomePath)return"/"!==t&&"/";if("string"==typeof e.canonical){var r=new o(e.canonical);if(t!==r.pathname)return r.pathname}return!1},u.prototype.getResource=async function(t){void 0===t&&(t={});var e=t.id,r=t.type;if(!e||!r)return!1;var i=(await this.getIndex(r)).href;i||(i=this.options.endpoint+"/"+r.replace("--","/"));var n=i+"/"+e;try{return(await this.axios.get(n)).data.data}catch(t){return!1}},u.prototype.getResources=async function(t,e,r){void 0===r&&(r={});var i=[],n=(await this.getIndex(t)).href;if(!n)return!1;var o=this.buildQueryUrl(n,e);this.addHeaders(r.headers);for(var s=!0;s;){var a=await this.axios.get(o);this.checkPermissions(a),i=i.concat(a.data.data),r.all&&a.data&&a.data.links&&a.data.links.next?o=a.data.links.next.href:s=!1}return i},u.prototype.getResourceByRoute=function(t){return this.getResource({id:t.entity.uuid,type:t.jsonapi.resourceName})},u.prototype.getRoute=async function(t){var e="/router/translate-path?path="+t,r=await this.axios.get(e,{validateStatus:function(t){return t<500}}),i=Object.assign({},{isHomePath:!1,jsonapi:{},label:!1,redirect:!1},r.data),n={error:!1,type:!1,canonical:!1,component:!1,isHomePath:i.isHomePath,jsonapi:i.jsonapi,label:i.label,props:!1,redirect:i.redirect,resolvedPath:o(i.resolved).pathname};for(var s in this.options.types){var a=Object.assign({},this.options.types[s]);if("string"==typeof a.property&&void 0!==i[a.property]){delete a.property,"function"==typeof a.canonical&&(a.canonical=a.canonical(i)),"function"==typeof a.props&&(a.props=a.props(i)),n=Object.assign({},n,a);break}}return r.status>=200&&r.status<300||(n.error={statusCode:r.status,message:r.statusText}),n};var d={props:{mode:{type:String,default:"default"},type:{type:String,required:!0},uuid:{type:String,required:!0}},fetch:async function(){void 0===this.entities[this.uuid]?!this.entity&&this.uuid&&this.type&&(this.entity=await this.getEntity({id:this.uuid,type:this.type}),this.loading=!1):this.entity=this.entities[this.uuid]},data:function(){return{entity:!1,loading:!0}},computed:Object.assign({},r.mapState({entities:function(t){return t.druxtRouter.entities}})),methods:Object.assign({},r.mapActions({getEntity:"druxtRouter/getEntity"}))};return t.DruxtRouter=u,t.DruxtRouterComponent=a,t.DruxtRouterEntityMixin=d,t.DruxtRouterStore=function(t){var e=t.store;if(void 0===e)throw new TypeError("Vuex store not found.");var r="druxtRouter";e.registerModule(r,{namespaced:!0,state:function(){return{entities:{},redirect:!1,route:{},routes:{}}},mutations:{addEntity:function(t,e){e&&void 0!==e.id&&(t.entities[e.id]=e)},setRedirect:function(t,e){t.redirect=e},addRoute:function(t,e){var r=e.path,i=e.route;"string"==typeof r&&void 0!==i&&(t.routes[r]=i)},setRoute:function(t,e){"string"==typeof e&&void 0!==t.routes[e]&&(t.route=t.routes[e])}},actions:{get:async function(t,e){var r=t.commit,i=t.dispatch,n=(t.state,await i("getRoute",e));if(n.error&&void 0!==n.error.statusCode)return this.app.context.error(n.error);r("setRoute",e);var o=this.$druxtRouter().getRedirect(e,n);return r("setRedirect",o),{redirect:o,route:n}},getEntity:async function(t,e){var r=t.commit,i=t.state;if(void 0!==i.entities[e.id])return i.entities[e.id];var n=await this.$druxtRouter().getResource(e);return r("addEntity",n),n},getResources:async function(t,e){t.commit,t.state;var r=e.resource,i=e.query,n=e.options;return await this.$druxtRouter().getResources(r,i,n)},getRoute:async function(t,e){var r=t.commit,i=t.state;if(void 0!==i.routes[e])return i.routes[e];var n=await this.$druxtRouter().getRoute(e);return r("addRoute",{path:e,route:n}),n}}},{preserveState:Boolean(e.state[r])})},t.default=function(t){var r=this;if(void 0===this.options||!this.options.druxt)throw new TypeError("Druxt settings missing.");var i=this.options.druxt;i.router=i.router||{},this.extendRoutes((function(t,e){i.router.component||(i.router.component=e(r.options.buildDir,"components/druxt-router.js"),r.addTemplate({src:e(__dirname,"../nuxt/component.js"),fileName:"components/druxt-router.js",options:i})),t.push({name:"druxt-router",path:"*",component:i.router.component,chunkName:"druxt-router"})})),this.addPlugin({src:e.resolve(__dirname,"../nuxt/plugin.js"),fileName:"druxt-router.js",options:i}),this.addPlugin({src:e.resolve(__dirname,"../nuxt/store.js"),fileName:"store/druxt-router.js",options:i})},t}({},path,vuex,querystring,axios,Url); |
@@ -1,6 +0,102 @@ | ||
'use strict';Object.defineProperty(exports,'__esModule',{value:true});function _interopDefault(e){return(e&&(typeof e==='object')&&'default'in e)?e['default']:e}var path=require('path'),vuex=require('vuex'),querystring=require('querystring'),axios=_interopDefault(require('axios')),Url=_interopDefault(require('url-parse'));// | ||
'use strict';Object.defineProperty(exports,'__esModule',{value:true});function _interopDefault(e){return(e&&(typeof e==='object')&&'default'in e)?e['default']:e}var path=require('path'),vuex=require('vuex'),querystring=require('querystring'),axios=_interopDefault(require('axios')),Url=_interopDefault(require('url-parse'));/** | ||
* @vuepress | ||
* --- | ||
* title: DruxtRouterModule | ||
* --- | ||
*/ | ||
/** | ||
* The Nuxt.js module function. | ||
* | ||
* - Extends the Vue router, adding the Druxt wildcard route. | ||
* - Adds the Druxt router plugin. | ||
* - Adds the Druxt router Vuex store. | ||
* | ||
* The module function should not be used directly, but rather installed via yout Nuxt.js configuration file. | ||
* | ||
* Options are set on the root level `druxt` Nuxt.js config object. | ||
* | ||
* @example @lang js | ||
* // `nuxt.config.js` | ||
* module.exports = { | ||
* modules: [ | ||
* 'druxt-router' | ||
* ], | ||
* druxt: { | ||
* baseUrl: 'https://example.com' | ||
* } | ||
* } | ||
* | ||
* @todo [Add module level options]{@link https://github.com/druxt/druxt-router/issues/53} | ||
* | ||
* @property {object} options.druxt - Druxt.js root level options. | ||
* @property {string} options.druxt.baseUrl - Base URL of Drupal JSON:API backend. | ||
* @property {string} options.druxt.router.component - File to custom Router component. | ||
*/ | ||
var DruxtRouterModule = function (moduleOptions) { | ||
var this$1 = this; | ||
// Use root level Druxt options. | ||
if (typeof this.options === 'undefined' || !this.options.druxt) { | ||
throw new TypeError('Druxt settings missing.') | ||
} | ||
var options = this.options.druxt; | ||
options.router = options.router || {}; | ||
this.extendRoutes(function (routes, resolve) { | ||
// Only add router component if custom component is undefined. | ||
// @TODO - Validate custom component. | ||
// @TODO - Add test for custom component. | ||
// @TODO - Document usage. | ||
if (!options.router.component) { | ||
options.router.component = resolve(this$1.options.buildDir, 'components/druxt-router.js'); | ||
this$1.addTemplate({ | ||
src: resolve(__dirname, '../nuxt/component.js'), | ||
fileName: 'components/druxt-router.js', | ||
options: options | ||
}); | ||
} | ||
// Add Druxt router custom wildcard route. | ||
routes.push({ | ||
name: 'druxt-router', | ||
path: '*', | ||
component: options.router.component, | ||
chunkName: 'druxt-router' | ||
}); | ||
}); | ||
// Add plugin. | ||
this.addPlugin({ | ||
src: path.resolve(__dirname, '../nuxt/plugin.js'), | ||
fileName: 'druxt-router.js', | ||
options: options | ||
}); | ||
// Add Vuex plugin. | ||
// @TODO - Ensure Vuex store is available. | ||
this.addPlugin({ | ||
src: path.resolve(__dirname, '../nuxt/store.js'), | ||
fileName: 'store/druxt-router.js', | ||
options: options | ||
}); | ||
};// | ||
/** | ||
* The DruxtRouter Vue.js component. | ||
* | ||
* @example @lang vue | ||
* <druxt-router /> | ||
*/ | ||
var script = { | ||
name: 'DruxtRouter', | ||
/** | ||
* Nuxt.js fetch method. | ||
* | ||
* - Loads the route and redirect information from the Vuex store. | ||
* - Resolves redirects. | ||
* | ||
* @see {@link https://nuxtjs.org/api/pages-fetch/} | ||
*/ | ||
fetch: async function fetch (ref) { | ||
@@ -19,2 +115,8 @@ var store = ref.store; | ||
/** | ||
* Vue.js Computed properties. | ||
* | ||
* @vue-computed {object} redirect The current Redirect, if applicable. | ||
* @vue-computed {object} route The current Route. | ||
*/ | ||
computed: Object.assign({}, {component: function component () { | ||
@@ -24,2 +126,7 @@ return this.route.component || false | ||
/** | ||
* Route title. | ||
* @type {boolean|string} | ||
* @default false | ||
*/ | ||
title: function title () { | ||
@@ -29,2 +136,7 @@ return this.route.label || false | ||
/** | ||
* Route component property data. | ||
* @type {object|string} | ||
* @default false | ||
*/ | ||
props: function props () { | ||
@@ -39,2 +151,11 @@ return this.route.props || false | ||
/** | ||
* Nuxt.js head method. | ||
* | ||
* - Sets the page title. | ||
* - Sets the canonical link. | ||
* | ||
* @see {@link https://nuxtjs.org/api/pages-head/} | ||
* @todo Improve metatag support. | ||
*/ | ||
head: function head () { | ||
@@ -137,3 +258,3 @@ return { | ||
/* module identifier */ | ||
var __vue_module_identifier__ = "data-v-2ba51c20"; | ||
var __vue_module_identifier__ = "data-v-3f5ed9e1"; | ||
/* functional template */ | ||
@@ -160,3 +281,15 @@ var __vue_is_functional_template__ = false; | ||
undefined | ||
);var DruxtRouter = function DruxtRouter (baseURL, options) { | ||
);/** | ||
* @vuepress | ||
* --- | ||
* title: DruxtRouter | ||
* --- | ||
*/ | ||
/** | ||
* DruxtRouter class. | ||
* | ||
* Provides core Drupal JSON:API query functionality. | ||
*/ | ||
var DruxtRouter = function DruxtRouter (baseURL, options) { | ||
if ( options === void 0 ) options = {}; | ||
@@ -175,4 +308,15 @@ | ||
} | ||
/** | ||
* Axios instance. | ||
* @see {@link https://github.com/axios/axios#instance-methods} | ||
* @type {object} | ||
*/ | ||
this.axios = axios.create(axiosSettings); | ||
/** | ||
* Druxt router options. | ||
* @type {object} | ||
* @private | ||
*/ | ||
this.options = Object.assign({}, {endpoint: '/jsonapi', | ||
@@ -207,2 +351,7 @@ jsonapiResourceConfig: 'jsonapi_resource_config--jsonapi_resource_config', | ||
/** | ||
* Drupal JSON:API index. | ||
* @type {object} | ||
* @private | ||
*/ | ||
this.index = null; | ||
@@ -214,3 +363,6 @@ }; | ||
* | ||
* @param {*} headers | ||
* @example @lang js | ||
* router.addHeaders({ 'Authorization': `Basic ${token}` }) | ||
* | ||
* @param {object} headers - An object containing HTTP headers. | ||
*/ | ||
@@ -230,4 +382,11 @@ DruxtRouter.prototype.addHeaders = function addHeaders (headers) { | ||
* | ||
* @param string url | ||
* @param {*} query | ||
* @example @lang js | ||
* const query = new DrupalJsonApiParams() | ||
* query.addFilter('status', '1') | ||
* const queryUrl = router.buildQueryUrl(resourceUrl, query) | ||
* | ||
* @param {string} url - The base query URL. | ||
* @param {string|object} [query] - A correctly formatted JSON:API query string or object. | ||
* | ||
* @return {string} The URL with query string. | ||
*/ | ||
@@ -261,3 +420,7 @@ DruxtRouter.prototype.buildQueryUrl = function buildQueryUrl (url, query) { | ||
* | ||
* @param {*} res | ||
* @todo - Move this to utils? | ||
* | ||
* @param {object} res - Axios GET request response object. | ||
* | ||
* @private | ||
*/ | ||
@@ -283,5 +446,10 @@ DruxtRouter.prototype.checkPermissions = function checkPermissions (res) { | ||
/** | ||
* Returns Drupal entity and route for given path. | ||
* Returns route and redirect data for a given path. | ||
* | ||
* @param string path | ||
* @example @lang js | ||
* const { redirect, route } = await router.get('/node/1') | ||
* | ||
* @param {string} path - The route path. | ||
* | ||
* @returns {object} The route and redirect data. | ||
*/ | ||
@@ -300,3 +468,10 @@ DruxtRouter.prototype.get = async function get (path) { | ||
/** | ||
* Get index of all available resources. | ||
* Get index of all available resources, or the optionally specified resource. | ||
* | ||
* @example @lang js | ||
* const { href } = await router.getIndex('node--article') | ||
* | ||
* @param {string} resource - (Optional) A specific resource to query. | ||
* | ||
* @returns {object} The resource index object or the specified resource. | ||
*/ | ||
@@ -343,3 +518,15 @@ DruxtRouter.prototype.getIndex = async function getIndex (resource) { | ||
/** | ||
* @param object route | ||
* Get redirect data for a given route. | ||
* | ||
* @example @lang js | ||
* const route = await router.getRoute(path) | ||
* const redirect = router.getRedirect(path, route) | ||
* | ||
* @todo Move this to a DruxtRouterRedirect class. | ||
* @todo Remove the path parameter. | ||
* | ||
* @param {string} path - The route path. | ||
* @param {object} route - Druxt route object. | ||
* | ||
* @returns {boolean|string} The redirect path or false. | ||
*/ | ||
@@ -376,4 +563,9 @@ DruxtRouter.prototype.getRedirect = function getRedirect (path, route) { | ||
* | ||
* @param string type | ||
* @param string id | ||
* @example @lang js | ||
* const data = await router.get({ type: 'node--article', id }) | ||
* | ||
* @param {string} type - The JSON:API resource type. | ||
* @param {string} id - The Drupal resource UUID. | ||
* | ||
* @returns {object} The JSON:API resource data. | ||
*/ | ||
@@ -396,14 +588,26 @@ DruxtRouter.prototype.getResource = async function getResource (query) { | ||
var url = href + "/" + id; | ||
var resource = await this.axios.get(url); | ||
return resource.data.data | ||
try { | ||
var resource = await this.axios.get(url); | ||
return resource.data.data | ||
} catch (e) { | ||
return false | ||
} | ||
}; | ||
/** | ||
* Get all resources based on resource and query. | ||
* Gets a collection of resources. | ||
* | ||
* @todo Add pagination. | ||
* @todo Add granular pagination. | ||
* | ||
* @param {*} resource | ||
* @param {*} query | ||
* @example @lang js | ||
* // Load all currently published Articles. | ||
* const query = new DrupalJsonApiParams() | ||
* query.addFilter('status', '1') | ||
* const resources = await router.getResources('node--article', query, { all: true }) | ||
* | ||
* @param {string} resource - The JSON:API resource type. | ||
* @param {string|object} query - A JSON:API query string or object. | ||
* @param {object} [options] | ||
* @param {boolean} [options.all=false] - Load all results. | ||
* @return {object[]} Array of resources. | ||
*/ | ||
@@ -446,3 +650,9 @@ DruxtRouter.prototype.getResources = async function getResources (resource, query, options) { | ||
* | ||
* @param object route | ||
* @example @lang js | ||
* const route = await router.getRoute('/') | ||
* const data = await router.getResourceByRoute(route) | ||
* | ||
* @param {object} route - Druxt Router route object. | ||
* | ||
* @returns {object} The JSON:API resource data. | ||
*/ | ||
@@ -456,3 +666,8 @@ DruxtRouter.prototype.getResourceByRoute = function getResourceByRoute (route) { | ||
* | ||
* @param string path | ||
* @example @lang js | ||
* const route = await router.getRoute('/') | ||
* | ||
* @param {string} path - The route path. | ||
* | ||
* @returns {object} The route object. | ||
*/ | ||
@@ -525,9 +740,41 @@ DruxtRouter.prototype.getRoute = async function getRoute (path) { | ||
};/** | ||
* @vuepress | ||
* --- | ||
* title: DruxtRouterEntityMixin | ||
* --- | ||
*/ | ||
/** | ||
* The DruxtRouterEntityMixin Vue.js mixin provides easy integration with the Druxt.js Router Vuex store, including on-demand loading of JSON:API resources. | ||
* | ||
* @mixin | ||
* | ||
* @example @lang vue | ||
* <template> | ||
* <div v-if="entity && !loading"> | ||
* {{ entity }} | ||
* </div> | ||
* </template> | ||
* | ||
* <script> | ||
* // Import mixin. | ||
* import { DruxtRouterEntityMixin } from 'druxt-router' | ||
* | ||
* export default { | ||
* // Set mixin. | ||
* mixins: [DruxtRouterEntityMixin] | ||
* } | ||
* </script> | ||
*/ | ||
var DruxtRouterEntityMixin = { | ||
/** | ||
* Props. | ||
* Vue.js Properties. | ||
*/ | ||
props: { | ||
/** | ||
* The Drupal display mode. | ||
* | ||
* @type {string} | ||
* @default default | ||
*/ | ||
mode: { | ||
@@ -538,2 +785,7 @@ type: String, | ||
/** | ||
* The JSON:API resource type. | ||
* | ||
* @type {string} | ||
*/ | ||
type: { | ||
@@ -546,2 +798,4 @@ type: String, | ||
* The Drupal entity UUID. | ||
* | ||
* @type {string} | ||
*/ | ||
@@ -554,10 +808,7 @@ uuid: { | ||
data: function () { return ({ | ||
entity: false, | ||
loading: true | ||
}); }, | ||
created: function created () { | ||
var this$1 = this; | ||
/** | ||
* Loads the JSON:API resource via the Vuex store. | ||
*/ | ||
fetch: async function fetch () { | ||
// Use resource from Vuex store if available. | ||
if (typeof this.entities[this.uuid] !== 'undefined') { | ||
@@ -568,10 +819,30 @@ this.entity = this.entities[this.uuid]; | ||
// Otherwise invoke getEntity() to retrieve it from Drupal. | ||
if (!this.entity && this.uuid && this.type) { | ||
this.getEntity({ id: this.uuid, type: this.type }).then(function (res) { | ||
this$1.entity = res; | ||
this$1.loading = false; | ||
}); | ||
this.entity = await this.getEntity({ id: this.uuid, type: this.type }); | ||
this.loading = false; | ||
} | ||
}, | ||
/** | ||
* Vue.js Data object. | ||
* | ||
* Used for on-demand JSON:API resource loading. | ||
* | ||
* @property {object} entity - The Drupal entity JSON:API resource. | ||
* @property {boolean} loading - The loading state. | ||
*/ | ||
data: function () { return ({ | ||
entity: false, | ||
loading: true | ||
}); }, | ||
/** | ||
* Vue.js Computed properties. | ||
* | ||
* - Maps Vuex `entities` state to `this->entities`. | ||
* | ||
* @property {object} entities - The mapped Druxt.js Router Vuex `entities` state. | ||
* @see {@link store|src/store.js} | ||
*/ | ||
computed: Object.assign({}, vuex.mapState({ | ||
@@ -581,7 +852,13 @@ entities: function (state) { return state.druxtRouter.entities; } | ||
/** | ||
* Vue.js Methods. | ||
* | ||
* - Maps Vuex `druxtRouter/getEntity` action to `this->getEntity()`. | ||
* | ||
* @see {@link store|src/store.js} | ||
*/ | ||
methods: Object.assign({}, vuex.mapActions({ | ||
getEntity: 'druxtRouter/getEntity' | ||
})) | ||
};// @TODO - Add Vuex test coverage. | ||
var DruxtRouterStore = function (ref) { | ||
};var DruxtRouterStore = function (ref) { | ||
var store = ref.store; | ||
@@ -593,6 +870,31 @@ | ||
/** | ||
* @namespace | ||
*/ | ||
var namespace = 'druxtRouter'; | ||
/** | ||
* The druxtRouter Vuex module. | ||
* | ||
* Provides a Vuex state object, mutations and actions for interacting with the Drupal JSON:API. | ||
* | ||
* @name druxtRouter | ||
* @module druxtRouter | ||
* | ||
* @todo Replace 'entit(y|ies)' with 'resource(s)' | ||
*/ | ||
var module = { | ||
namespaced: true, | ||
/** | ||
* Vuex State object. | ||
* | ||
* @name state | ||
* @type {object} | ||
* @property {object} entities - Drupal entity store. | ||
* @property {boolean|object} redirect - Active redirect. | ||
* @property {object} route - Active route. | ||
* @property {object} routes - Route store. | ||
* @readonly | ||
*/ | ||
state: function () { return ({ | ||
@@ -605,3 +907,14 @@ entities: {}, | ||
/** | ||
* Vuex Mutations. | ||
*/ | ||
mutations: { | ||
/** | ||
* @name addEntity | ||
* @mutator {object} addEntity=entities Adds specified Drupal entity JSON:API resource data to the Vuex state object. | ||
* @param {object} entity - The Drupal entity JSON:API resource data. | ||
* | ||
* @example @lang js | ||
* this.$store.commit('druxtRouter/addEntity', entity) | ||
*/ | ||
addEntity: function addEntity (state, entity) { | ||
@@ -615,2 +928,10 @@ if (!entity || typeof entity.id === 'undefined') { | ||
/** | ||
* @name setRedirect | ||
* @mutator {object} setRedirect=redirect Sets the active redirect. | ||
* @param {object} redirect - The Redirect object. | ||
* | ||
* @example @lang js | ||
* this.$store.commit('druxtRouter/setRedirect', redirect) | ||
*/ | ||
setRedirect: function setRedirect (state, redirect) { | ||
@@ -620,2 +941,12 @@ state.redirect = redirect; | ||
/** | ||
* @name addRoute | ||
* @mutator {object} addRoute=routes Adds the supplied route to the Vuex state object. | ||
* @param {object} context | ||
* @param {string} context.path - The route path. | ||
* @param {object} context.route - The route object. | ||
* | ||
* @example @lang js | ||
* this.$store.commit('druxtRouter/addRoute', { path, route }) | ||
*/ | ||
addRoute: function addRoute (state, ref) { | ||
@@ -633,2 +964,10 @@ var path = ref.path; | ||
/** | ||
* @name setRoute | ||
* @mutator {string} setRoute=route Sets the active route by path. | ||
* @param {string} path - The route path | ||
* | ||
* @example @lang js | ||
* this.$store.commit('druxtRouter/setRoute', '/') | ||
*/ | ||
setRoute: function setRoute (state, path) { | ||
@@ -644,3 +983,21 @@ if (typeof path !== 'string' || typeof state.routes[path] === 'undefined') { | ||
/** | ||
* Vuex Actions. | ||
*/ | ||
actions: { | ||
/** | ||
* Get route and redirect information. | ||
* | ||
* - Dispatches `druxtRouter/getRoute` action. | ||
* - Sets the active route. | ||
* - Sets the active redirect. | ||
* | ||
* @name get | ||
* @action get=route | ||
* @param {string} path The router path. | ||
* @return {object} The route and redirect information. | ||
* | ||
* @example @lang js | ||
* const { redirect, route } = await this.$store.dispatch('druxtRouter/get', '/') | ||
*/ | ||
get: async function get (ref, path) { | ||
@@ -659,4 +1016,6 @@ var commit = ref.commit; | ||
// Set active route. | ||
commit('setRoute', path); | ||
// Set active redirect. | ||
var redirect = this.$druxtRouter().getRedirect(path, route); | ||
@@ -668,3 +1027,19 @@ commit('setRedirect', redirect); | ||
// @TODO - Move this into druxt-entity. | ||
/** | ||
* Get Entity. | ||
* | ||
* - Executes query against Drupal JSON:API. | ||
* - Caches result in the Vuex store. | ||
* - Returns cached result from Vuex store when available. | ||
* | ||
* @name getEntity | ||
* @action getEntity=entities | ||
* @param {object} query | ||
* @return {object} The Drupal entity JSON:API resource data. | ||
* | ||
* @example @lang js | ||
* const entity = await this.$store.dispatch('druxtRouter/getEntity', { type: 'node--article', id }) | ||
* | ||
* @todo Rename getEntity to getResource. | ||
*/ | ||
getEntity: async function getEntity (ref, query) { | ||
@@ -685,2 +1060,26 @@ var commit = ref.commit; | ||
/** | ||
* Get multiple resources. | ||
* | ||
* @name getResources | ||
* @action getResources | ||
* @param {object} context Object containing `druxtRouter.getResources()` parameters. | ||
* @param {string} context.resource - The JSON:API resource type. | ||
* @param {string|object} context.query - A JSON:API query string or object. | ||
* @param {object} [context.options] | ||
* @param {boolean} [context.options.all=false] - Load all results. | ||
* @return {object[]} Array of Drupal JSON:API resource data. | ||
* | ||
* @example @lang js | ||
* // Load all currently published Articles. | ||
* const query = new DrupalJsonApiParams() | ||
* query.addFilter('status', '1') | ||
* const resources = await this.$store.dispatch('druxtRouter/getResources', { | ||
* resource: 'node--article', | ||
* query, | ||
* options: { all: true } | ||
* }) | ||
* | ||
* @todo Add Vuex store caching for getResources. | ||
*/ | ||
getResources: async function getResources (ref, ref$1) { | ||
@@ -698,2 +1097,17 @@ var commit = ref.commit; | ||
/** | ||
* Get Route. | ||
* | ||
* - Executes query against Drupal Decoupled router. | ||
* - Caches result in the Vuex store. | ||
* - Returns cached result from Vuex store when available. | ||
* | ||
* @name getRoute | ||
* @action getRoute=route | ||
* @param {string} path - The route path. | ||
* @return {object} The route object. | ||
* | ||
* @example @lang js | ||
* const route = await this.$store.dispatch('druxtRouter/getRoute', '/') | ||
*/ | ||
getRoute: async function getRoute (ref, path) { | ||
@@ -719,49 +1133,2 @@ var commit = ref.commit; | ||
}); | ||
};function index (moduleOptions) { | ||
var this$1 = this; | ||
// Use root level Druxt options. | ||
if (typeof this.options === 'undefined' || !this.options.druxt) { | ||
throw new TypeError('Druxt settings missing.') | ||
} | ||
var options = this.options.druxt; | ||
options.router = options.router || {}; | ||
this.extendRoutes(function (routes, resolve) { | ||
// Only add router component if custom component is undefined. | ||
// @TODO - Validate custom component. | ||
// @TODO - Add test for custom component. | ||
// @TODO - Document usage. | ||
if (!options.router.component) { | ||
options.router.component = resolve(this$1.options.buildDir, 'components/druxt-router.js'); | ||
this$1.addTemplate({ | ||
src: resolve(__dirname, '../nuxt/component.js'), | ||
fileName: 'components/druxt-router.js', | ||
options: options | ||
}); | ||
} | ||
// Add Druxt router custom wildcard route. | ||
routes.push({ | ||
name: 'druxt-router', | ||
path: '*', | ||
component: options.router.component, | ||
chunkName: 'druxt-router' | ||
}); | ||
}); | ||
// Add plugin. | ||
this.addPlugin({ | ||
src: path.resolve(__dirname, '../nuxt/plugin.js'), | ||
fileName: 'druxt-router.js', | ||
options: options | ||
}); | ||
// Add Vuex plugin. | ||
// @TODO - Ensure Vuex store is available. | ||
this.addPlugin({ | ||
src: path.resolve(__dirname, '../nuxt/store.js'), | ||
fileName: 'store/druxt-router.js', | ||
options: options | ||
}); | ||
}exports.DruxtRouter=DruxtRouter;exports.DruxtRouterComponent=__vue_component__;exports.DruxtRouterEntityMixin=DruxtRouterEntityMixin;exports.DruxtRouterStore=DruxtRouterStore;exports.default=index; | ||
};exports.DruxtRouter=DruxtRouter;exports.DruxtRouterComponent=__vue_component__;exports.DruxtRouterEntityMixin=DruxtRouterEntityMixin;exports.DruxtRouterStore=DruxtRouterStore;exports.default=DruxtRouterModule; |
{ | ||
"name": "druxt-router", | ||
"version": "0.15.0", | ||
"description": "Provides a Nuxt <-> Drupal router.", | ||
"version": "0.16.0", | ||
"description": "Simple decoupled Drupal routing for Nuxt.js.", | ||
"files": [ | ||
@@ -13,10 +13,12 @@ "dist", | ||
"scripts": { | ||
"lint": "eslint --ext .js,.vue src", | ||
"start": "npm run dev", | ||
"dev": "nodemon --ext js,vue --exec 'npm run lint && npm run build && npm run test'", | ||
"test": "jest", | ||
"build": "cross-env NODE_ENV=production rollup -c", | ||
"build:ssr": "cross-env NODE_ENV=production rollup -c --format cjs", | ||
"build:es": "cross-env NODE_ENV=production rollup -c --format es", | ||
"build:unpkg": "cross-env NODE_ENV=production rollup -c --format iife" | ||
"build:unpkg": "cross-env NODE_ENV=production rollup -c --format iife", | ||
"dev": "nodemon --ext js,vue --exec 'npm run lint && npm run build && npm run test'", | ||
"docs:dev": "druxt-docgen dev", | ||
"docs:build": "druxt-docgen build", | ||
"lint": "eslint --ext .js,.vue src", | ||
"start": "npm run dev", | ||
"test": "jest" | ||
}, | ||
@@ -30,3 +32,3 @@ "nodemonConfig": { | ||
"type": "git", | ||
"url": "git+https://github.com/Realityloop/druxt_router.git" | ||
"url": "git+https://github.com/druxt/druxt_router.git" | ||
}, | ||
@@ -45,8 +47,8 @@ "keywords": [ | ||
"bugs": { | ||
"url": "https://github.com/Realityloop/druxt_router/issues" | ||
"url": "https://github.com/druxt/druxt_router/issues" | ||
}, | ||
"homepage": "https://github.com/Realityloop/druxt_router#readme", | ||
"homepage": "https://github.com/druxt/druxt_router#readme", | ||
"dependencies": { | ||
"axios": "^0.19.2", | ||
"codecov": "^3.7.0", | ||
"codecov": "^3.7.2", | ||
"querystring": "^0.2.0", | ||
@@ -56,11 +58,11 @@ "url-parse": "^1.4.7" | ||
"devDependencies": { | ||
"@babel/node": "^7.8.7", | ||
"@babel/plugin-transform-runtime": "^7.9.6", | ||
"@babel/preset-env": "^7.9.6", | ||
"@babel/runtime": "^7.9.6", | ||
"@babel/node": "^7.10.5", | ||
"@babel/plugin-transform-runtime": "^7.11.0", | ||
"@babel/preset-env": "^7.11.0", | ||
"@babel/runtime": "^7.11.2", | ||
"@nuxtjs/eslint-config": "^2.0.2", | ||
"@rollup/plugin-alias": "^3.1.0", | ||
"@rollup/plugin-alias": "^3.1.1", | ||
"@rollup/plugin-buble": "^0.21.3", | ||
"@rollup/plugin-replace": "^2.3.2", | ||
"@vue/test-utils": "^1.0.2", | ||
"@rollup/plugin-replace": "^2.3.3", | ||
"@vue/test-utils": "^1.0.4", | ||
"babel-core": "^7.0.0-bridge.0", | ||
@@ -70,17 +72,22 @@ "babel-eslint": "^10.1.0", | ||
"cross-env": "^7.0.2", | ||
"druxt-docgen": "^0.2.4", | ||
"eslint": "^6.8.0", | ||
"get-port": "^5.1.1", | ||
"jest": "^24.9.0", | ||
"gh-pages": "^3.1.0", | ||
"jest": "^26.4.2", | ||
"jest-junit": "^11.1.0", | ||
"jest-mock-axios": "^3.2.0", | ||
"md5": "^2.2.1", | ||
"nodemon": "^2.0.3", | ||
"md5": "^2.3.0", | ||
"nodemon": "^2.0.4", | ||
"nuxt-edge": "^2.11.0-26277131.7af9ec8c", | ||
"require-directory": "^2.1.1", | ||
"rollup": "^1.32.1", | ||
"rollup-plugin-commonjs": "^10.1.0", | ||
"rollup-plugin-terser": "^5.3.0", | ||
"rollup-plugin-vue": "^5.1.7", | ||
"vue": "^2.6.11", | ||
"vue-jest": "^3.0.5", | ||
"vue-server-renderer": "^2.6.11", | ||
"vue-template-compiler": "^2.6.11" | ||
"rollup-plugin-terser": "^7.0.0", | ||
"rollup-plugin-vue": "^5.1.9", | ||
"vue": "^2.6.12", | ||
"vue-jest": "^3.0.6", | ||
"vue-server-renderer": "^2.6.12", | ||
"vue-template-compiler": "^2.6.12", | ||
"vuepress-theme-druxt": "^0.2.1" | ||
}, | ||
@@ -87,0 +94,0 @@ "jest": { |
@@ -1,9 +0,21 @@ | ||
# Druxt router | ||
# Druxt.js Router | ||
[![CircleCI](https://circleci.com/gh/Realityloop/druxt-router.svg?style=svg)](https://circleci.com/gh/Realityloop/druxt-router) | ||
[![Known Vulnerabilities](https://snyk.io//test/github/Realityloop/druxt-router/badge.svg?targetFile=package.json)](https://snyk.io//test/github/Realityloop/druxt-router?targetFile=package.json) | ||
[![codecov](https://codecov.io/gh/Realityloop/druxt-router/branch/develop/graph/badge.svg)](https://codecov.io/gh/Realityloop/druxt-router) | ||
[![CircleCI](https://circleci.com/gh/druxt/druxt-router.svg?style=svg)](https://circleci.com/gh/druxt/druxt-router) | ||
[![Known Vulnerabilities](https://snyk.io//test/github/druxt/druxt-router/badge.svg?targetFile=package.json)](https://snyk.io//test/github/druxt/druxt-router?targetFile=package.json) | ||
[![codecov](https://codecov.io/gh/druxt/druxt-router/branch/develop/graph/badge.svg)](https://codecov.io/gh/druxt/druxt-router) | ||
Druxt (DRUpal nuXT) is a Nuxt module that provides an easy connection between a Nuxt frontend and Drupal backend. | ||
Simple decoupled [Drupal](https://drupal.org) routing for your [Nuxt.js](https://nuxtjs.org) application. | ||
## Links | ||
- Druxt.js: https://druxtjs.org | ||
- Documentation: https://router.druxtjs.org | ||
## Features | ||
- Nuxt.js module with out of the box page routing: `druxt-router` | ||
- Vuex store: `druxtRouter` | ||
- Vue component: `<druxt-router />` | ||
- Vue mixin: `DruxtRouterEntityMixin` | ||
## Install | ||
@@ -36,3 +48,3 @@ | ||
These options are available to all Druxt modules. | ||
These options are available to all Druxt.js modules. | ||
@@ -39,0 +51,0 @@ | Option | Type | Required | Default | Description | |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No bug tracker
MaintenancePackage does not have a linked bug tracker in package.json.
Found 1 instance in 1 package
No website
QualityPackage does not have a website.
Found 1 instance in 1 package
74097
1989
55
33
Updatedcodecov@^3.7.2