druxt 0.15.0 → 0.18.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/DruxtDebug.stories.mjs +48 -0
- package/dist/components/DruxtDebug.vue +7 -2
- package/dist/components/DruxtModule.stories.mdx +126 -0
- package/dist/components/DruxtModule.vue +66 -10
- package/dist/druxt.esm.js +110 -41
- package/dist/druxt.ssr.js +110 -41
- package/package.json +7 -2
- package/stories/README.stories.mdx +74 -0
- package/templates/plugin.js +10 -1
- package/CHANGELOG.md +0 -368
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import DruxtDebug from './DruxtDebug.vue'
|
|
2
|
+
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Druxt/DruxtDebug',
|
|
5
|
+
component: DruxtDebug
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const Template = (args) => ({
|
|
9
|
+
components: { DruxtDebug },
|
|
10
|
+
props: Object.keys(args),
|
|
11
|
+
template: `<DruxtDebug v-bind="$props">Debug information.</DruxtDebug>`
|
|
12
|
+
})
|
|
13
|
+
|
|
14
|
+
export const Default = Template.bind({})
|
|
15
|
+
Default.storyName = 'Default slot'
|
|
16
|
+
|
|
17
|
+
export const Json = Template.bind({})
|
|
18
|
+
Json.args = {
|
|
19
|
+
json: {
|
|
20
|
+
type: '',
|
|
21
|
+
id: '',
|
|
22
|
+
links: {},
|
|
23
|
+
attributes: {},
|
|
24
|
+
relationships: {},
|
|
25
|
+
},
|
|
26
|
+
open: true,
|
|
27
|
+
}
|
|
28
|
+
Json.parameters = {
|
|
29
|
+
docs: {
|
|
30
|
+
storyDescription: 'The **json** prop takes any data and runs it through a basic JSON formatter for improved readability.',
|
|
31
|
+
source: {
|
|
32
|
+
code: '<DruxtDebug :json="entity" open>Debug information</DruxtDebug>'
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const Summary = Template.bind({})
|
|
38
|
+
Summary.args = {
|
|
39
|
+
summary: 'A brief debug message'
|
|
40
|
+
}
|
|
41
|
+
Summary.parameters = {
|
|
42
|
+
docs: {
|
|
43
|
+
storyDescription: 'The **summary** prop can be used to provide a quick explanation of the debug component.',
|
|
44
|
+
source: {
|
|
45
|
+
code: `<DruxtDebug summary="${Summary.args.sumary}">Debug information</DruxtDebug>`
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
}
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<pre v-if="json"><!--
|
|
5
5
|
--><code>{{ JSON.stringify(json, null, ' ') }}</code><!--
|
|
6
6
|
--></pre>
|
|
7
|
+
<!-- @slot Debug content -->
|
|
7
8
|
<slot />
|
|
8
9
|
</details>
|
|
9
10
|
|
|
@@ -13,10 +14,14 @@
|
|
|
13
14
|
<script>
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
|
-
*
|
|
17
|
+
* The DruxtDebug component can be used to render debug information that is
|
|
18
|
+
* visible only when Nuxt is run in development mode.
|
|
19
|
+
*
|
|
20
|
+
* You can render your debug information through the default slot, or via the
|
|
21
|
+
* **json** prop to format your data, or a combination of the two.
|
|
17
22
|
*
|
|
18
23
|
* @example @lang vue
|
|
19
|
-
* <DruxtDebug :json="entity"
|
|
24
|
+
* <DruxtDebug :json="entity">Debug information</DruxtDebug>
|
|
20
25
|
*/
|
|
21
26
|
export default {
|
|
22
27
|
/** */
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { Canvas, Meta, Story } from '@storybook/addon-docs'
|
|
2
|
+
|
|
3
|
+
<Meta title="Druxt/DruxtModule" />
|
|
4
|
+
|
|
5
|
+
# DruxtModule
|
|
6
|
+
|
|
7
|
+
The DruxtModule component is the core component to be extended by core and
|
|
8
|
+
custom modules.
|
|
9
|
+
|
|
10
|
+
```js
|
|
11
|
+
import DruxtModule from 'druxt/dist/components/DruxtModule.vue'
|
|
12
|
+
export default {
|
|
13
|
+
extends: DruxtModule
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Fetch config
|
|
20
|
+
|
|
21
|
+
All modules have a two part fetch system available to them; **fetchConfig** and
|
|
22
|
+
**fetchData**.
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
async fetchConfig() {
|
|
26
|
+
// Load configuration data here.
|
|
27
|
+
this.config = await this.getResource({...})
|
|
28
|
+
},
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Fetch config is used to load information from Drupal to determine the default
|
|
32
|
+
behaviour of that component, as well as to determine the available component
|
|
33
|
+
|
|
34
|
+
---
|
|
35
|
+
|
|
36
|
+
## Component options
|
|
37
|
+
|
|
38
|
+
The Druxt Wrapper system looks for available Vue components using a specific
|
|
39
|
+
naming convention, determined by the Druxt module **componentOptions**.
|
|
40
|
+
|
|
41
|
+
This allows for targetted theming of components based on the props or
|
|
42
|
+
configuration data.
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
componentOptions: (context) => ([[context.attributes.foo, 'default']]),
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## Fetch data
|
|
51
|
+
|
|
52
|
+
After the Component options are determined, the first available component is
|
|
53
|
+
determined, and any exported Druxt settings are loaded and used to fetch the
|
|
54
|
+
main module data.
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
async fetchData(settings) {
|
|
58
|
+
// Load data using the settings determine based on the configuration data.
|
|
59
|
+
this.resource = await this.getResource({
|
|
60
|
+
type: this.config.attributes.foo,
|
|
61
|
+
id: this.id,
|
|
62
|
+
query: this.getQuery(settings)
|
|
63
|
+
})
|
|
64
|
+
},
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
---
|
|
68
|
+
|
|
69
|
+
## Props data
|
|
70
|
+
|
|
71
|
+
The **propsData** callback returns the props data for the render Wrapper
|
|
72
|
+
component, making props data available to the frontend developer.
|
|
73
|
+
|
|
74
|
+
```js
|
|
75
|
+
propsData: (context) => ({ foo: context.config.attributes.foo })
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
## Slots
|
|
81
|
+
|
|
82
|
+
The **slots** method builds the slots that are made available to the Wrapper
|
|
83
|
+
component. It is expected to return an object of scoped slot functions.
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
slots(h) {
|
|
87
|
+
return {
|
|
88
|
+
default: () => h('div', ['Hello world']),
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
---
|
|
94
|
+
|
|
95
|
+
### Custom module boilerplate
|
|
96
|
+
|
|
97
|
+
Paste this into a Vue component as a starting point for a custom or contrib
|
|
98
|
+
Druxt module.
|
|
99
|
+
|
|
100
|
+
```vue
|
|
101
|
+
<script>
|
|
102
|
+
import DruxtModule from 'druxt/dist/components/DruxtModule.vue'
|
|
103
|
+
export default {
|
|
104
|
+
name: 'MyModule',
|
|
105
|
+
extends: DruxtModule
|
|
106
|
+
druxt: {
|
|
107
|
+
async fetchConfig() {
|
|
108
|
+
// Load configuration data here.
|
|
109
|
+
},
|
|
110
|
+
async fetchData(settings) {
|
|
111
|
+
// Load data using the settings determine based on the configuration data.
|
|
112
|
+
},
|
|
113
|
+
// Build nested arrays of component options based on the context.
|
|
114
|
+
componentOptions: (context) => ([['default']]),
|
|
115
|
+
// Map props data from the context.
|
|
116
|
+
propsData: (context) => ({ ...context }),
|
|
117
|
+
// Build slots render arrays.
|
|
118
|
+
slots(h) {
|
|
119
|
+
return {
|
|
120
|
+
default: () => h('div', ['Hello world'])
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
</script>
|
|
126
|
+
```
|
|
@@ -6,7 +6,11 @@ import Vue from 'vue'
|
|
|
6
6
|
import DruxtWrapper from './DruxtWrapper.vue'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* The DruxtModule component is used to make a Druxt module, simply import and
|
|
10
|
+
* extend the component to get started.
|
|
11
|
+
*
|
|
12
|
+
* The component provides access to the Druxt Wrapper theming and fetch system
|
|
13
|
+
* via the druxt settings object.
|
|
10
14
|
*
|
|
11
15
|
* @example @lang js
|
|
12
16
|
* import DruxtModule from 'druxt/dist/components/DruxtModule.vue'
|
|
@@ -14,11 +18,18 @@ import DruxtWrapper from './DruxtWrapper.vue'
|
|
|
14
18
|
* name: 'DruxtTestModule',
|
|
15
19
|
* extends: DruxtModule,
|
|
16
20
|
* druxt: {
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
+
* async fetchConfig() {},
|
|
22
|
+
* async fetchData(settings) {},
|
|
23
|
+
* componentOptions: (context) => ([[context.foo, context.bar, 'default']]),
|
|
24
|
+
* propsData: (context) => ({
|
|
25
|
+
* foo: context.foo,
|
|
26
|
+
* bar: context.bar,
|
|
21
27
|
* }),
|
|
28
|
+
* slots(h) {
|
|
29
|
+
* return {
|
|
30
|
+
* default: (attrs) => h('DruxtDebug', ['Hello world'])
|
|
31
|
+
* }
|
|
32
|
+
* }
|
|
22
33
|
* }
|
|
23
34
|
* }
|
|
24
35
|
*/
|
|
@@ -107,12 +118,16 @@ export default {
|
|
|
107
118
|
|
|
108
119
|
// Fetch configuration.
|
|
109
120
|
if ((this.$options.druxt || {}).fetchConfig) {
|
|
110
|
-
|
|
121
|
+
try {
|
|
122
|
+
await this.$options.druxt.fetchConfig.call(this)
|
|
123
|
+
} catch(err) {
|
|
124
|
+
return this.error(err)
|
|
125
|
+
}
|
|
111
126
|
}
|
|
112
127
|
|
|
113
128
|
// Build wrapper component object.
|
|
114
129
|
let options = []
|
|
115
|
-
const hasDefaultTemplate = !!(this.$vnode.data.scopedSlots || {}).default
|
|
130
|
+
const hasDefaultTemplate = !!(((this.$vnode || {}).data || {}).scopedSlots || {}).default
|
|
116
131
|
// Load wrapper components if:
|
|
117
132
|
if (
|
|
118
133
|
// No default template and wrapper isn't false OR
|
|
@@ -138,7 +153,11 @@ export default {
|
|
|
138
153
|
|
|
139
154
|
// Fetch resource.
|
|
140
155
|
if ((this.$options.druxt || {}).fetchData) {
|
|
141
|
-
|
|
156
|
+
try {
|
|
157
|
+
await this.$options.druxt.fetchData.call(this, component.settings)
|
|
158
|
+
} catch(err) {
|
|
159
|
+
return this.error(err, { component })
|
|
160
|
+
}
|
|
142
161
|
}
|
|
143
162
|
|
|
144
163
|
// Get scoped slots.
|
|
@@ -153,7 +172,7 @@ export default {
|
|
|
153
172
|
|
|
154
173
|
watch: {
|
|
155
174
|
model() {
|
|
156
|
-
if (this.component.props.value !== this.model) {
|
|
175
|
+
if (this.component.props && this.component.props.value !== this.model) {
|
|
157
176
|
this.component.props.value = this.model
|
|
158
177
|
|
|
159
178
|
// Only emit 'input' if using the default 'DruxtWrapper' component.
|
|
@@ -172,6 +191,31 @@ export default {
|
|
|
172
191
|
|
|
173
192
|
/** */
|
|
174
193
|
methods: {
|
|
194
|
+
/**
|
|
195
|
+
* Sets the component to render a DruxtDebug error message.
|
|
196
|
+
*/
|
|
197
|
+
error(err, context = {}) {
|
|
198
|
+
// Build error details.
|
|
199
|
+
const { url } = err.druxt || {}
|
|
200
|
+
const title = (err.response || {}).statusText || ((((err.response || {}).data || {}).errors || [])[0] || {}).title
|
|
201
|
+
const summary = (err.response || {}).status
|
|
202
|
+
? [(err.response || {}).status, title].filter((s) => s).join(': ')
|
|
203
|
+
: err.message
|
|
204
|
+
|
|
205
|
+
// Set the component to a Debug component with error details.
|
|
206
|
+
this.component = {
|
|
207
|
+
...context.component || {},
|
|
208
|
+
is: 'DruxtDebug',
|
|
209
|
+
props: {
|
|
210
|
+
json: {
|
|
211
|
+
url,
|
|
212
|
+
errors: ((err.response || {}).data || {}).errors
|
|
213
|
+
},
|
|
214
|
+
summary
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
|
|
175
219
|
/**
|
|
176
220
|
* Get list of module wrapper components.
|
|
177
221
|
*
|
|
@@ -193,7 +237,7 @@ export default {
|
|
|
193
237
|
let components = []
|
|
194
238
|
for (const set of options.filter(set => Array.isArray(set))) {
|
|
195
239
|
const variants = []
|
|
196
|
-
components = [...components, ...set.map(item => {
|
|
240
|
+
components = [...components, ...set.filter((o) => o).map(item => {
|
|
197
241
|
// Build array of name parts.
|
|
198
242
|
const parts = variants.length ? [...variants[0].parts] : []
|
|
199
243
|
parts.push(pascalCase(splitByCase(item)))
|
|
@@ -265,6 +309,18 @@ export default {
|
|
|
265
309
|
*/
|
|
266
310
|
getScopedSlots() {
|
|
267
311
|
const h = this.$createElement
|
|
312
|
+
|
|
313
|
+
// Get an array of unmet required props.
|
|
314
|
+
const required = Object.entries(this.$options.props)
|
|
315
|
+
.filter(([k, o]) => o.required && !this[k])
|
|
316
|
+
.map(([k]) => k)
|
|
317
|
+
// Return debug error if any missing props are found.
|
|
318
|
+
if (required.length) {
|
|
319
|
+
return {
|
|
320
|
+
default: () => h('DruxtDebug', { props: { summary: `Missing required props: ${required.join(', ')}.` } })
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
268
324
|
const scopedSlots = typeof (this.$options.druxt || {}).slots === 'function'
|
|
269
325
|
? this.$options.druxt.slots.call(this, h)
|
|
270
326
|
: {}
|
package/dist/druxt.esm.js
CHANGED
|
@@ -9,7 +9,7 @@ import Vue from 'vue';
|
|
|
9
9
|
import { DrupalJsonApiParams } from 'drupal-jsonapi-params';
|
|
10
10
|
|
|
11
11
|
var name = "druxt";
|
|
12
|
-
var version = "0.
|
|
12
|
+
var version = "0.18.0";
|
|
13
13
|
var description = "The Fully Decoupled Drupal Framework for Nuxt.js.";
|
|
14
14
|
var keywords = [
|
|
15
15
|
"cms",
|
|
@@ -43,11 +43,12 @@ var main = "dist/druxt.ssr.js";
|
|
|
43
43
|
var module = "dist/druxt.esm.js";
|
|
44
44
|
var files = [
|
|
45
45
|
"dist",
|
|
46
|
+
"stories",
|
|
46
47
|
"templates"
|
|
47
48
|
];
|
|
48
49
|
var dependencies = {
|
|
50
|
+
"@nuxtjs/axios": "^5.13.6",
|
|
49
51
|
"@nuxtjs/proxy": "^2.1.0",
|
|
50
|
-
axios: "^0.21.1",
|
|
51
52
|
chalk: "^4.1.2",
|
|
52
53
|
deepmerge: "^4.2.2",
|
|
53
54
|
"drupal-jsonapi-params": "^1.2.1",
|
|
@@ -55,7 +56,11 @@ var dependencies = {
|
|
|
55
56
|
querystring: "^0.2.0",
|
|
56
57
|
scule: "^0.2.0"
|
|
57
58
|
};
|
|
59
|
+
var devDependencies = {
|
|
60
|
+
"@storybook/addon-docs": "^6.4.13"
|
|
61
|
+
};
|
|
58
62
|
var peerDependencies = {
|
|
63
|
+
axios: "*",
|
|
59
64
|
consola: "*"
|
|
60
65
|
};
|
|
61
66
|
var optionalDependencies = {
|
|
@@ -80,6 +85,7 @@ var meta = {
|
|
|
80
85
|
module: module,
|
|
81
86
|
files: files,
|
|
82
87
|
dependencies: dependencies,
|
|
88
|
+
devDependencies: devDependencies,
|
|
83
89
|
peerDependencies: peerDependencies,
|
|
84
90
|
optionalDependencies: optionalDependencies,
|
|
85
91
|
publishConfig: publishConfig
|
|
@@ -119,6 +125,14 @@ const DruxtNuxtModule = function(moduleOptions = {}) {
|
|
|
119
125
|
}
|
|
120
126
|
this.addModule("@nuxtjs/proxy");
|
|
121
127
|
}
|
|
128
|
+
if (!options.axios) {
|
|
129
|
+
this.options.axios = {
|
|
130
|
+
baseURL: options.baseUrl,
|
|
131
|
+
proxy: !!this.options.proxy,
|
|
132
|
+
...this.options.axios
|
|
133
|
+
};
|
|
134
|
+
this.addModule("@nuxtjs/axios");
|
|
135
|
+
}
|
|
122
136
|
this.nuxt.hook("components:dirs", (dirs) => {
|
|
123
137
|
dirs.push({ path: join(__dirname, "components") });
|
|
124
138
|
});
|
|
@@ -127,6 +141,18 @@ const DruxtNuxtModule = function(moduleOptions = {}) {
|
|
|
127
141
|
fileName: "druxt.js",
|
|
128
142
|
options
|
|
129
143
|
});
|
|
144
|
+
const extendPlugins = this.options.extendPlugins;
|
|
145
|
+
this.options.extendPlugins = (plugins) => {
|
|
146
|
+
plugins = typeof extendPlugins === "function" ? extendPlugins(plugins) : plugins;
|
|
147
|
+
const axiosIndex = plugins.findIndex(({ src }) => src === `${this.options.buildDir}/axios.js`);
|
|
148
|
+
const axiosPlugin = plugins[axiosIndex];
|
|
149
|
+
plugins.splice(axiosIndex, 1);
|
|
150
|
+
const druxtIndex = plugins.findIndex(({ src }) => src === `${this.options.buildDir}/druxt.js`);
|
|
151
|
+
const druxtPlugin = plugins[druxtIndex];
|
|
152
|
+
plugins.splice(druxtIndex, 1);
|
|
153
|
+
plugins = [axiosPlugin, druxtPlugin, ...plugins];
|
|
154
|
+
return plugins;
|
|
155
|
+
};
|
|
130
156
|
this.addPlugin({
|
|
131
157
|
src: resolve(__dirname, "../templates/store.js"),
|
|
132
158
|
fileName: "store/druxt.js",
|
|
@@ -136,8 +162,12 @@ const DruxtNuxtModule = function(moduleOptions = {}) {
|
|
|
136
162
|
this.options.components = (_a = this.options.components) != null ? _a : true;
|
|
137
163
|
this.options.cli.badgeMessages.push(`${chalk.blue.bold("Druxt")} @ v${meta.version}`);
|
|
138
164
|
this.options.cli.badgeMessages.push(`${chalk.bold("API:")} ${chalk.blue.underline(options.baseUrl + options.endpoint)}`);
|
|
165
|
+
this.nuxt.hook("storybook:config", async ({ stories }) => {
|
|
166
|
+
stories.push("druxt/stories/*.stories.mdx");
|
|
167
|
+
stories.push("druxt/dist/components/*.stories.mdx");
|
|
168
|
+
stories.push("druxt/dist/components/*.stories.mjs");
|
|
169
|
+
});
|
|
139
170
|
};
|
|
140
|
-
DruxtNuxtModule.meta = meta;
|
|
141
171
|
|
|
142
172
|
class DruxtClient {
|
|
143
173
|
constructor(baseUrl, options = {}) {
|
|
@@ -147,14 +177,15 @@ class DruxtClient {
|
|
|
147
177
|
if (!baseUrl) {
|
|
148
178
|
throw new Error("The 'baseUrl' parameter is required.");
|
|
149
179
|
}
|
|
150
|
-
|
|
151
|
-
if (
|
|
152
|
-
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
|
|
180
|
+
this.axios = {};
|
|
181
|
+
if (typeof options.axios === "function") {
|
|
182
|
+
this.axios = options.axios;
|
|
183
|
+
} else {
|
|
184
|
+
this.axios = axios.create({
|
|
185
|
+
...options.axios || {},
|
|
186
|
+
baseURL: baseUrl
|
|
187
|
+
});
|
|
156
188
|
}
|
|
157
|
-
this.axios = axios.create(axiosSettings);
|
|
158
189
|
if (options.debug) {
|
|
159
190
|
const log = this.log;
|
|
160
191
|
this.axios.interceptors.request.use((config) => {
|
|
@@ -206,9 +237,16 @@ class DruxtClient {
|
|
|
206
237
|
}
|
|
207
238
|
}
|
|
208
239
|
if (Object.keys(permissions).length) {
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
240
|
+
const err = {
|
|
241
|
+
response: {
|
|
242
|
+
statusText: res.data.meta.omitted.detail,
|
|
243
|
+
data: {
|
|
244
|
+
errors: [{ detail: `Required permissions:
|
|
245
|
+
- ${Object.keys(permissions).join("\n - ")}` }]
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
throw err;
|
|
212
250
|
}
|
|
213
251
|
}
|
|
214
252
|
}
|
|
@@ -228,19 +266,49 @@ class DruxtClient {
|
|
|
228
266
|
}
|
|
229
267
|
});
|
|
230
268
|
} catch (err) {
|
|
231
|
-
|
|
269
|
+
this.error(err, { url: href });
|
|
232
270
|
}
|
|
233
271
|
return response;
|
|
234
272
|
}
|
|
273
|
+
error(err, context = {}) {
|
|
274
|
+
let { url } = context;
|
|
275
|
+
if (!url && ((err.response || {}).config || {}).url) {
|
|
276
|
+
url = err.response.config.url;
|
|
277
|
+
}
|
|
278
|
+
const title = [
|
|
279
|
+
(err.response || {}).status,
|
|
280
|
+
(err.response || {}).statusText || err.message
|
|
281
|
+
].filter((s) => s).join(": ");
|
|
282
|
+
const meta = { url: url && [this.options.baseUrl, url].join("") };
|
|
283
|
+
let message = [title];
|
|
284
|
+
if (Object.values(meta).filter((o) => o).length) {
|
|
285
|
+
message.push(Object.entries(meta).filter(([, v]) => v).map(([key, value]) => `${key.toUpperCase()}: ${value}`).join("\n"));
|
|
286
|
+
}
|
|
287
|
+
if (((((err.response || {}).data || {}).errors || [])[0] || {}).detail) {
|
|
288
|
+
message.push(err.response.data.errors[0].detail);
|
|
289
|
+
}
|
|
290
|
+
const error = Error(message.join("\n\n"));
|
|
291
|
+
error.response = err.response;
|
|
292
|
+
error.druxt = context;
|
|
293
|
+
throw error;
|
|
294
|
+
}
|
|
295
|
+
async get(url, options) {
|
|
296
|
+
try {
|
|
297
|
+
const res = await this.axios.get(url, options);
|
|
298
|
+
this.checkPermissions(res);
|
|
299
|
+
return res;
|
|
300
|
+
} catch (err) {
|
|
301
|
+
this.error(err, { url });
|
|
302
|
+
}
|
|
303
|
+
}
|
|
235
304
|
async getCollection(type, query) {
|
|
236
305
|
const { href } = await this.getIndex(type);
|
|
237
306
|
if (!href) {
|
|
238
307
|
return false;
|
|
239
308
|
}
|
|
240
309
|
const url = this.buildQueryUrl(href, query);
|
|
241
|
-
const
|
|
242
|
-
|
|
243
|
-
return res.data;
|
|
310
|
+
const { data } = await this.get(url);
|
|
311
|
+
return data;
|
|
244
312
|
}
|
|
245
313
|
async getCollectionAll(type, query) {
|
|
246
314
|
const collections = [];
|
|
@@ -260,16 +328,27 @@ class DruxtClient {
|
|
|
260
328
|
if (this.index && resource) {
|
|
261
329
|
return this.index[resource] ? this.index[resource] : false;
|
|
262
330
|
}
|
|
263
|
-
|
|
331
|
+
const url = this.options.endpoint;
|
|
332
|
+
const { data } = await this.get(url);
|
|
333
|
+
let index = data.links;
|
|
334
|
+
if (typeof index !== "object") {
|
|
335
|
+
const err = { response: { statusText: "Invalid JSON:API endpoint" } };
|
|
336
|
+
this.error(err, { url });
|
|
337
|
+
}
|
|
264
338
|
const baseUrl = this.options.baseUrl;
|
|
265
339
|
index = Object.fromEntries(Object.entries(index).map(([key, value]) => {
|
|
266
340
|
value.href = value.href.replace(baseUrl, "");
|
|
267
341
|
return [key, value];
|
|
268
342
|
}));
|
|
269
343
|
if (index[this.options.jsonapiResourceConfig]) {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
344
|
+
let resources = [];
|
|
345
|
+
try {
|
|
346
|
+
resources = (await this.get(index[this.options.jsonapiResourceConfig].href)).data.data;
|
|
347
|
+
} catch (err) {
|
|
348
|
+
this.log.warn(err.message);
|
|
349
|
+
}
|
|
350
|
+
for (const resourceType in resources) {
|
|
351
|
+
const resource2 = resources[resourceType];
|
|
273
352
|
const internal = resource2.attributes.drupal_internal__id.split("--");
|
|
274
353
|
const item = {
|
|
275
354
|
resourceType: resource2.attributes.resourceType,
|
|
@@ -285,11 +364,7 @@ class DruxtClient {
|
|
|
285
364
|
}
|
|
286
365
|
}
|
|
287
366
|
this.index = index;
|
|
288
|
-
|
|
289
|
-
const response = this.index[resource] ? this.index[resource] : false;
|
|
290
|
-
return response;
|
|
291
|
-
}
|
|
292
|
-
return this.index;
|
|
367
|
+
return resource ? this.index[resource] || false : this.index;
|
|
293
368
|
}
|
|
294
369
|
async getRelated(type, id, related, query) {
|
|
295
370
|
if (!id || !type || !related) {
|
|
@@ -300,12 +375,8 @@ class DruxtClient {
|
|
|
300
375
|
href = this.options.endpoint + "/" + type.replace("--", "/");
|
|
301
376
|
}
|
|
302
377
|
const url = this.buildQueryUrl(`${href}/${id}/${related}`, query);
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
return related2.data;
|
|
306
|
-
} catch (e) {
|
|
307
|
-
return false;
|
|
308
|
-
}
|
|
378
|
+
const { data } = await this.get(url);
|
|
379
|
+
return data;
|
|
309
380
|
}
|
|
310
381
|
async getResource(type, id, query) {
|
|
311
382
|
if (!id || !type) {
|
|
@@ -315,13 +386,9 @@ class DruxtClient {
|
|
|
315
386
|
if (!href) {
|
|
316
387
|
href = this.options.endpoint + "/" + type.replace("--", "/");
|
|
317
388
|
}
|
|
318
|
-
const url = this.buildQueryUrl(
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
return resource.data;
|
|
322
|
-
} catch (e) {
|
|
323
|
-
return false;
|
|
324
|
-
}
|
|
389
|
+
const url = this.buildQueryUrl([href, id].join("/"), query);
|
|
390
|
+
const { data } = await this.get(url);
|
|
391
|
+
return data;
|
|
325
392
|
}
|
|
326
393
|
async updateResource(resource) {
|
|
327
394
|
const { href } = await this.getIndex(resource.type);
|
|
@@ -337,7 +404,7 @@ class DruxtClient {
|
|
|
337
404
|
}
|
|
338
405
|
});
|
|
339
406
|
} catch (err) {
|
|
340
|
-
|
|
407
|
+
this.error(err);
|
|
341
408
|
}
|
|
342
409
|
return response;
|
|
343
410
|
}
|
|
@@ -348,7 +415,7 @@ const getDrupalJsonApiParams = (query) => {
|
|
|
348
415
|
};
|
|
349
416
|
|
|
350
417
|
const dehydrateResources = ({ commit, queryObject, resources }) => {
|
|
351
|
-
return resources.map((data) => {
|
|
418
|
+
return (resources || []).map((data) => {
|
|
352
419
|
const link = decodeURI(((data.links || {}).self || {}).href || "");
|
|
353
420
|
const href = typeof (queryObject.fields || {})[data.type] === "string" ? [link.split("?")[0], `fields[${data.type}]=${queryObject.fields[data.type]}`].join("?") : link;
|
|
354
421
|
commit("druxt/addResource", {
|
|
@@ -539,5 +606,7 @@ class DruxtClass {
|
|
|
539
606
|
}
|
|
540
607
|
}
|
|
541
608
|
|
|
609
|
+
DruxtNuxtModule.meta = require("../package.json");
|
|
610
|
+
|
|
542
611
|
export default DruxtNuxtModule;
|
|
543
612
|
export { DruxtClass, DruxtClient, DruxtStore };
|