Socket
Socket
Sign inDemoInstall

druxt-router

Package Overview
Dependencies
Maintainers
1
Versions
51
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

druxt-router - npm Package Compare versions

Comparing version 0.18.1 to 0.19.0

CHANGELOG.md

1258

dist/druxt-router.esm.js
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
}
{
"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

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc