druxt-router
Advanced tools
Comparing version 0.18.1 to 0.19.0
import { resolve } from 'path'; | ||
import { DruxtComponentMixin, DruxtClient } from 'druxt'; | ||
import { DruxtClient } from 'druxt'; | ||
import Url from 'url-parse'; | ||
import { mapState, mapActions } from 'vuex'; | ||
import Url from '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 your Nuxt configuration file. | ||
* | ||
* Options are set on the root level `druxt` Nuxt config object. | ||
* | ||
* @example @lang js | ||
* // `nuxt.config.js` | ||
* module.exports = { | ||
* modules: [ | ||
* 'druxt-router' | ||
* ], | ||
* druxt: { | ||
* baseUrl: 'https://demi-api.druxtjs.org' | ||
* } | ||
* } | ||
* | ||
* @todo [Add module level options]{@link https://github.com/druxt/druxt-router/issues/53} | ||
* | ||
* @property {object} options.druxt - Druxt 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 DruxtRouterNuxtModule = 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.') | ||
const DruxtRouterNuxtModule = function(moduleOptions = {}) { | ||
if (typeof this.options === "undefined" || !this.options.druxt) { | ||
throw new TypeError("Druxt settings missing."); | ||
} | ||
var options = this.options.druxt; | ||
const 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. | ||
this.extendRoutes((routes, resolve2) => { | ||
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 | ||
options.router.component = resolve2(this.options.buildDir, "components/druxt-router.js"); | ||
this.addTemplate({ | ||
src: resolve2(__dirname, "../nuxt/component.js"), | ||
fileName: "components/druxt-router.js", | ||
options | ||
}); | ||
} | ||
// Add Druxt router custom wildcard route. | ||
routes.push({ | ||
name: 'druxt-router', | ||
path: '*', | ||
name: "druxt-router", | ||
path: "*", | ||
component: options.router.component, | ||
chunkName: 'druxt-router' | ||
chunkName: "druxt-router" | ||
}); | ||
}); | ||
// Add plugin. | ||
this.addPlugin({ | ||
src: resolve(__dirname, '../nuxt/plugin.js'), | ||
fileName: 'druxt-router.js', | ||
options: options | ||
src: resolve(__dirname, "../nuxt/plugin.js"), | ||
fileName: "druxt-router.js", | ||
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 | ||
src: resolve(__dirname, "../nuxt/store.js"), | ||
fileName: "store/druxt-router.js", | ||
options | ||
}); | ||
}; | ||
// | ||
/** | ||
* The DruxtRouter Vue.js component. | ||
* | ||
* @example @lang vue | ||
* <DruxtRouter /> | ||
*/ | ||
var script = { | ||
name: 'DruxtRouter', | ||
mixins: [DruxtComponentMixin], | ||
middleware: async function middleware (ref) { | ||
var store = ref.store; | ||
var redirect = ref.redirect; | ||
var route = ref.route; | ||
var result = await store.dispatch('druxtRouter/get', route.fullPath); | ||
// Process redirect. | ||
if (result.redirect) { | ||
redirect(result.redirect); | ||
} | ||
}, | ||
/** | ||
* Vue.js Computed properties. | ||
* | ||
* @vue-computed {object} redirect The current Redirect, if applicable. | ||
* @vue-computed {object} route The current Route. | ||
*/ | ||
computed: Object.assign({}, {module: function module () { | ||
return (this.route || {}).component && this.route.component.startsWith('druxt-') ? this.route.component.substring(6) : false | ||
}, | ||
/** | ||
* Route title. | ||
* @type {boolean|string} | ||
* @default false | ||
*/ | ||
title: function title () { | ||
return this.route.label || false | ||
}, | ||
/** | ||
* Route component property data. | ||
* @type {object|string} | ||
* @default false | ||
*/ | ||
props: function props () { | ||
return this.route.props || false | ||
}}, | ||
mapState({ | ||
redirect: function (state) { return state.druxtRouter.redirect; }, | ||
route: function (state) { return state.druxtRouter.route; } | ||
})), | ||
/** | ||
* Nuxt 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 () { | ||
var head = { | ||
title: this.title, | ||
link: [ | ||
class DruxtRouter { | ||
constructor(baseUrl, options = {}) { | ||
this.options = { | ||
types: [ | ||
{ | ||
hid: 'canonical', | ||
rel: 'canonical', | ||
href: this.canonical || this.route.canonical | ||
type: "entity", | ||
canonical: (route) => route.entity.canonical, | ||
component: "druxt-entity", | ||
property: "entity", | ||
props: (route) => ({ | ||
type: route.jsonapi.resourceName, | ||
uuid: route.entity.uuid | ||
}) | ||
}, | ||
{ | ||
type: "views", | ||
canonical: (route) => route.resolved, | ||
component: "druxt-view", | ||
property: "view", | ||
props: (route) => ({ | ||
displayId: route.view.display_id, | ||
type: route.jsonapi.resourceName, | ||
uuid: route.view.uuid, | ||
viewId: route.view.view_id | ||
}) | ||
} | ||
] | ||
], | ||
...options | ||
}; | ||
if (this.metatags) { | ||
head.meta = this.metatags; | ||
this.druxt = new DruxtClient(baseUrl, this.options); | ||
this.axios = this.druxt.axios; | ||
} | ||
addHeaders(headers) { | ||
console.warn("[druxt-router] `addHeaders` is deprecated. See http://druxtjs.org/api/client."); | ||
if (typeof headers === "undefined") { | ||
return false; | ||
} | ||
return head | ||
}, | ||
druxt: function (ref) { | ||
var vm = ref.vm; | ||
return ({ | ||
componentOptions: [ | ||
// @TODO - Add Path options. | ||
[vm.module ? vm.module : 'error', vm.route.isHomePath ? 'front' : 'not-front'], | ||
['default'] | ||
], | ||
propsData: { | ||
route: vm.route | ||
} | ||
}); | ||
} | ||
}; | ||
function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) { | ||
if (typeof shadowMode !== 'boolean') { | ||
createInjectorSSR = createInjector; | ||
createInjector = shadowMode; | ||
shadowMode = false; | ||
} | ||
// Vue.extend constructor export interop. | ||
var options = typeof script === 'function' ? script.options : script; | ||
// render functions | ||
if (template && template.render) { | ||
options.render = template.render; | ||
options.staticRenderFns = template.staticRenderFns; | ||
options._compiled = true; | ||
// functional template | ||
if (isFunctionalTemplate) { | ||
options.functional = true; | ||
} | ||
} | ||
// scopedId | ||
if (scopeId) { | ||
options._scopeId = scopeId; | ||
} | ||
var hook; | ||
if (moduleIdentifier) { | ||
// server build | ||
hook = function (context) { | ||
// 2.3 injection | ||
context = | ||
context || // cached call | ||
(this.$vnode && this.$vnode.ssrContext) || // stateful | ||
(this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional | ||
// 2.2 with runInNewContext: true | ||
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { | ||
context = __VUE_SSR_CONTEXT__; | ||
} | ||
// inject component styles | ||
if (style) { | ||
style.call(this, createInjectorSSR(context)); | ||
} | ||
// register component module identifier for async chunk inference | ||
if (context && context._registeredComponents) { | ||
context._registeredComponents.add(moduleIdentifier); | ||
} | ||
}; | ||
// used by ssr in case component is cached and beforeCreate | ||
// never gets called | ||
options._ssrRegister = hook; | ||
} | ||
else if (style) { | ||
hook = shadowMode | ||
? function (context) { | ||
style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot)); | ||
} | ||
: function (context) { | ||
style.call(this, createInjector(context)); | ||
}; | ||
} | ||
if (hook) { | ||
if (options.functional) { | ||
// register for functional component in vue file | ||
var originalRender = options.render; | ||
options.render = function renderWithStyleInjection(h, context) { | ||
hook.call(context); | ||
return originalRender(h, context); | ||
}; | ||
} | ||
else { | ||
// inject component registration as beforeCreate hook | ||
var existing = options.beforeCreate; | ||
options.beforeCreate = existing ? [].concat(existing, hook) : [hook]; | ||
} | ||
} | ||
return script; | ||
} | ||
/* script */ | ||
var __vue_script__ = script; | ||
/* template */ | ||
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return (!_vm.$fetchState.pending)?_c(_vm.wrapper.component,_vm._b({tag:"component",class:_vm.wrapper.class,style:(_vm.wrapper.style)},'component',_vm.wrapper.propsData,false),[_c(_vm.component.is,_vm._b({tag:"component"},'component',_vm.component.propsData,false),[_vm._v("\n "+_vm._s(_vm.route)+"\n ")])],1):_vm._e()}; | ||
var __vue_staticRenderFns__ = []; | ||
/* style */ | ||
var __vue_inject_styles__ = undefined; | ||
/* scoped */ | ||
var __vue_scope_id__ = undefined; | ||
/* module identifier */ | ||
var __vue_module_identifier__ = undefined; | ||
/* functional template */ | ||
var __vue_is_functional_template__ = false; | ||
/* style inject */ | ||
/* style inject SSR */ | ||
/* style inject shadow dom */ | ||
var __vue_component__ = /*#__PURE__*/normalizeComponent( | ||
{ render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ }, | ||
__vue_inject_styles__, | ||
__vue_script__, | ||
__vue_scope_id__, | ||
__vue_is_functional_template__, | ||
__vue_module_identifier__, | ||
false, | ||
undefined, | ||
undefined, | ||
undefined | ||
); | ||
/** | ||
* @vuepress | ||
* --- | ||
* title: DruxtRouter | ||
* --- | ||
*/ | ||
/** | ||
* DruxtRouter class. | ||
* | ||
* Provides core Drupal JSON:API query functionality. | ||
*/ | ||
var DruxtRouter = function DruxtRouter (baseUrl, options) { | ||
if ( options === void 0 ) options = {}; | ||
/** | ||
* Druxt router options. | ||
* @type {object} | ||
* @private | ||
*/ | ||
this.options = Object.assign({}, {types: [ | ||
{ | ||
type: 'entity', | ||
canonical: function (route) { return route.entity.canonical; }, | ||
component: 'druxt-entity', | ||
property: 'entity', | ||
props: function (route) { return ({ | ||
type: route.jsonapi.resourceName, | ||
uuid: route.entity.uuid | ||
}); } | ||
}, | ||
{ | ||
type: 'views', | ||
canonical: function (route) { return route.resolved; }, | ||
component: 'druxt-view', | ||
property: 'view', | ||
props: function (route) { return ({ | ||
displayId: route.view.display_id, | ||
type: route.jsonapi.resourceName, | ||
uuid: route.view.uuid, | ||
viewId: route.view.view_id | ||
}); } | ||
} | ||
]}, | ||
options); | ||
/** | ||
* Instance of the Druxt Client. | ||
* | ||
* @type {DruxtClient} | ||
* @see {@link http://druxtjs.org/api/client} | ||
*/ | ||
this.druxt = new DruxtClient(baseUrl, this.options); | ||
this.axios = this.druxt.axios; | ||
}; | ||
/** | ||
* Add headers to the Axios instance. | ||
* | ||
* @deprecated | ||
* @see {@link https://druxtjs.org/api/client} | ||
* | ||
* @example @lang js | ||
* router.druxt.addHeaders({ 'Authorization': `Basic ${token}` }) | ||
* | ||
* @param {object} headers - An object containing HTTP headers. | ||
*/ | ||
DruxtRouter.prototype.addHeaders = function addHeaders (headers) { | ||
console.warn('[druxt-router] `addHeaders` is deprecated. See http://druxtjs.org/api/client.'); | ||
if (typeof headers === 'undefined') { | ||
return false | ||
this.druxt.addHeaders(headers); | ||
} | ||
this.druxt.addHeaders(headers); | ||
}; | ||
/** | ||
* Build query URL. | ||
* | ||
* @deprecated | ||
* @see {@link https://druxtjs.org/api/client} | ||
* | ||
* @example @lang js | ||
* const query = new DrupalJsonApiParams() | ||
* query.addFilter('status', '1') | ||
* const queryUrl = router.druxt.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. | ||
*/ | ||
DruxtRouter.prototype.buildQueryUrl = function buildQueryUrl (url, query) { | ||
console.warn('[druxt-router] `buildQueryUrl` is deprecated. See http://druxtjs.org/api/client.'); | ||
return this.druxt.buildQueryUrl(url, query) | ||
}; | ||
/** | ||
* Check response for permissions. | ||
* | ||
* @deprecated | ||
* @see {@link https://druxtjs.org/api/client} | ||
* | ||
* @param {object} res - Axios GET request response object. | ||
* | ||
* @private | ||
*/ | ||
DruxtRouter.prototype.checkPermissions = function checkPermissions (res) { | ||
console.warn('[druxt-router] `checkPermissions` is deprecated. See http://druxtjs.org/api/client.'); | ||
return this.druxt.checkPermissions(res) | ||
}; | ||
/** | ||
* Returns route and redirect data for a given 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. | ||
*/ | ||
DruxtRouter.prototype.get = async function get (path) { | ||
var route = await this.getRoute(path); | ||
if (route.error) { | ||
return { route: route } | ||
buildQueryUrl(url, query) { | ||
console.warn("[druxt-router] `buildQueryUrl` is deprecated. See http://druxtjs.org/api/client."); | ||
return this.druxt.buildQueryUrl(url, query); | ||
} | ||
var redirect = this.getRedirect(path, route); | ||
return { redirect: redirect, route: route } | ||
}; | ||
/** | ||
* Get index of all available resources, or the optionally specified resource. | ||
* | ||
* @deprecated | ||
* @see {@link https://druxtjs.org/api/client} | ||
* | ||
* @example @lang js | ||
* const { href } = await router.druxt.getIndex('node--article') | ||
* | ||
* @param {string} resource - (Optional) A specific resource to query. | ||
* | ||
* @returns {object} The resource index object or the specified resource. | ||
*/ | ||
DruxtRouter.prototype.getIndex = async function getIndex (resource) { | ||
console.warn('[druxt-router] `getIndex` is deprecated. See http://druxtjs.org/api/client.'); | ||
this.index = await this.druxt.getIndex(resource); | ||
return this.index | ||
}; | ||
/** | ||
* 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. | ||
*/ | ||
DruxtRouter.prototype.getRedirect = function getRedirect (path, route) { | ||
if ( route === void 0 ) route = {}; | ||
// Redirect to route provided redirect. | ||
if (((route.redirect || [])[0] || {}).to) { | ||
return route.redirect[0].to | ||
checkPermissions(res) { | ||
console.warn("[druxt-router] `checkPermissions` is deprecated. See http://druxtjs.org/api/client."); | ||
return this.druxt.checkPermissions(res); | ||
} | ||
var url = Url(path); | ||
// Redirect to root if route is home path but path isn't root. | ||
if (route.isHomePath) { | ||
if (url.pathname !== '/') { | ||
return '/' | ||
async get(path) { | ||
const route = await this.getRoute(path); | ||
if (route.error) { | ||
return { route }; | ||
} | ||
return false | ||
const redirect = this.getRedirect(path, route); | ||
return { redirect, route }; | ||
} | ||
// Redirect if path does not match resolved clean url path. | ||
if (typeof route.canonical === 'string') { | ||
var canonicalUrl = new Url(route.canonical); | ||
if (url.pathname !== canonicalUrl.pathname) { | ||
return canonicalUrl.pathname | ||
} | ||
async getIndex(resource) { | ||
console.warn("[druxt-router] `getIndex` is deprecated. See http://druxtjs.org/api/client."); | ||
this.index = await this.druxt.getIndex(resource); | ||
return this.index; | ||
} | ||
return false | ||
}; | ||
/** | ||
* Get a JSON:API resource by type and ID. | ||
* | ||
* @deprecated | ||
* @see {@link https://druxtjs.org/api/client} | ||
* | ||
* @example @lang js | ||
* const data = await router.druxt.getResource('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. | ||
*/ | ||
DruxtRouter.prototype.getResource = async function getResource (query) { | ||
if ( query === void 0 ) query = {}; | ||
console.warn('[druxt-router] `getResource` is deprecated. See http://druxtjs.org/api/client.'); | ||
var resource = await this.druxt.getResource(query.type, query.id); | ||
return resource.data || false | ||
}; | ||
/** | ||
* Gets a collection of resources. | ||
* | ||
* @deprecated | ||
* @see {@link https://druxtjs.org/api/client} | ||
* | ||
* @todo Add granular pagination. | ||
* | ||
* @example @lang js | ||
* // Load all currently published Articles. | ||
* const query = new DrupalJsonApiParams() | ||
* query.addFilter('status', '1') | ||
* const resources = await router.druxt.getCollection('node--article', query) | ||
* | ||
* @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. | ||
*/ | ||
DruxtRouter.prototype.getResources = async function getResources (resource, query, options) { | ||
if ( options === void 0 ) options = {}; | ||
console.warn('[druxt-router] `getResources` is deprecated. See http://druxtjs.org/api/client.'); | ||
var resources = { data: [] }; | ||
if (options.all) { | ||
var collections = await this.druxt.getCollectionAll(resource, query); | ||
collections.map(function (collection) { (collection.data || []).map(function (resource) { resources.data.push(resource); }); }); | ||
} else { | ||
resources = await this.druxt.getCollection(resource, query); | ||
} | ||
return resources.data || false | ||
}; | ||
/** | ||
* Get a JSON:API resource by Drupal 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. | ||
*/ | ||
DruxtRouter.prototype.getResourceByRoute = async function getResourceByRoute (route) { | ||
var resource = await this.druxt.getResource(route.jsonapi.resourceName, route.entity.uuid); | ||
return resource.data || false | ||
}; | ||
/** | ||
* Get routing data from Decoupled Router. | ||
* | ||
* @example @lang js | ||
* const route = await router.getRoute('/') | ||
* | ||
* @param {string} path - The route path. | ||
* | ||
* @returns {object} The route object. | ||
*/ | ||
DruxtRouter.prototype.getRoute = async function getRoute (path) { | ||
// @TODO - Add validation/error handling. | ||
var url = "/router/translate-path?path=" + path; | ||
var response = await this.druxt.axios.get(url, { | ||
// Prevent invalid routes (404) from throwing validation errors. | ||
validateStatus: function (status) { return status < 500; } | ||
}); | ||
var data = Object.assign({}, {isHomePath: false, | ||
jsonapi: {}, | ||
label: false, | ||
redirect: false}, | ||
response.data); | ||
var route = { | ||
error: false, | ||
type: false, | ||
canonical: false, | ||
component: false, | ||
isHomePath: data.isHomePath, | ||
jsonapi: data.jsonapi, | ||
label: data.label, | ||
props: false, | ||
redirect: data.redirect, | ||
resolvedPath: Url(data.resolved).pathname | ||
}; | ||
// Determine route type by configuration. | ||
// @TODO - Move type to Decoupled router. | ||
// @SEE- https://www.drupal.org/project/decoupled_router/issues/3146024 | ||
for (var key in this.options.types) { | ||
var type = Object.assign({}, this.options.types[key]); | ||
if (typeof type.property !== 'string' || typeof data[type.property] === 'undefined') { | ||
continue | ||
getRedirect(path, route = {}) { | ||
if (((route.redirect || [])[0] || {}).to) { | ||
return route.redirect[0].to; | ||
} | ||
delete type.property; | ||
// Construct canonical link. | ||
if (typeof type.canonical === 'function') { | ||
type.canonical = type.canonical(data); | ||
const url = Url(path); | ||
if (route.isHomePath) { | ||
if (url.pathname !== "/") { | ||
return "/"; | ||
} | ||
return false; | ||
} | ||
// Construct props. | ||
if (typeof type.props === 'function') { | ||
type.props = type.props(data); | ||
if (typeof route.canonical === "string") { | ||
const canonicalUrl = new Url(route.canonical); | ||
if (url.pathname !== canonicalUrl.pathname) { | ||
return canonicalUrl.pathname; | ||
} | ||
} | ||
// Merge type | ||
route = Object.assign({}, route, | ||
type); | ||
break | ||
return false; | ||
} | ||
// Process Axios error. | ||
if (!(response.status >= 200 && response.status < 300)) { | ||
route.error = { | ||
statusCode: response.status, | ||
message: response.statusText | ||
}; | ||
route.component = 'error'; | ||
async getResource(query = {}) { | ||
console.warn("[druxt-router] `getResource` is deprecated. See http://druxtjs.org/api/client."); | ||
const resource = await this.druxt.getResource(query.type, query.id); | ||
return resource.data || false; | ||
} | ||
return route | ||
}; | ||
/** | ||
* The DruxtRouterEntityMixin Vue.js mixin provides easy integration with the DruxtJS Router Vuex store, including on-demand loading of JSON:API resources. | ||
* | ||
* @mixin | ||
* | ||
* @example @lang vue | ||
* <template> | ||
* <div v-if="!$fetchState.pending"> | ||
* {{ entity }} | ||
* </div> | ||
* </template> | ||
* | ||
* <script> | ||
* import { DruxtRouterEntityMixin } from 'druxt-router' | ||
* | ||
* export default { | ||
* mixins: [DruxtRouterEntityMixin] | ||
* } | ||
* </script> | ||
*/ | ||
var DruxtRouterEntityMixin = { | ||
/** | ||
* Vue.js Properties. | ||
*/ | ||
props: { | ||
/** | ||
* The Drupal display mode. | ||
* | ||
* @type {string} | ||
* @default default | ||
*/ | ||
mode: { | ||
type: String, | ||
default: 'default' | ||
}, | ||
/** | ||
* The JSON:API resource type. | ||
* | ||
* @type {string} | ||
*/ | ||
type: { | ||
type: String, | ||
required: true | ||
}, | ||
/** | ||
* The Drupal entity UUID. | ||
* | ||
* @type {string} | ||
*/ | ||
uuid: { | ||
type: String, | ||
required: true | ||
async getResources(resource, query, options = {}) { | ||
console.warn("[druxt-router] `getResources` is deprecated. See http://druxtjs.org/api/client."); | ||
let resources = { data: [] }; | ||
if (options.all) { | ||
const collections = await this.druxt.getCollectionAll(resource, query); | ||
collections.map((collection) => { | ||
(collection.data || []).map((resource2) => { | ||
resources.data.push(resource2); | ||
}); | ||
}); | ||
} else { | ||
resources = await this.druxt.getCollection(resource, query); | ||
} | ||
}, | ||
/** | ||
* 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') { | ||
this.entity = this.entities[this.uuid]; | ||
return | ||
return resources.data || false; | ||
} | ||
async getResourceByRoute(route) { | ||
const resource = await this.druxt.getResource(route.jsonapi.resourceName, route.entity.uuid); | ||
return resource.data || false; | ||
} | ||
async getRoute(path) { | ||
const url = `/router/translate-path?path=${path}`; | ||
const response = await this.druxt.axios.get(url, { | ||
validateStatus: (status) => status < 500 | ||
}); | ||
const data = { | ||
isHomePath: false, | ||
jsonapi: {}, | ||
label: false, | ||
redirect: false, | ||
...response.data | ||
}; | ||
let route = { | ||
error: false, | ||
type: false, | ||
canonical: false, | ||
component: false, | ||
isHomePath: data.isHomePath, | ||
jsonapi: data.jsonapi, | ||
label: data.label, | ||
props: false, | ||
redirect: data.redirect, | ||
resolvedPath: Url(data.resolved).pathname | ||
}; | ||
for (const key in this.options.types) { | ||
const type = { | ||
...this.options.types[key] | ||
}; | ||
if (typeof type.property !== "string" || typeof data[type.property] === "undefined") { | ||
continue; | ||
} | ||
delete type.property; | ||
if (typeof type.canonical === "function") { | ||
type.canonical = type.canonical(data); | ||
} | ||
if (typeof type.props === "function") { | ||
type.props = type.props(data); | ||
} | ||
route = { | ||
...route, | ||
...type | ||
}; | ||
break; | ||
} | ||
// Otherwise invoke getResource() to retrieve it from Drupal. | ||
if (!this.entity && this.uuid && this.type) { | ||
var resource = await this.getResource({ id: this.uuid, type: this.type }); | ||
this.entity = resource.data; | ||
this.loading = false; | ||
if (!(response.status >= 200 && response.status < 300)) { | ||
route.error = { | ||
statusCode: response.status, | ||
message: response.statusText | ||
}; | ||
route.component = "error"; | ||
} | ||
}, | ||
/** | ||
* 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 Router Vuex `entities` state. | ||
* @see {@link store|src/store.js} | ||
*/ | ||
computed: Object.assign({}, mapState({ | ||
entities: function (state) { return state.druxt.resources; } | ||
})), | ||
/** | ||
* Vue.js Methods. | ||
* | ||
* - Maps Vuex `druxtRouter/getEntity` action to `this->getEntity()`. | ||
* - Maps Vuex `druxt/getResource` action to `this->getResource()`. | ||
* | ||
* @see {@link store|src/store.js} | ||
*/ | ||
methods: Object.assign({}, mapActions({ | ||
getEntity: 'druxtRouter/getEntity', | ||
getResource: 'druxt/getResource' | ||
})) | ||
}; | ||
/** | ||
* The DruxtRouterMixin Vue.js mixin provides the props required for a Router Druxt wrapper component. | ||
* | ||
* @mixin | ||
* | ||
* @example @lang vue | ||
* <template> | ||
* <div> | ||
* <slot /> | ||
* </div> | ||
* </template> | ||
* | ||
* <script> | ||
* import { DruxtRouterMixin } from 'druxt-router' | ||
* | ||
* export default { | ||
* mixins: [DruxtRouterMixin] | ||
* } | ||
* </script> | ||
*/ | ||
var DruxtRouterMixin = { | ||
/** | ||
* Vue.js Properties. | ||
*/ | ||
props: { | ||
/** | ||
* The Decoupled router object. | ||
* | ||
* @type {object} | ||
*/ | ||
route: { | ||
type: Object, | ||
required: true | ||
} | ||
return route; | ||
} | ||
}; | ||
} | ||
var DruxtRouterStore = function (ref) { | ||
var store = ref.store; | ||
if (typeof store === 'undefined') { | ||
throw new TypeError('Vuex store not found.') | ||
const DruxtRouterStore = ({ store }) => { | ||
if (typeof store === "undefined") { | ||
throw new TypeError("Vuex store not found."); | ||
} | ||
/** | ||
* @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 Change namespace to `druxt/router`. | ||
*/ | ||
var module = { | ||
const namespace = "druxtRouter"; | ||
const 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 ({ | ||
state: () => ({ | ||
entities: {}, | ||
@@ -846,225 +210,62 @@ redirect: false, | ||
routes: {} | ||
}); }, | ||
/** | ||
* Vuex Mutations. | ||
*/ | ||
}), | ||
mutations: { | ||
/** | ||
* @deprecated | ||
* @see {@link https://druxtjs.org/api/stores/druxt} | ||
* | ||
* @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) { | ||
console.warn('[druxt-router] `druxtRouter/addEntity` is deprecated. See http://druxtjs.org/api/stores/druxt.'); | ||
if (!entity || typeof entity.id === 'undefined') { | ||
// @TODO - Error? | ||
return | ||
addEntity(state, entity) { | ||
console.warn("[druxt-router] `druxtRouter/addEntity` is deprecated. See http://druxtjs.org/api/stores/druxt."); | ||
if (!entity || typeof entity.id === "undefined") { | ||
return; | ||
} | ||
state.entities[entity.id] = entity; | ||
}, | ||
/** | ||
* @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) { | ||
setRedirect(state, redirect) { | ||
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) { | ||
var path = ref.path; | ||
var route = ref.route; | ||
if (typeof path !== 'string' || typeof route === 'undefined') { | ||
// @TODO - Error? | ||
return | ||
addRoute(state, { path, route }) { | ||
if (typeof path !== "string" || typeof route === "undefined") { | ||
return; | ||
} | ||
state.routes[path] = route; | ||
}, | ||
/** | ||
* @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) { | ||
if (typeof path !== 'string' || typeof state.routes[path] === 'undefined') { | ||
// @TODO - Error? | ||
return | ||
setRoute(state, path) { | ||
if (typeof path !== "string" || typeof state.routes[path] === "undefined") { | ||
return; | ||
} | ||
state.route = state.routes[path]; | ||
} | ||
}, | ||
/** | ||
* 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) { | ||
var commit = ref.commit; | ||
var dispatch = ref.dispatch; | ||
var state = ref.state; | ||
// Get route by path from 'getRoute'. | ||
var route = await dispatch('getRoute', path); | ||
// Handle route errors. | ||
if (route.error && typeof route.error.statusCode !== 'undefined' && ((this.app || {}).context || {}).error) { | ||
return this.app.context.error(route.error) | ||
async get({ commit, dispatch, state }, path) { | ||
const route = await dispatch("getRoute", path); | ||
if (route.error && typeof route.error.statusCode !== "undefined" && ((this.app || {}).context || {}).error) { | ||
return this.app.context.error(route.error); | ||
} | ||
// Set active route. | ||
commit('setRoute', path); | ||
// Set active redirect. | ||
var redirect = this.$druxtRouter().getRedirect(path, route); | ||
commit('setRedirect', redirect); | ||
return { redirect: redirect, route: route } | ||
commit("setRoute", path); | ||
const redirect = this.$druxtRouter().getRedirect(path, route); | ||
commit("setRedirect", redirect); | ||
return { redirect, route }; | ||
}, | ||
/** | ||
* Get Entity. | ||
* | ||
* - Executes query against Drupal JSON:API. | ||
* - Caches result in the Vuex store. | ||
* - Returns cached result from Vuex store when available. | ||
* | ||
* @deprecated | ||
* @see {@link https://druxtjs.org/api/stores/druxt} | ||
* | ||
* @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) { | ||
var commit = ref.commit; | ||
var state = ref.state; | ||
console.warn('[druxt-router] `druxtRouter/getEntity` is deprecated. See http://druxtjs.org/api/stores/druxt.'); | ||
if (typeof state.entities[query.id] !== 'undefined') { | ||
return state.entities[query.id] | ||
async getEntity({ commit, state }, query) { | ||
console.warn("[druxt-router] `druxtRouter/getEntity` is deprecated. See http://druxtjs.org/api/stores/druxt."); | ||
if (typeof state.entities[query.id] !== "undefined") { | ||
return state.entities[query.id]; | ||
} | ||
var entity = await this.app.store.dispatch('druxt/getResource', query); | ||
commit('addEntity', entity.data); | ||
return entity.data | ||
const entity = await this.app.store.dispatch("druxt/getResource", query); | ||
commit("addEntity", entity.data); | ||
return entity.data; | ||
}, | ||
/** | ||
* Get multiple resources. | ||
* | ||
* @deprecated | ||
* @see {@link https://druxtjs.org/api/stores/druxt} | ||
* | ||
* @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 } | ||
* }) | ||
*/ | ||
getResources: async function getResources (app, ref) { | ||
var resource = ref.resource; | ||
var query = ref.query; | ||
var options = ref.options; | ||
console.warn('[druxt-router] `druxtRouter/getResources` is deprecated. See http://druxtjs.org/api/stores/druxt.'); | ||
var collection = await this.app.store.dispatch('druxt/getCollection', { type: resource, query: query }); | ||
return collection.data || false | ||
async getResources(app, { resource, query, options }) { | ||
console.warn("[druxt-router] `druxtRouter/getResources` is deprecated. See http://druxtjs.org/api/stores/druxt."); | ||
const collection = await this.app.store.dispatch("druxt/getCollection", { type: resource, query }); | ||
return collection.data || false; | ||
}, | ||
/** | ||
* 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) { | ||
var commit = ref.commit; | ||
var state = ref.state; | ||
if (typeof state.routes[path] !== 'undefined') { | ||
return state.routes[path] | ||
async getRoute({ commit, state }, path) { | ||
if (typeof state.routes[path] !== "undefined") { | ||
return state.routes[path]; | ||
} | ||
var route = await this.$druxtRouter().getRoute(path); | ||
commit('addRoute', { path: path, route: route }); | ||
return route | ||
const route = await this.$druxtRouter().getRoute(path); | ||
commit("addRoute", { path, route }); | ||
return route; | ||
} | ||
} | ||
}; | ||
store.registerModule(namespace, module, { | ||
@@ -1075,3 +276,54 @@ preserveState: Boolean(store.state[namespace]) | ||
export default DruxtRouterNuxtModule; | ||
export { DruxtRouter, __vue_component__ as DruxtRouterComponent, DruxtRouterEntityMixin, DruxtRouterMixin, DruxtRouterStore }; | ||
const DruxtRouterEntityMixin = { | ||
props: { | ||
mode: { | ||
type: String, | ||
default: "default" | ||
}, | ||
type: { | ||
type: String, | ||
required: true | ||
}, | ||
uuid: { | ||
type: String, | ||
required: true | ||
} | ||
}, | ||
async fetch() { | ||
if (typeof this.entities[this.uuid] !== "undefined") { | ||
this.entity = this.entities[this.uuid]; | ||
return; | ||
} | ||
if (!this.entity && this.uuid && this.type) { | ||
const resource = await this.getResource({ id: this.uuid, type: this.type }); | ||
this.entity = resource.data; | ||
this.loading = false; | ||
} | ||
}, | ||
data: () => ({ | ||
entity: false, | ||
loading: true | ||
}), | ||
computed: { | ||
...mapState({ | ||
entities: (state) => state.druxt.resources | ||
}) | ||
}, | ||
methods: { | ||
...mapActions({ | ||
getEntity: "druxtRouter/getEntity", | ||
getResource: "druxt/getResource" | ||
}) | ||
} | ||
}; | ||
const DruxtRouterMixin = { | ||
props: { | ||
route: { | ||
type: Object, | ||
required: true | ||
} | ||
} | ||
}; | ||
export { DruxtRouter, DruxtRouterEntityMixin, DruxtRouterMixin, DruxtRouterStore, DruxtRouterNuxtModule as default }; |
@@ -1,823 +0,214 @@ | ||
'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'),druxt=require('druxt'),vuex=require('vuex'),Url=_interopDefault(require('url-parse'));/** | ||
* @vuepress | ||
* --- | ||
* title: DruxtRouterModule | ||
* --- | ||
*/ | ||
'use strict'; | ||
/** | ||
* 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 your Nuxt configuration file. | ||
* | ||
* Options are set on the root level `druxt` Nuxt config object. | ||
* | ||
* @example @lang js | ||
* // `nuxt.config.js` | ||
* module.exports = { | ||
* modules: [ | ||
* 'druxt-router' | ||
* ], | ||
* druxt: { | ||
* baseUrl: 'https://demi-api.druxtjs.org' | ||
* } | ||
* } | ||
* | ||
* @todo [Add module level options]{@link https://github.com/druxt/druxt-router/issues/53} | ||
* | ||
* @property {object} options.druxt - Druxt 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 DruxtRouterNuxtModule = function (moduleOptions) { | ||
var this$1 = this; | ||
Object.defineProperty(exports, '__esModule', { value: true }); | ||
// Use root level Druxt options. | ||
if (typeof this.options === 'undefined' || !this.options.druxt) { | ||
throw new TypeError('Druxt settings missing.') | ||
const path = require('path'); | ||
const druxt = require('druxt'); | ||
const Url = require('url-parse'); | ||
const vuex = require('vuex'); | ||
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; } | ||
const Url__default = /*#__PURE__*/_interopDefaultLegacy(Url); | ||
const DruxtRouterNuxtModule = function(moduleOptions = {}) { | ||
if (typeof this.options === "undefined" || !this.options.druxt) { | ||
throw new TypeError("Druxt settings missing."); | ||
} | ||
var options = this.options.druxt; | ||
const 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. | ||
this.extendRoutes((routes, resolve2) => { | ||
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 | ||
options.router.component = resolve2(this.options.buildDir, "components/druxt-router.js"); | ||
this.addTemplate({ | ||
src: resolve2(__dirname, "../nuxt/component.js"), | ||
fileName: "components/druxt-router.js", | ||
options | ||
}); | ||
} | ||
// Add Druxt router custom wildcard route. | ||
routes.push({ | ||
name: 'druxt-router', | ||
path: '*', | ||
name: "druxt-router", | ||
path: "*", | ||
component: options.router.component, | ||
chunkName: 'druxt-router' | ||
chunkName: "druxt-router" | ||
}); | ||
}); | ||
// Add plugin. | ||
this.addPlugin({ | ||
src: path.resolve(__dirname, '../nuxt/plugin.js'), | ||
fileName: 'druxt-router.js', | ||
options: options | ||
src: path.resolve(__dirname, "../nuxt/plugin.js"), | ||
fileName: "druxt-router.js", | ||
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 | ||
src: path.resolve(__dirname, "../nuxt/store.js"), | ||
fileName: "store/druxt-router.js", | ||
options | ||
}); | ||
};// | ||
}; | ||
/** | ||
* The DruxtRouter Vue.js component. | ||
* | ||
* @example @lang vue | ||
* <DruxtRouter /> | ||
*/ | ||
var script = { | ||
name: 'DruxtRouter', | ||
mixins: [druxt.DruxtComponentMixin], | ||
middleware: async function middleware (ref) { | ||
var store = ref.store; | ||
var redirect = ref.redirect; | ||
var route = ref.route; | ||
var result = await store.dispatch('druxtRouter/get', route.fullPath); | ||
// Process redirect. | ||
if (result.redirect) { | ||
redirect(result.redirect); | ||
} | ||
}, | ||
/** | ||
* Vue.js Computed properties. | ||
* | ||
* @vue-computed {object} redirect The current Redirect, if applicable. | ||
* @vue-computed {object} route The current Route. | ||
*/ | ||
computed: Object.assign({}, {module: function module () { | ||
return (this.route || {}).component && this.route.component.startsWith('druxt-') ? this.route.component.substring(6) : false | ||
}, | ||
/** | ||
* Route title. | ||
* @type {boolean|string} | ||
* @default false | ||
*/ | ||
title: function title () { | ||
return this.route.label || false | ||
}, | ||
/** | ||
* Route component property data. | ||
* @type {object|string} | ||
* @default false | ||
*/ | ||
props: function props () { | ||
return this.route.props || false | ||
}}, | ||
vuex.mapState({ | ||
redirect: function (state) { return state.druxtRouter.redirect; }, | ||
route: function (state) { return state.druxtRouter.route; } | ||
})), | ||
/** | ||
* Nuxt 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 () { | ||
var head = { | ||
title: this.title, | ||
link: [ | ||
class DruxtRouter { | ||
constructor(baseUrl, options = {}) { | ||
this.options = { | ||
types: [ | ||
{ | ||
hid: 'canonical', | ||
rel: 'canonical', | ||
href: this.canonical || this.route.canonical | ||
type: "entity", | ||
canonical: (route) => route.entity.canonical, | ||
component: "druxt-entity", | ||
property: "entity", | ||
props: (route) => ({ | ||
type: route.jsonapi.resourceName, | ||
uuid: route.entity.uuid | ||
}) | ||
}, | ||
{ | ||
type: "views", | ||
canonical: (route) => route.resolved, | ||
component: "druxt-view", | ||
property: "view", | ||
props: (route) => ({ | ||
displayId: route.view.display_id, | ||
type: route.jsonapi.resourceName, | ||
uuid: route.view.uuid, | ||
viewId: route.view.view_id | ||
}) | ||
} | ||
] | ||
], | ||
...options | ||
}; | ||
if (this.metatags) { | ||
head.meta = this.metatags; | ||
this.druxt = new druxt.DruxtClient(baseUrl, this.options); | ||
this.axios = this.druxt.axios; | ||
} | ||
addHeaders(headers) { | ||
console.warn("[druxt-router] `addHeaders` is deprecated. See http://druxtjs.org/api/client."); | ||
if (typeof headers === "undefined") { | ||
return false; | ||
} | ||
return head | ||
}, | ||
druxt: function (ref) { | ||
var vm = ref.vm; | ||
return ({ | ||
componentOptions: [ | ||
// @TODO - Add Path options. | ||
[vm.module ? vm.module : 'error', vm.route.isHomePath ? 'front' : 'not-front'], | ||
['default'] | ||
], | ||
propsData: { | ||
route: vm.route | ||
} | ||
}); | ||
} | ||
};function normalizeComponent(template, style, script, scopeId, isFunctionalTemplate, moduleIdentifier /* server only */, shadowMode, createInjector, createInjectorSSR, createInjectorShadow) { | ||
if (typeof shadowMode !== 'boolean') { | ||
createInjectorSSR = createInjector; | ||
createInjector = shadowMode; | ||
shadowMode = false; | ||
} | ||
// Vue.extend constructor export interop. | ||
var options = typeof script === 'function' ? script.options : script; | ||
// render functions | ||
if (template && template.render) { | ||
options.render = template.render; | ||
options.staticRenderFns = template.staticRenderFns; | ||
options._compiled = true; | ||
// functional template | ||
if (isFunctionalTemplate) { | ||
options.functional = true; | ||
} | ||
} | ||
// scopedId | ||
if (scopeId) { | ||
options._scopeId = scopeId; | ||
} | ||
var hook; | ||
if (moduleIdentifier) { | ||
// server build | ||
hook = function (context) { | ||
// 2.3 injection | ||
context = | ||
context || // cached call | ||
(this.$vnode && this.$vnode.ssrContext) || // stateful | ||
(this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext); // functional | ||
// 2.2 with runInNewContext: true | ||
if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { | ||
context = __VUE_SSR_CONTEXT__; | ||
} | ||
// inject component styles | ||
if (style) { | ||
style.call(this, createInjectorSSR(context)); | ||
} | ||
// register component module identifier for async chunk inference | ||
if (context && context._registeredComponents) { | ||
context._registeredComponents.add(moduleIdentifier); | ||
} | ||
}; | ||
// used by ssr in case component is cached and beforeCreate | ||
// never gets called | ||
options._ssrRegister = hook; | ||
} | ||
else if (style) { | ||
hook = shadowMode | ||
? function (context) { | ||
style.call(this, createInjectorShadow(context, this.$root.$options.shadowRoot)); | ||
} | ||
: function (context) { | ||
style.call(this, createInjector(context)); | ||
}; | ||
} | ||
if (hook) { | ||
if (options.functional) { | ||
// register for functional component in vue file | ||
var originalRender = options.render; | ||
options.render = function renderWithStyleInjection(h, context) { | ||
hook.call(context); | ||
return originalRender(h, context); | ||
}; | ||
} | ||
else { | ||
// inject component registration as beforeCreate hook | ||
var existing = options.beforeCreate; | ||
options.beforeCreate = existing ? [].concat(existing, hook) : [hook]; | ||
} | ||
} | ||
return script; | ||
}/* script */ | ||
var __vue_script__ = script; | ||
/* template */ | ||
var __vue_render__ = function () {var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;return (!_vm.$fetchState.pending)?_c(_vm.wrapper.component,_vm._b({tag:"component",class:_vm.wrapper.class,style:(_vm.wrapper.style)},'component',_vm.wrapper.propsData,false),[_c(_vm.component.is,_vm._b({tag:"component"},'component',_vm.component.propsData,false),[_vm._v("\n "+_vm._s(_vm.route)+"\n ")])],1):_vm._e()}; | ||
var __vue_staticRenderFns__ = []; | ||
/* style */ | ||
var __vue_inject_styles__ = undefined; | ||
/* scoped */ | ||
var __vue_scope_id__ = undefined; | ||
/* module identifier */ | ||
var __vue_module_identifier__ = "data-v-130f3e88"; | ||
/* functional template */ | ||
var __vue_is_functional_template__ = false; | ||
/* style inject */ | ||
/* style inject SSR */ | ||
/* style inject shadow dom */ | ||
var __vue_component__ = /*#__PURE__*/normalizeComponent( | ||
{ render: __vue_render__, staticRenderFns: __vue_staticRenderFns__ }, | ||
__vue_inject_styles__, | ||
__vue_script__, | ||
__vue_scope_id__, | ||
__vue_is_functional_template__, | ||
__vue_module_identifier__, | ||
false, | ||
undefined, | ||
undefined, | ||
undefined | ||
);/** | ||
* @vuepress | ||
* --- | ||
* title: DruxtRouter | ||
* --- | ||
*/ | ||
/** | ||
* DruxtRouter class. | ||
* | ||
* Provides core Drupal JSON:API query functionality. | ||
*/ | ||
var DruxtRouter = function DruxtRouter (baseUrl, options) { | ||
if ( options === void 0 ) options = {}; | ||
/** | ||
* Druxt router options. | ||
* @type {object} | ||
* @private | ||
*/ | ||
this.options = Object.assign({}, {types: [ | ||
{ | ||
type: 'entity', | ||
canonical: function (route) { return route.entity.canonical; }, | ||
component: 'druxt-entity', | ||
property: 'entity', | ||
props: function (route) { return ({ | ||
type: route.jsonapi.resourceName, | ||
uuid: route.entity.uuid | ||
}); } | ||
}, | ||
{ | ||
type: 'views', | ||
canonical: function (route) { return route.resolved; }, | ||
component: 'druxt-view', | ||
property: 'view', | ||
props: function (route) { return ({ | ||
displayId: route.view.display_id, | ||
type: route.jsonapi.resourceName, | ||
uuid: route.view.uuid, | ||
viewId: route.view.view_id | ||
}); } | ||
} | ||
]}, | ||
options); | ||
/** | ||
* Instance of the Druxt Client. | ||
* | ||
* @type {DruxtClient} | ||
* @see {@link http://druxtjs.org/api/client} | ||
*/ | ||
this.druxt = new druxt.DruxtClient(baseUrl, this.options); | ||
this.axios = this.druxt.axios; | ||
}; | ||
/** | ||
* Add headers to the Axios instance. | ||
* | ||
* @deprecated | ||
* @see {@link https://druxtjs.org/api/client} | ||
* | ||
* @example @lang js | ||
* router.druxt.addHeaders({ 'Authorization': `Basic ${token}` }) | ||
* | ||
* @param {object} headers - An object containing HTTP headers. | ||
*/ | ||
DruxtRouter.prototype.addHeaders = function addHeaders (headers) { | ||
console.warn('[druxt-router] `addHeaders` is deprecated. See http://druxtjs.org/api/client.'); | ||
if (typeof headers === 'undefined') { | ||
return false | ||
this.druxt.addHeaders(headers); | ||
} | ||
this.druxt.addHeaders(headers); | ||
}; | ||
/** | ||
* Build query URL. | ||
* | ||
* @deprecated | ||
* @see {@link https://druxtjs.org/api/client} | ||
* | ||
* @example @lang js | ||
* const query = new DrupalJsonApiParams() | ||
* query.addFilter('status', '1') | ||
* const queryUrl = router.druxt.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. | ||
*/ | ||
DruxtRouter.prototype.buildQueryUrl = function buildQueryUrl (url, query) { | ||
console.warn('[druxt-router] `buildQueryUrl` is deprecated. See http://druxtjs.org/api/client.'); | ||
return this.druxt.buildQueryUrl(url, query) | ||
}; | ||
/** | ||
* Check response for permissions. | ||
* | ||
* @deprecated | ||
* @see {@link https://druxtjs.org/api/client} | ||
* | ||
* @param {object} res - Axios GET request response object. | ||
* | ||
* @private | ||
*/ | ||
DruxtRouter.prototype.checkPermissions = function checkPermissions (res) { | ||
console.warn('[druxt-router] `checkPermissions` is deprecated. See http://druxtjs.org/api/client.'); | ||
return this.druxt.checkPermissions(res) | ||
}; | ||
/** | ||
* Returns route and redirect data for a given 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. | ||
*/ | ||
DruxtRouter.prototype.get = async function get (path) { | ||
var route = await this.getRoute(path); | ||
if (route.error) { | ||
return { route: route } | ||
buildQueryUrl(url, query) { | ||
console.warn("[druxt-router] `buildQueryUrl` is deprecated. See http://druxtjs.org/api/client."); | ||
return this.druxt.buildQueryUrl(url, query); | ||
} | ||
var redirect = this.getRedirect(path, route); | ||
return { redirect: redirect, route: route } | ||
}; | ||
/** | ||
* Get index of all available resources, or the optionally specified resource. | ||
* | ||
* @deprecated | ||
* @see {@link https://druxtjs.org/api/client} | ||
* | ||
* @example @lang js | ||
* const { href } = await router.druxt.getIndex('node--article') | ||
* | ||
* @param {string} resource - (Optional) A specific resource to query. | ||
* | ||
* @returns {object} The resource index object or the specified resource. | ||
*/ | ||
DruxtRouter.prototype.getIndex = async function getIndex (resource) { | ||
console.warn('[druxt-router] `getIndex` is deprecated. See http://druxtjs.org/api/client.'); | ||
this.index = await this.druxt.getIndex(resource); | ||
return this.index | ||
}; | ||
/** | ||
* 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. | ||
*/ | ||
DruxtRouter.prototype.getRedirect = function getRedirect (path, route) { | ||
if ( route === void 0 ) route = {}; | ||
// Redirect to route provided redirect. | ||
if (((route.redirect || [])[0] || {}).to) { | ||
return route.redirect[0].to | ||
checkPermissions(res) { | ||
console.warn("[druxt-router] `checkPermissions` is deprecated. See http://druxtjs.org/api/client."); | ||
return this.druxt.checkPermissions(res); | ||
} | ||
var url = Url(path); | ||
// Redirect to root if route is home path but path isn't root. | ||
if (route.isHomePath) { | ||
if (url.pathname !== '/') { | ||
return '/' | ||
async get(path) { | ||
const route = await this.getRoute(path); | ||
if (route.error) { | ||
return { route }; | ||
} | ||
return false | ||
const redirect = this.getRedirect(path, route); | ||
return { redirect, route }; | ||
} | ||
// Redirect if path does not match resolved clean url path. | ||
if (typeof route.canonical === 'string') { | ||
var canonicalUrl = new Url(route.canonical); | ||
if (url.pathname !== canonicalUrl.pathname) { | ||
return canonicalUrl.pathname | ||
} | ||
async getIndex(resource) { | ||
console.warn("[druxt-router] `getIndex` is deprecated. See http://druxtjs.org/api/client."); | ||
this.index = await this.druxt.getIndex(resource); | ||
return this.index; | ||
} | ||
return false | ||
}; | ||
/** | ||
* Get a JSON:API resource by type and ID. | ||
* | ||
* @deprecated | ||
* @see {@link https://druxtjs.org/api/client} | ||
* | ||
* @example @lang js | ||
* const data = await router.druxt.getResource('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. | ||
*/ | ||
DruxtRouter.prototype.getResource = async function getResource (query) { | ||
if ( query === void 0 ) query = {}; | ||
console.warn('[druxt-router] `getResource` is deprecated. See http://druxtjs.org/api/client.'); | ||
var resource = await this.druxt.getResource(query.type, query.id); | ||
return resource.data || false | ||
}; | ||
/** | ||
* Gets a collection of resources. | ||
* | ||
* @deprecated | ||
* @see {@link https://druxtjs.org/api/client} | ||
* | ||
* @todo Add granular pagination. | ||
* | ||
* @example @lang js | ||
* // Load all currently published Articles. | ||
* const query = new DrupalJsonApiParams() | ||
* query.addFilter('status', '1') | ||
* const resources = await router.druxt.getCollection('node--article', query) | ||
* | ||
* @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. | ||
*/ | ||
DruxtRouter.prototype.getResources = async function getResources (resource, query, options) { | ||
if ( options === void 0 ) options = {}; | ||
console.warn('[druxt-router] `getResources` is deprecated. See http://druxtjs.org/api/client.'); | ||
var resources = { data: [] }; | ||
if (options.all) { | ||
var collections = await this.druxt.getCollectionAll(resource, query); | ||
collections.map(function (collection) { (collection.data || []).map(function (resource) { resources.data.push(resource); }); }); | ||
} else { | ||
resources = await this.druxt.getCollection(resource, query); | ||
} | ||
return resources.data || false | ||
}; | ||
/** | ||
* Get a JSON:API resource by Drupal 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. | ||
*/ | ||
DruxtRouter.prototype.getResourceByRoute = async function getResourceByRoute (route) { | ||
var resource = await this.druxt.getResource(route.jsonapi.resourceName, route.entity.uuid); | ||
return resource.data || false | ||
}; | ||
/** | ||
* Get routing data from Decoupled Router. | ||
* | ||
* @example @lang js | ||
* const route = await router.getRoute('/') | ||
* | ||
* @param {string} path - The route path. | ||
* | ||
* @returns {object} The route object. | ||
*/ | ||
DruxtRouter.prototype.getRoute = async function getRoute (path) { | ||
// @TODO - Add validation/error handling. | ||
var url = "/router/translate-path?path=" + path; | ||
var response = await this.druxt.axios.get(url, { | ||
// Prevent invalid routes (404) from throwing validation errors. | ||
validateStatus: function (status) { return status < 500; } | ||
}); | ||
var data = Object.assign({}, {isHomePath: false, | ||
jsonapi: {}, | ||
label: false, | ||
redirect: false}, | ||
response.data); | ||
var route = { | ||
error: false, | ||
type: false, | ||
canonical: false, | ||
component: false, | ||
isHomePath: data.isHomePath, | ||
jsonapi: data.jsonapi, | ||
label: data.label, | ||
props: false, | ||
redirect: data.redirect, | ||
resolvedPath: Url(data.resolved).pathname | ||
}; | ||
// Determine route type by configuration. | ||
// @TODO - Move type to Decoupled router. | ||
// @SEE- https://www.drupal.org/project/decoupled_router/issues/3146024 | ||
for (var key in this.options.types) { | ||
var type = Object.assign({}, this.options.types[key]); | ||
if (typeof type.property !== 'string' || typeof data[type.property] === 'undefined') { | ||
continue | ||
getRedirect(path, route = {}) { | ||
if (((route.redirect || [])[0] || {}).to) { | ||
return route.redirect[0].to; | ||
} | ||
delete type.property; | ||
// Construct canonical link. | ||
if (typeof type.canonical === 'function') { | ||
type.canonical = type.canonical(data); | ||
const url = Url__default['default'](path); | ||
if (route.isHomePath) { | ||
if (url.pathname !== "/") { | ||
return "/"; | ||
} | ||
return false; | ||
} | ||
// Construct props. | ||
if (typeof type.props === 'function') { | ||
type.props = type.props(data); | ||
if (typeof route.canonical === "string") { | ||
const canonicalUrl = new Url__default['default'](route.canonical); | ||
if (url.pathname !== canonicalUrl.pathname) { | ||
return canonicalUrl.pathname; | ||
} | ||
} | ||
// Merge type | ||
route = Object.assign({}, route, | ||
type); | ||
break | ||
return false; | ||
} | ||
// Process Axios error. | ||
if (!(response.status >= 200 && response.status < 300)) { | ||
route.error = { | ||
statusCode: response.status, | ||
message: response.statusText | ||
}; | ||
route.component = 'error'; | ||
async getResource(query = {}) { | ||
console.warn("[druxt-router] `getResource` is deprecated. See http://druxtjs.org/api/client."); | ||
const resource = await this.druxt.getResource(query.type, query.id); | ||
return resource.data || false; | ||
} | ||
return route | ||
};/** | ||
* The DruxtRouterEntityMixin Vue.js mixin provides easy integration with the DruxtJS Router Vuex store, including on-demand loading of JSON:API resources. | ||
* | ||
* @mixin | ||
* | ||
* @example @lang vue | ||
* <template> | ||
* <div v-if="!$fetchState.pending"> | ||
* {{ entity }} | ||
* </div> | ||
* </template> | ||
* | ||
* <script> | ||
* import { DruxtRouterEntityMixin } from 'druxt-router' | ||
* | ||
* export default { | ||
* mixins: [DruxtRouterEntityMixin] | ||
* } | ||
* </script> | ||
*/ | ||
var DruxtRouterEntityMixin = { | ||
/** | ||
* Vue.js Properties. | ||
*/ | ||
props: { | ||
/** | ||
* The Drupal display mode. | ||
* | ||
* @type {string} | ||
* @default default | ||
*/ | ||
mode: { | ||
type: String, | ||
default: 'default' | ||
}, | ||
/** | ||
* The JSON:API resource type. | ||
* | ||
* @type {string} | ||
*/ | ||
type: { | ||
type: String, | ||
required: true | ||
}, | ||
/** | ||
* The Drupal entity UUID. | ||
* | ||
* @type {string} | ||
*/ | ||
uuid: { | ||
type: String, | ||
required: true | ||
async getResources(resource, query, options = {}) { | ||
console.warn("[druxt-router] `getResources` is deprecated. See http://druxtjs.org/api/client."); | ||
let resources = { data: [] }; | ||
if (options.all) { | ||
const collections = await this.druxt.getCollectionAll(resource, query); | ||
collections.map((collection) => { | ||
(collection.data || []).map((resource2) => { | ||
resources.data.push(resource2); | ||
}); | ||
}); | ||
} else { | ||
resources = await this.druxt.getCollection(resource, query); | ||
} | ||
}, | ||
/** | ||
* 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') { | ||
this.entity = this.entities[this.uuid]; | ||
return | ||
return resources.data || false; | ||
} | ||
async getResourceByRoute(route) { | ||
const resource = await this.druxt.getResource(route.jsonapi.resourceName, route.entity.uuid); | ||
return resource.data || false; | ||
} | ||
async getRoute(path) { | ||
const url = `/router/translate-path?path=${path}`; | ||
const response = await this.druxt.axios.get(url, { | ||
validateStatus: (status) => status < 500 | ||
}); | ||
const data = { | ||
isHomePath: false, | ||
jsonapi: {}, | ||
label: false, | ||
redirect: false, | ||
...response.data | ||
}; | ||
let route = { | ||
error: false, | ||
type: false, | ||
canonical: false, | ||
component: false, | ||
isHomePath: data.isHomePath, | ||
jsonapi: data.jsonapi, | ||
label: data.label, | ||
props: false, | ||
redirect: data.redirect, | ||
resolvedPath: Url__default['default'](data.resolved).pathname | ||
}; | ||
for (const key in this.options.types) { | ||
const type = { | ||
...this.options.types[key] | ||
}; | ||
if (typeof type.property !== "string" || typeof data[type.property] === "undefined") { | ||
continue; | ||
} | ||
delete type.property; | ||
if (typeof type.canonical === "function") { | ||
type.canonical = type.canonical(data); | ||
} | ||
if (typeof type.props === "function") { | ||
type.props = type.props(data); | ||
} | ||
route = { | ||
...route, | ||
...type | ||
}; | ||
break; | ||
} | ||
// Otherwise invoke getResource() to retrieve it from Drupal. | ||
if (!this.entity && this.uuid && this.type) { | ||
var resource = await this.getResource({ id: this.uuid, type: this.type }); | ||
this.entity = resource.data; | ||
this.loading = false; | ||
if (!(response.status >= 200 && response.status < 300)) { | ||
route.error = { | ||
statusCode: response.status, | ||
message: response.statusText | ||
}; | ||
route.component = "error"; | ||
} | ||
}, | ||
/** | ||
* 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 Router Vuex `entities` state. | ||
* @see {@link store|src/store.js} | ||
*/ | ||
computed: Object.assign({}, vuex.mapState({ | ||
entities: function (state) { return state.druxt.resources; } | ||
})), | ||
/** | ||
* Vue.js Methods. | ||
* | ||
* - Maps Vuex `druxtRouter/getEntity` action to `this->getEntity()`. | ||
* - Maps Vuex `druxt/getResource` action to `this->getResource()`. | ||
* | ||
* @see {@link store|src/store.js} | ||
*/ | ||
methods: Object.assign({}, vuex.mapActions({ | ||
getEntity: 'druxtRouter/getEntity', | ||
getResource: 'druxt/getResource' | ||
})) | ||
};/** | ||
* The DruxtRouterMixin Vue.js mixin provides the props required for a Router Druxt wrapper component. | ||
* | ||
* @mixin | ||
* | ||
* @example @lang vue | ||
* <template> | ||
* <div> | ||
* <slot /> | ||
* </div> | ||
* </template> | ||
* | ||
* <script> | ||
* import { DruxtRouterMixin } from 'druxt-router' | ||
* | ||
* export default { | ||
* mixins: [DruxtRouterMixin] | ||
* } | ||
* </script> | ||
*/ | ||
var DruxtRouterMixin = { | ||
/** | ||
* Vue.js Properties. | ||
*/ | ||
props: { | ||
/** | ||
* The Decoupled router object. | ||
* | ||
* @type {object} | ||
*/ | ||
route: { | ||
type: Object, | ||
required: true | ||
} | ||
return route; | ||
} | ||
};var DruxtRouterStore = function (ref) { | ||
var store = ref.store; | ||
} | ||
if (typeof store === 'undefined') { | ||
throw new TypeError('Vuex store not found.') | ||
const DruxtRouterStore = ({ store }) => { | ||
if (typeof store === "undefined") { | ||
throw new TypeError("Vuex store not found."); | ||
} | ||
/** | ||
* @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 Change namespace to `druxt/router`. | ||
*/ | ||
var module = { | ||
const namespace = "druxtRouter"; | ||
const 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 ({ | ||
state: () => ({ | ||
entities: {}, | ||
@@ -827,228 +218,123 @@ redirect: false, | ||
routes: {} | ||
}); }, | ||
/** | ||
* Vuex Mutations. | ||
*/ | ||
}), | ||
mutations: { | ||
/** | ||
* @deprecated | ||
* @see {@link https://druxtjs.org/api/stores/druxt} | ||
* | ||
* @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) { | ||
console.warn('[druxt-router] `druxtRouter/addEntity` is deprecated. See http://druxtjs.org/api/stores/druxt.'); | ||
if (!entity || typeof entity.id === 'undefined') { | ||
// @TODO - Error? | ||
return | ||
addEntity(state, entity) { | ||
console.warn("[druxt-router] `druxtRouter/addEntity` is deprecated. See http://druxtjs.org/api/stores/druxt."); | ||
if (!entity || typeof entity.id === "undefined") { | ||
return; | ||
} | ||
state.entities[entity.id] = entity; | ||
}, | ||
/** | ||
* @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) { | ||
setRedirect(state, redirect) { | ||
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) { | ||
var path = ref.path; | ||
var route = ref.route; | ||
if (typeof path !== 'string' || typeof route === 'undefined') { | ||
// @TODO - Error? | ||
return | ||
addRoute(state, { path, route }) { | ||
if (typeof path !== "string" || typeof route === "undefined") { | ||
return; | ||
} | ||
state.routes[path] = route; | ||
}, | ||
/** | ||
* @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) { | ||
if (typeof path !== 'string' || typeof state.routes[path] === 'undefined') { | ||
// @TODO - Error? | ||
return | ||
setRoute(state, path) { | ||
if (typeof path !== "string" || typeof state.routes[path] === "undefined") { | ||
return; | ||
} | ||
state.route = state.routes[path]; | ||
} | ||
}, | ||
/** | ||
* 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) { | ||
var commit = ref.commit; | ||
var dispatch = ref.dispatch; | ||
var state = ref.state; | ||
// Get route by path from 'getRoute'. | ||
var route = await dispatch('getRoute', path); | ||
// Handle route errors. | ||
if (route.error && typeof route.error.statusCode !== 'undefined' && ((this.app || {}).context || {}).error) { | ||
return this.app.context.error(route.error) | ||
async get({ commit, dispatch, state }, path) { | ||
const route = await dispatch("getRoute", path); | ||
if (route.error && typeof route.error.statusCode !== "undefined" && ((this.app || {}).context || {}).error) { | ||
return this.app.context.error(route.error); | ||
} | ||
// Set active route. | ||
commit('setRoute', path); | ||
// Set active redirect. | ||
var redirect = this.$druxtRouter().getRedirect(path, route); | ||
commit('setRedirect', redirect); | ||
return { redirect: redirect, route: route } | ||
commit("setRoute", path); | ||
const redirect = this.$druxtRouter().getRedirect(path, route); | ||
commit("setRedirect", redirect); | ||
return { redirect, route }; | ||
}, | ||
/** | ||
* Get Entity. | ||
* | ||
* - Executes query against Drupal JSON:API. | ||
* - Caches result in the Vuex store. | ||
* - Returns cached result from Vuex store when available. | ||
* | ||
* @deprecated | ||
* @see {@link https://druxtjs.org/api/stores/druxt} | ||
* | ||
* @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) { | ||
var commit = ref.commit; | ||
var state = ref.state; | ||
console.warn('[druxt-router] `druxtRouter/getEntity` is deprecated. See http://druxtjs.org/api/stores/druxt.'); | ||
if (typeof state.entities[query.id] !== 'undefined') { | ||
return state.entities[query.id] | ||
async getEntity({ commit, state }, query) { | ||
console.warn("[druxt-router] `druxtRouter/getEntity` is deprecated. See http://druxtjs.org/api/stores/druxt."); | ||
if (typeof state.entities[query.id] !== "undefined") { | ||
return state.entities[query.id]; | ||
} | ||
var entity = await this.app.store.dispatch('druxt/getResource', query); | ||
commit('addEntity', entity.data); | ||
return entity.data | ||
const entity = await this.app.store.dispatch("druxt/getResource", query); | ||
commit("addEntity", entity.data); | ||
return entity.data; | ||
}, | ||
/** | ||
* Get multiple resources. | ||
* | ||
* @deprecated | ||
* @see {@link https://druxtjs.org/api/stores/druxt} | ||
* | ||
* @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 } | ||
* }) | ||
*/ | ||
getResources: async function getResources (app, ref) { | ||
var resource = ref.resource; | ||
var query = ref.query; | ||
var options = ref.options; | ||
console.warn('[druxt-router] `druxtRouter/getResources` is deprecated. See http://druxtjs.org/api/stores/druxt.'); | ||
var collection = await this.app.store.dispatch('druxt/getCollection', { type: resource, query: query }); | ||
return collection.data || false | ||
async getResources(app, { resource, query, options }) { | ||
console.warn("[druxt-router] `druxtRouter/getResources` is deprecated. See http://druxtjs.org/api/stores/druxt."); | ||
const collection = await this.app.store.dispatch("druxt/getCollection", { type: resource, query }); | ||
return collection.data || false; | ||
}, | ||
/** | ||
* 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) { | ||
var commit = ref.commit; | ||
var state = ref.state; | ||
if (typeof state.routes[path] !== 'undefined') { | ||
return state.routes[path] | ||
async getRoute({ commit, state }, path) { | ||
if (typeof state.routes[path] !== "undefined") { | ||
return state.routes[path]; | ||
} | ||
var route = await this.$druxtRouter().getRoute(path); | ||
commit('addRoute', { path: path, route: route }); | ||
return route | ||
const route = await this.$druxtRouter().getRoute(path); | ||
commit("addRoute", { path, route }); | ||
return route; | ||
} | ||
} | ||
}; | ||
store.registerModule(namespace, module, { | ||
preserveState: Boolean(store.state[namespace]) | ||
}); | ||
};exports.DruxtRouter=DruxtRouter;exports.DruxtRouterComponent=__vue_component__;exports.DruxtRouterEntityMixin=DruxtRouterEntityMixin;exports.DruxtRouterMixin=DruxtRouterMixin;exports.DruxtRouterStore=DruxtRouterStore;exports.default=DruxtRouterNuxtModule; | ||
}; | ||
const DruxtRouterEntityMixin = { | ||
props: { | ||
mode: { | ||
type: String, | ||
default: "default" | ||
}, | ||
type: { | ||
type: String, | ||
required: true | ||
}, | ||
uuid: { | ||
type: String, | ||
required: true | ||
} | ||
}, | ||
async fetch() { | ||
if (typeof this.entities[this.uuid] !== "undefined") { | ||
this.entity = this.entities[this.uuid]; | ||
return; | ||
} | ||
if (!this.entity && this.uuid && this.type) { | ||
const resource = await this.getResource({ id: this.uuid, type: this.type }); | ||
this.entity = resource.data; | ||
this.loading = false; | ||
} | ||
}, | ||
data: () => ({ | ||
entity: false, | ||
loading: true | ||
}), | ||
computed: { | ||
...vuex.mapState({ | ||
entities: (state) => state.druxt.resources | ||
}) | ||
}, | ||
methods: { | ||
...vuex.mapActions({ | ||
getEntity: "druxtRouter/getEntity", | ||
getResource: "druxt/getResource" | ||
}) | ||
} | ||
}; | ||
const DruxtRouterMixin = { | ||
props: { | ||
route: { | ||
type: Object, | ||
required: true | ||
} | ||
} | ||
}; | ||
exports.DruxtRouter = DruxtRouter; | ||
exports.DruxtRouterEntityMixin = DruxtRouterEntityMixin; | ||
exports.DruxtRouterMixin = DruxtRouterMixin; | ||
exports.DruxtRouterStore = DruxtRouterStore; | ||
exports['default'] = DruxtRouterNuxtModule; |
@@ -1,5 +0,5 @@ | ||
import { DruxtRouterComponent } from 'druxt-router' | ||
import DruxtRouter from 'druxt-router/dist/components/DruxtRouter.vue' | ||
export default { | ||
extends: DruxtRouterComponent | ||
extends: DruxtRouter | ||
} |
108
package.json
{ | ||
"name": "druxt-router", | ||
"version": "0.18.1", | ||
"description": "Simple decoupled Drupal routing for Nuxt.", | ||
"files": [ | ||
"dist", | ||
"nuxt" | ||
], | ||
"main": "dist/druxt-router.ssr.js", | ||
"module": "dist/druxt-router.esm.js", | ||
"unpkg": "dist/druxt-router.min.js", | ||
"scripts": { | ||
"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", | ||
"dev": "nodemon --ext js,vue --exec 'npm run lint && npm run build && npm run test'", | ||
"docs:dev": "npx druxt-docgen", | ||
"docs:build": "npx druxt-docgen build", | ||
"lint": "eslint --ext .js,.vue src", | ||
"start": "npm run dev", | ||
"test": "jest" | ||
}, | ||
"nodemonConfig": { | ||
"ignore": [ | ||
"dist/*" | ||
] | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/druxt/druxt_router.git" | ||
}, | ||
"version": "0.19.0", | ||
"description": "Drupal router for Nuxt, powered by the Drupal Decoupled Router module.", | ||
"keywords": [ | ||
@@ -42,60 +14,32 @@ "drupal", | ||
], | ||
"author": "Stuart Clark <stuart@realityloop.com>", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/druxt/druxt_router/issues" | ||
"author": { | ||
"name": "Stuart Clark", | ||
"email": "stuart@realityloop.com", | ||
"url": "https://realityloop.com" | ||
}, | ||
"homepage": "https://github.com/druxt/druxt_router#readme", | ||
"exports": { | ||
".": { | ||
"require": "./dist/druxt-router.ssr.js", | ||
"import": "./dist/druxt-router.esm.js" | ||
}, | ||
"./components/*": "./dist/components/*" | ||
}, | ||
"main": "dist/druxt-router.ssr.js", | ||
"module": "dist/druxt-router.esm.js", | ||
"files": [ | ||
"dist", | ||
"nuxt" | ||
], | ||
"dependencies": { | ||
"codecov": "^3.8.1", | ||
"druxt": "^0.4.1", | ||
"url-parse": "^1.4.7", | ||
"vuex": "^3.6.0" | ||
"druxt": "workspace:*", | ||
"url-parse": "^1.4.7" | ||
}, | ||
"devDependencies": { | ||
"@babel/node": "^7.12.10", | ||
"@babel/plugin-transform-runtime": "^7.12.10", | ||
"@babel/preset-env": "^7.12.11", | ||
"@babel/runtime": "^7.12.5", | ||
"@nuxtjs/eslint-config": "^2.0.2", | ||
"@rollup/plugin-alias": "^3.1.1", | ||
"@rollup/plugin-buble": "^0.21.3", | ||
"@rollup/plugin-replace": "^2.3.4", | ||
"@vue/test-utils": "^1.1.2", | ||
"babel-core": "^7.0.0-bridge.0", | ||
"babel-eslint": "^10.1.0", | ||
"core-js": "^2.6.12", | ||
"cross-env": "^7.0.3", | ||
"eslint": "^6.8.0", | ||
"get-port": "^5.1.1", | ||
"gh-pages": "^3.1.0", | ||
"jest": "^26.6.3", | ||
"jest-junit": "^11.1.0", | ||
"jest-mock-axios": "^3.2.0", | ||
"md5": "^2.3.0", | ||
"nodemon": "^2.0.7", | ||
"request": "^2.88.2", | ||
"require-directory": "^2.1.1", | ||
"rollup": "^1.32.1", | ||
"rollup-plugin-commonjs": "^10.1.0", | ||
"rollup-plugin-terser": "^7.0.2", | ||
"rollup-plugin-vue": "^5.1.9", | ||
"vue": "^2.6.12", | ||
"vue-jest": "^3.0.7", | ||
"vue-server-renderer": "^2.6.12", | ||
"vue-template-compiler": "^2.6.12" | ||
"optionalDependencies": { | ||
"vue": "^2.6.14", | ||
"vuex": "^3.6.2" | ||
}, | ||
"jest": { | ||
"coverageDirectory": "./coverage/", | ||
"collectCoverage": true, | ||
"moduleFileExtensions": [ | ||
"js", | ||
"json", | ||
"vue" | ||
], | ||
"transform": { | ||
".*\\.(vue)$": "vue-jest", | ||
"^.+\\.js$": "<rootDir>/node_modules/babel-jest" | ||
} | ||
"publishConfig": { | ||
"access": "public" | ||
} | ||
} |
@@ -7,3 +7,3 @@ # DruxtJS Router | ||
> Simple decoupled [Drupal](https://drupal.org) routing for your [Nuxt.js](https://nuxtjs.org) application. | ||
> Drupal router for Nuxt, powered by the Drupal Decoupled Router module. | ||
@@ -10,0 +10,0 @@ ## Links |
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
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
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 repository
Supply chain riskPackage does not have a linked source code repository. Without this field, a package will have no reference to the location of the source code use to generate the package.
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
0
10
28305
692
1
1
- Removedcodecov@^3.8.1
- Removedvuex@^3.6.0
- Removed@tootallnate/once@1.1.2(transitive)
- Removedagent-base@6.0.2(transitive)
- Removedargparse@1.0.10(transitive)
- Removedargv@0.0.2(transitive)
- Removedaxios@0.21.4(transitive)
- Removedbalanced-match@1.0.2(transitive)
- Removedbrace-expansion@1.1.11(transitive)
- Removedcharenc@0.0.2(transitive)
- Removedcodecov@3.8.3(transitive)
- Removedconcat-map@0.0.1(transitive)
- Removedcrypt@0.0.2(transitive)
- Removeddebug@4.3.7(transitive)
- Removeddruxt@0.4.2(transitive)
- Removedesprima@4.0.1(transitive)
- Removedfast-url-parser@1.1.3(transitive)
- Removedfollow-redirects@1.15.9(transitive)
- Removedhttp-proxy-agent@4.0.1(transitive)
- Removedhttps-proxy-agent@5.0.1(transitive)
- Removedignore-walk@3.0.4(transitive)
- Removedis-buffer@1.1.6(transitive)
- Removedjs-yaml@3.14.1(transitive)
- Removedmd5@2.3.0(transitive)
- Removedminimatch@3.1.2(transitive)
- Removedms@2.1.3(transitive)
- Removednode-fetch@2.7.0(transitive)
- Removedpunycode@1.4.1(transitive)
- Removedquerystring@0.2.1(transitive)
- Removedsprintf-js@1.0.3(transitive)
- Removedstream-events@1.0.5(transitive)
- Removedstubs@3.0.0(transitive)
- Removedteeny-request@7.1.1(transitive)
- Removedtr46@0.0.3(transitive)
- Removedurlgrey@1.0.0(transitive)
- Removeduuid@8.3.2(transitive)
- Removedwebidl-conversions@3.0.1(transitive)
- Removedwhatwg-url@5.0.0(transitive)
Updateddruxt@workspace:*