druxt 0.11.0 → 0.15.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/CHANGELOG.md CHANGED
@@ -1,5 +1,104 @@
1
1
  # druxt
2
2
 
3
+ ## 0.15.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 2ae1d6d: Reduced Fetch based UI flicker in the DruxtModule
8
+
9
+ ## 0.14.0
10
+
11
+ ### Minor Changes
12
+
13
+ - 85fff42: Added debug mode and Axios request logging.
14
+
15
+ ```
16
+ export default {
17
+ druxt: {
18
+ // Enable debug log messages.
19
+ debug: true,
20
+ }
21
+ }
22
+ ```
23
+
24
+ - 39e2e2e: Added ability to render readable JSON with the DruxtDebug component
25
+
26
+ ```jsx
27
+ <DruxtDebug :json="{ data: [{ one: true, two: false }] }" />
28
+ ```
29
+
30
+ - 9c33d82: Made summary prop optional on DruxtDebug component
31
+ - 45bc0b9: Added Druxt version to Nuxt badge
32
+
33
+ ## 0.13.0
34
+
35
+ ### Minor Changes
36
+
37
+ - 77ab204: Added ability to proxy the API
38
+
39
+ ```js
40
+ export default {
41
+ druxt: {
42
+ proxy: {
43
+ api: true
44
+ }
45
+ }
46
+ };
47
+ ```
48
+
49
+ Creates two proxy entries:
50
+
51
+ - The JSON:API: `${ENDPOINT}` -> `${BASEURL}${ENDPOINT}`
52
+ - The Decoupled Router:`/router/translate-path` -> `${BASEURL}/router/translate-path`
53
+
54
+ - 77ab204: Added ability to proxy the Drupal file system
55
+
56
+ ```js
57
+ export default {
58
+ druxt: {
59
+ proxy: {
60
+ files: "default"
61
+ }
62
+ }
63
+ };
64
+ ```
65
+
66
+ Creates a proxy entry:
67
+
68
+ - `/sites/${PATH}/files` -> `${BASEURL}/site/${PATH}/files`
69
+
70
+ - c4457e1: Changed template injected module components to not use a DruxtWrapper component by default.
71
+ - e7b1533: Refactored DruxtModule fetch hooks
72
+
73
+ ## 0.12.0
74
+
75
+ ### Minor Changes
76
+
77
+ - 897dcbc: Added createResource method to DruxtClient
78
+
79
+ ```js
80
+ this.$druxt.createResource({ type, attributes: {}, relationships: {} });
81
+ ```
82
+
83
+ - 897dcbc: Added updateResource method to DruxtClient
84
+
85
+ ```js
86
+ await this.$druxt.updateResource({
87
+ type,
88
+ id,
89
+ attributes: {},
90
+ relationships: {}
91
+ });
92
+ ```
93
+
94
+ - 4504a2f: Added getRelated() method
95
+
96
+ ```js
97
+ await this.$druxt.getRelated(type, id, related);
98
+ ```
99
+
100
+ - e3e634c: Enabled Components auto-discovery by default
101
+
3
102
  ## 0.11.0
4
103
 
5
104
  ### Minor Changes
@@ -1,6 +1,9 @@
1
1
  <template>
2
2
  <details v-if="$nuxt.context.isDev">
3
3
  <summary v-text="title" />
4
+ <pre v-if="json"><!--
5
+ --><code>{{ JSON.stringify(json, null, ' ') }}</code><!--
6
+ --></pre>
4
7
  <slot />
5
8
  </details>
6
9
 
@@ -10,19 +13,36 @@
10
13
  <script>
11
14
 
12
15
  /**
13
- * Debug component for use by Druxt modules.
16
+ * Renders Debug data only when Nuxt is in development mode.
17
+ *
18
+ * @example @lang vue
19
+ * <DruxtDebug :json="entity" />
14
20
  */
15
21
  export default {
16
22
  /** */
17
23
  props: {
18
24
  /**
19
- * Text to display in summary.
25
+ * JSON data to format for readability.
26
+ *
27
+ * @type {*}
28
+ * @example @lang vue
29
+ * <DruxtDebug :json="{ data: [{ one: true, two: false }] }" />
30
+ */
31
+ json: {
32
+ type: [Array, Boolean, Object, Number, String],
33
+ default: undefined
34
+ },
35
+
36
+ /**
37
+ * Text to use for debug summary.
20
38
  *
21
39
  * @type {string}
40
+ * @example @lang vue
41
+ * <DruxtDebug summary="Foo bar" />
22
42
  */
23
43
  summary: {
24
44
  type: String,
25
- required: true,
45
+ default: 'Debug',
26
46
  },
27
47
  },
28
48
 
@@ -43,7 +63,9 @@ export default {
43
63
  *
44
64
  * @return {string}
45
65
  */
46
- title: ({ module, summary }) => `[${module.$options._componentTag}] ${summary}`,
66
+ title: ({ module, summary }) => module.$options._componentTag
67
+ ? `[${module.$options._componentTag}] ${summary}`
68
+ : summary,
47
69
  },
48
70
  };
49
71
  </script>
@@ -38,12 +38,25 @@ export default {
38
38
  default: null,
39
39
  },
40
40
 
41
+ /**
42
+ * The wrapper component configuration.
43
+ *
44
+ * Used to set the wrapper component, class, style and propsData.
45
+ *
46
+ * @example
47
+ * <DruxtModule
48
+ * :wrapper="{
49
+ * component: 'MyWrapper',
50
+ * class: 'wrapper',
51
+ * propsData: { foo: 'bar' }
52
+ * }"
53
+ * />
54
+ *
55
+ * @type {(Boolean|Object)}
56
+ */
41
57
  wrapper: {
42
- type: Object,
43
- default: () => ({
44
- component: 'div',
45
- propsData: {},
46
- })
58
+ type: [Boolean, Object],
59
+ default: () => undefined
47
60
  },
48
61
  },
49
62
 
@@ -92,19 +105,44 @@ export default {
92
105
  return false
93
106
  }
94
107
 
108
+ // Fetch configuration.
109
+ if ((this.$options.druxt || {}).fetchConfig) {
110
+ await this.$options.druxt.fetchConfig.call(this)
111
+ }
112
+
95
113
  // Build wrapper component object.
96
- const options = this.getModuleComponents()
114
+ let options = []
115
+ const hasDefaultTemplate = !!(this.$vnode.data.scopedSlots || {}).default
116
+ // Load wrapper components if:
117
+ if (
118
+ // No default template and wrapper isn't false OR
119
+ (!hasDefaultTemplate && this.wrapper !== false) ||
120
+ // Default tempalte and wrapper is set
121
+ (hasDefaultTemplate && this.wrapper)
122
+ ) {
123
+ options = this.getModuleComponents()
124
+ }
97
125
  let component = {
98
126
  is: (((options.filter(o => o.global) || [])[0] || {}).name || 'DruxtWrapper'),
99
127
  options: options.map(o => o.name) || [],
100
128
  }
101
129
 
102
- // Get scoped slots.
103
- component.slots = Object.keys(this.getScopedSlots())
104
-
105
130
  // Get wrapper data.
106
131
  const wrapperData = await this.getWrapperData(component.is)
132
+
133
+ // Build module settings.
107
134
  component.settings = wrapperData.druxt || {}
135
+ if ((this.$options.druxt || {}).settings) {
136
+ component.settings = this.$options.druxt.settings(this, component.settings)
137
+ }
138
+
139
+ // Fetch resource.
140
+ if ((this.$options.druxt || {}).fetchData) {
141
+ await this.$options.druxt.fetchData.call(this, component.settings)
142
+ }
143
+
144
+ // Get scoped slots.
145
+ component.slots = Object.keys(this.getScopedSlots())
108
146
 
109
147
  // Build wrapper component propsData.
110
148
  component = { ...component, ...this.getModulePropsData(wrapperData.props) }
@@ -140,12 +178,14 @@ export default {
140
178
  * @returns {Components}
141
179
  */
142
180
  getModuleComponents() {
181
+ // Ensure that the Druxt module component has `druxt.componentOptions`.
143
182
  if (!(this.$options.druxt || {}).componentOptions) {
144
183
  return []
145
184
  }
146
-
147
185
  const options = this.$options.druxt.componentOptions.call(this, this)
148
- if (!options || !options.length) {
186
+
187
+ // Ensure that there available component options are returned.
188
+ if (!(options || []).length) {
149
189
  return []
150
190
  }
151
191
 
@@ -290,20 +330,27 @@ export default {
290
330
  const self = this
291
331
 
292
332
  const wrapperData = {
293
- class: this.wrapper.class || undefined,
294
- style: this.wrapper.style || undefined,
295
- props: this.wrapper.propsData,
333
+ class: (this.wrapper || {}).class || undefined,
334
+ style: (this.wrapper || {}).style || undefined,
335
+ props: (this.wrapper || {}).propsData || undefined,
296
336
  }
297
337
 
298
338
  // Return only wrapper if fetch state is still pending.
299
- if (this.$fetchState.pending) {
300
- return h(this.wrapper.component, wrapperData)
339
+ if (this.$fetchState.pending && this.component.is === 'DruxtWrapper') {
340
+ return h((this.wrapper || {}).component || 'div', wrapperData)
301
341
  }
302
342
 
303
- // Return wrapped component.
343
+ // Prepare attributes.
304
344
  const attrs = { ...this.component.$attrs, ...this.$attrs }
305
345
  delete attrs['data-fetch-key']
306
- return h(this.wrapper.component, wrapperData, [
346
+
347
+ // Unwrap default template based component if required.
348
+ if ((this.$scopedSlots.default && !this.wrapper) || this.wrapper === false) {
349
+ this.component.is = 'DruxtWrapper'
350
+ }
351
+
352
+ // Return component.
353
+ return h((this.wrapper || {}).component || 'div', wrapperData, [
307
354
  h(this.component.is, {
308
355
  attrs,
309
356
  on: {
package/dist/druxt.esm.js CHANGED
@@ -2,17 +2,123 @@ import chalk from 'chalk';
2
2
  import { join, resolve } from 'path';
3
3
  import axios from 'axios';
4
4
  import { stringify } from 'querystring';
5
+ import consola from 'consola';
5
6
  import merge from 'deepmerge';
6
7
  import md5 from 'md5';
7
8
  import Vue from 'vue';
8
9
  import { DrupalJsonApiParams } from 'drupal-jsonapi-params';
9
10
 
11
+ var name = "druxt";
12
+ var version = "0.15.0";
13
+ var description = "The Fully Decoupled Drupal Framework for Nuxt.js.";
14
+ var keywords = [
15
+ "cms",
16
+ "decoupled",
17
+ "drupal",
18
+ "druxt",
19
+ "headless",
20
+ "jsonapi",
21
+ "json:api",
22
+ "nuxt",
23
+ "module",
24
+ "vue"
25
+ ];
26
+ var homepage = "https://druxtjs.org";
27
+ var bugs = {
28
+ url: "https://github.com/druxt/druxt.js/issues"
29
+ };
30
+ var repository = {
31
+ type: "git",
32
+ url: "git+https://github.com/druxt/druxt.js"
33
+ };
34
+ var license = "MIT";
35
+ var exports = {
36
+ ".": {
37
+ require: "./dist/druxt.ssr.js",
38
+ "import": "./dist/druxt.esm.js"
39
+ },
40
+ "./components/*": "./dist/components/*"
41
+ };
42
+ var main = "dist/druxt.ssr.js";
43
+ var module = "dist/druxt.esm.js";
44
+ var files = [
45
+ "dist",
46
+ "templates"
47
+ ];
48
+ var dependencies = {
49
+ "@nuxtjs/proxy": "^2.1.0",
50
+ axios: "^0.21.1",
51
+ chalk: "^4.1.2",
52
+ deepmerge: "^4.2.2",
53
+ "drupal-jsonapi-params": "^1.2.1",
54
+ md5: "^2.3.0",
55
+ querystring: "^0.2.0",
56
+ scule: "^0.2.0"
57
+ };
58
+ var peerDependencies = {
59
+ consola: "*"
60
+ };
61
+ var optionalDependencies = {
62
+ "core-js": "^3.16.1",
63
+ vue: "^2.6.14",
64
+ vuex: "^3.6.2"
65
+ };
66
+ var publishConfig = {
67
+ access: "public"
68
+ };
69
+ var meta = {
70
+ name: name,
71
+ version: version,
72
+ description: description,
73
+ keywords: keywords,
74
+ homepage: homepage,
75
+ bugs: bugs,
76
+ repository: repository,
77
+ license: license,
78
+ exports: exports,
79
+ main: main,
80
+ module: module,
81
+ files: files,
82
+ dependencies: dependencies,
83
+ peerDependencies: peerDependencies,
84
+ optionalDependencies: optionalDependencies,
85
+ publishConfig: publishConfig
86
+ };
87
+
10
88
  const DruxtNuxtModule = function(moduleOptions = {}) {
89
+ var _a;
11
90
  const options = {
12
91
  endpoint: "/jsonapi",
13
92
  ...moduleOptions,
14
93
  ...(this.options || {}).druxt
15
94
  };
95
+ if (options.proxy) {
96
+ const proxies = {};
97
+ if ((options.proxy || {}).api) {
98
+ proxies[options.endpoint] = options.baseUrl;
99
+ proxies["/router/translate-path"] = options.baseUrl;
100
+ }
101
+ if ((options.proxy || {}).files) {
102
+ const filesPath = typeof options.proxy.files === "string" ? options.proxy.files : "default";
103
+ proxies[`/sites/${filesPath}/files`] = options.baseUrl;
104
+ }
105
+ if (this.options.proxy) {
106
+ if (Array.isArray(this.options.proxy)) {
107
+ this.options.proxy = [
108
+ ...Object.keys(proxies).map((path) => `${options.baseUrl}${path}`),
109
+ ...this.options.proxy
110
+ ];
111
+ } else {
112
+ this.options.proxy = {
113
+ ...proxies,
114
+ ...this.options.proxy
115
+ };
116
+ }
117
+ } else {
118
+ this.options.proxy = proxies;
119
+ }
120
+ this.addModule("@nuxtjs/proxy");
121
+ }
16
122
  this.nuxt.hook("components:dirs", (dirs) => {
17
123
  dirs.push({ path: join(__dirname, "components") });
18
124
  });
@@ -27,20 +133,38 @@ const DruxtNuxtModule = function(moduleOptions = {}) {
27
133
  options
28
134
  });
29
135
  this.options.store = true;
30
- this.options.cli.badgeMessages.push(`${chalk.bold("Druxt API:")} ${chalk.blue.underline(options.baseUrl + options.endpoint)}`);
136
+ this.options.components = (_a = this.options.components) != null ? _a : true;
137
+ this.options.cli.badgeMessages.push(`${chalk.blue.bold("Druxt")} @ v${meta.version}`);
138
+ this.options.cli.badgeMessages.push(`${chalk.bold("API:")} ${chalk.blue.underline(options.baseUrl + options.endpoint)}`);
31
139
  };
32
- DruxtNuxtModule.meta = require("../package.json");
140
+ DruxtNuxtModule.meta = meta;
33
141
 
34
142
  class DruxtClient {
35
143
  constructor(baseUrl, options = {}) {
144
+ this.log = consola.create({ defaults: {
145
+ tag: "DruxtClient"
146
+ } });
36
147
  if (!baseUrl) {
37
148
  throw new Error("The 'baseUrl' parameter is required.");
38
149
  }
39
- let axiosSettings = { baseURL: baseUrl };
150
+ let axiosSettings = {};
151
+ if (baseUrl && !(options.proxy || {}).api) {
152
+ axiosSettings.baseURL = baseUrl;
153
+ }
40
154
  if (typeof options.axios === "object") {
41
155
  axiosSettings = Object.assign(axiosSettings, options.axios);
42
156
  }
43
157
  this.axios = axios.create(axiosSettings);
158
+ if (options.debug) {
159
+ const log = this.log;
160
+ this.axios.interceptors.request.use((config) => {
161
+ log.info(config.url);
162
+ return config;
163
+ }, (error) => {
164
+ log.error(error);
165
+ return Promise.reject(error);
166
+ });
167
+ }
44
168
  this.options = {
45
169
  endpoint: "/jsonapi",
46
170
  jsonapiResourceConfig: "jsonapi_resource_config--jsonapi_resource_config",
@@ -88,6 +212,26 @@ class DruxtClient {
88
212
  }
89
213
  }
90
214
  }
215
+ async createResource(resource) {
216
+ if (resource.id) {
217
+ return this.updateResource(resource);
218
+ }
219
+ const { href } = await this.getIndex(resource.type);
220
+ if (!href) {
221
+ return false;
222
+ }
223
+ let response;
224
+ try {
225
+ response = await this.axios.post(href, { data: resource }, {
226
+ headers: {
227
+ "Content-Type": "application/vnd.api+json"
228
+ }
229
+ });
230
+ } catch (err) {
231
+ response = (err.response || {}).data || err.message;
232
+ }
233
+ return response;
234
+ }
91
235
  async getCollection(type, query) {
92
236
  const { href } = await this.getIndex(type);
93
237
  if (!href) {
@@ -116,10 +260,14 @@ class DruxtClient {
116
260
  if (this.index && resource) {
117
261
  return this.index[resource] ? this.index[resource] : false;
118
262
  }
119
- const index = await this.axios.get(this.options.endpoint);
120
- this.index = index.data.links;
121
- if (this.index[this.options.jsonapiResourceConfig]) {
122
- const resources = await this.axios.get(this.index[this.options.jsonapiResourceConfig].href);
263
+ let index = ((await this.axios.get(this.options.endpoint) || {}).data || {}).links;
264
+ const baseUrl = this.options.baseUrl;
265
+ index = Object.fromEntries(Object.entries(index).map(([key, value]) => {
266
+ value.href = value.href.replace(baseUrl, "");
267
+ return [key, value];
268
+ }));
269
+ if (index[this.options.jsonapiResourceConfig]) {
270
+ const resources = await this.axios.get(index[this.options.jsonapiResourceConfig].href);
123
271
  for (const resourceType in resources.data.data) {
124
272
  const resource2 = resources.data.data[resourceType];
125
273
  const internal = resource2.attributes.drupal_internal__id.split("--");
@@ -130,17 +278,35 @@ class DruxtClient {
130
278
  resourceFields: resource2.attributes.resourceFields
131
279
  };
132
280
  const id = [item.entityType, item.bundle].join("--");
133
- this.index[id] = {
281
+ index[id] = {
134
282
  ...item,
135
- ...this.index[id]
283
+ ...index[id]
136
284
  };
137
285
  }
138
286
  }
287
+ this.index = index;
139
288
  if (resource) {
140
- return this.index[resource] ? this.index[resource] : false;
289
+ const response = this.index[resource] ? this.index[resource] : false;
290
+ return response;
141
291
  }
142
292
  return this.index;
143
293
  }
294
+ async getRelated(type, id, related, query) {
295
+ if (!id || !type || !related) {
296
+ return false;
297
+ }
298
+ let { href } = await this.getIndex(type);
299
+ if (!href) {
300
+ href = this.options.endpoint + "/" + type.replace("--", "/");
301
+ }
302
+ const url = this.buildQueryUrl(`${href}/${id}/${related}`, query);
303
+ try {
304
+ const related2 = await this.axios.get(url);
305
+ return related2.data;
306
+ } catch (e) {
307
+ return false;
308
+ }
309
+ }
144
310
  async getResource(type, id, query) {
145
311
  if (!id || !type) {
146
312
  return false;
@@ -157,6 +323,24 @@ class DruxtClient {
157
323
  return false;
158
324
  }
159
325
  }
326
+ async updateResource(resource) {
327
+ const { href } = await this.getIndex(resource.type);
328
+ if (!href) {
329
+ return false;
330
+ }
331
+ const url = [href, resource.id].join("/");
332
+ let response;
333
+ try {
334
+ response = await this.axios.patch(url, { data: resource }, {
335
+ headers: {
336
+ "Content-Type": "application/vnd.api+json"
337
+ }
338
+ });
339
+ } catch (err) {
340
+ response = (err.response || {}).data || err.message;
341
+ }
342
+ return response;
343
+ }
160
344
  }
161
345
 
162
346
  const getDrupalJsonApiParams = (query) => {
package/dist/druxt.ssr.js CHANGED
@@ -6,6 +6,7 @@ const chalk = require('chalk');
6
6
  const path = require('path');
7
7
  const axios = require('axios');
8
8
  const querystring = require('querystring');
9
+ const consola = require('consola');
9
10
  const merge = require('deepmerge');
10
11
  const md5 = require('md5');
11
12
  const Vue = require('vue');
@@ -15,16 +16,122 @@ function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'defau
15
16
 
16
17
  const chalk__default = /*#__PURE__*/_interopDefaultLegacy(chalk);
17
18
  const axios__default = /*#__PURE__*/_interopDefaultLegacy(axios);
19
+ const consola__default = /*#__PURE__*/_interopDefaultLegacy(consola);
18
20
  const merge__default = /*#__PURE__*/_interopDefaultLegacy(merge);
19
21
  const md5__default = /*#__PURE__*/_interopDefaultLegacy(md5);
20
22
  const Vue__default = /*#__PURE__*/_interopDefaultLegacy(Vue);
21
23
 
24
+ var name = "druxt";
25
+ var version = "0.15.0";
26
+ var description = "The Fully Decoupled Drupal Framework for Nuxt.js.";
27
+ var keywords = [
28
+ "cms",
29
+ "decoupled",
30
+ "drupal",
31
+ "druxt",
32
+ "headless",
33
+ "jsonapi",
34
+ "json:api",
35
+ "nuxt",
36
+ "module",
37
+ "vue"
38
+ ];
39
+ var homepage = "https://druxtjs.org";
40
+ var bugs = {
41
+ url: "https://github.com/druxt/druxt.js/issues"
42
+ };
43
+ var repository = {
44
+ type: "git",
45
+ url: "git+https://github.com/druxt/druxt.js"
46
+ };
47
+ var license = "MIT";
48
+ var exports$1 = {
49
+ ".": {
50
+ require: "./dist/druxt.ssr.js",
51
+ "import": "./dist/druxt.esm.js"
52
+ },
53
+ "./components/*": "./dist/components/*"
54
+ };
55
+ var main = "dist/druxt.ssr.js";
56
+ var module$1 = "dist/druxt.esm.js";
57
+ var files = [
58
+ "dist",
59
+ "templates"
60
+ ];
61
+ var dependencies = {
62
+ "@nuxtjs/proxy": "^2.1.0",
63
+ axios: "^0.21.1",
64
+ chalk: "^4.1.2",
65
+ deepmerge: "^4.2.2",
66
+ "drupal-jsonapi-params": "^1.2.1",
67
+ md5: "^2.3.0",
68
+ querystring: "^0.2.0",
69
+ scule: "^0.2.0"
70
+ };
71
+ var peerDependencies = {
72
+ consola: "*"
73
+ };
74
+ var optionalDependencies = {
75
+ "core-js": "^3.16.1",
76
+ vue: "^2.6.14",
77
+ vuex: "^3.6.2"
78
+ };
79
+ var publishConfig = {
80
+ access: "public"
81
+ };
82
+ const meta = {
83
+ name: name,
84
+ version: version,
85
+ description: description,
86
+ keywords: keywords,
87
+ homepage: homepage,
88
+ bugs: bugs,
89
+ repository: repository,
90
+ license: license,
91
+ exports: exports$1,
92
+ main: main,
93
+ module: module$1,
94
+ files: files,
95
+ dependencies: dependencies,
96
+ peerDependencies: peerDependencies,
97
+ optionalDependencies: optionalDependencies,
98
+ publishConfig: publishConfig
99
+ };
100
+
22
101
  const DruxtNuxtModule = function(moduleOptions = {}) {
102
+ var _a;
23
103
  const options = {
24
104
  endpoint: "/jsonapi",
25
105
  ...moduleOptions,
26
106
  ...(this.options || {}).druxt
27
107
  };
108
+ if (options.proxy) {
109
+ const proxies = {};
110
+ if ((options.proxy || {}).api) {
111
+ proxies[options.endpoint] = options.baseUrl;
112
+ proxies["/router/translate-path"] = options.baseUrl;
113
+ }
114
+ if ((options.proxy || {}).files) {
115
+ const filesPath = typeof options.proxy.files === "string" ? options.proxy.files : "default";
116
+ proxies[`/sites/${filesPath}/files`] = options.baseUrl;
117
+ }
118
+ if (this.options.proxy) {
119
+ if (Array.isArray(this.options.proxy)) {
120
+ this.options.proxy = [
121
+ ...Object.keys(proxies).map((path) => `${options.baseUrl}${path}`),
122
+ ...this.options.proxy
123
+ ];
124
+ } else {
125
+ this.options.proxy = {
126
+ ...proxies,
127
+ ...this.options.proxy
128
+ };
129
+ }
130
+ } else {
131
+ this.options.proxy = proxies;
132
+ }
133
+ this.addModule("@nuxtjs/proxy");
134
+ }
28
135
  this.nuxt.hook("components:dirs", (dirs) => {
29
136
  dirs.push({ path: path.join(__dirname, "components") });
30
137
  });
@@ -39,20 +146,38 @@ const DruxtNuxtModule = function(moduleOptions = {}) {
39
146
  options
40
147
  });
41
148
  this.options.store = true;
42
- this.options.cli.badgeMessages.push(`${chalk__default['default'].bold("Druxt API:")} ${chalk__default['default'].blue.underline(options.baseUrl + options.endpoint)}`);
149
+ this.options.components = (_a = this.options.components) != null ? _a : true;
150
+ this.options.cli.badgeMessages.push(`${chalk__default['default'].blue.bold("Druxt")} @ v${meta.version}`);
151
+ this.options.cli.badgeMessages.push(`${chalk__default['default'].bold("API:")} ${chalk__default['default'].blue.underline(options.baseUrl + options.endpoint)}`);
43
152
  };
44
- DruxtNuxtModule.meta = require("../package.json");
153
+ DruxtNuxtModule.meta = meta;
45
154
 
46
155
  class DruxtClient {
47
156
  constructor(baseUrl, options = {}) {
157
+ this.log = consola__default['default'].create({ defaults: {
158
+ tag: "DruxtClient"
159
+ } });
48
160
  if (!baseUrl) {
49
161
  throw new Error("The 'baseUrl' parameter is required.");
50
162
  }
51
- let axiosSettings = { baseURL: baseUrl };
163
+ let axiosSettings = {};
164
+ if (baseUrl && !(options.proxy || {}).api) {
165
+ axiosSettings.baseURL = baseUrl;
166
+ }
52
167
  if (typeof options.axios === "object") {
53
168
  axiosSettings = Object.assign(axiosSettings, options.axios);
54
169
  }
55
170
  this.axios = axios__default['default'].create(axiosSettings);
171
+ if (options.debug) {
172
+ const log = this.log;
173
+ this.axios.interceptors.request.use((config) => {
174
+ log.info(config.url);
175
+ return config;
176
+ }, (error) => {
177
+ log.error(error);
178
+ return Promise.reject(error);
179
+ });
180
+ }
56
181
  this.options = {
57
182
  endpoint: "/jsonapi",
58
183
  jsonapiResourceConfig: "jsonapi_resource_config--jsonapi_resource_config",
@@ -100,6 +225,26 @@ class DruxtClient {
100
225
  }
101
226
  }
102
227
  }
228
+ async createResource(resource) {
229
+ if (resource.id) {
230
+ return this.updateResource(resource);
231
+ }
232
+ const { href } = await this.getIndex(resource.type);
233
+ if (!href) {
234
+ return false;
235
+ }
236
+ let response;
237
+ try {
238
+ response = await this.axios.post(href, { data: resource }, {
239
+ headers: {
240
+ "Content-Type": "application/vnd.api+json"
241
+ }
242
+ });
243
+ } catch (err) {
244
+ response = (err.response || {}).data || err.message;
245
+ }
246
+ return response;
247
+ }
103
248
  async getCollection(type, query) {
104
249
  const { href } = await this.getIndex(type);
105
250
  if (!href) {
@@ -128,10 +273,14 @@ class DruxtClient {
128
273
  if (this.index && resource) {
129
274
  return this.index[resource] ? this.index[resource] : false;
130
275
  }
131
- const index = await this.axios.get(this.options.endpoint);
132
- this.index = index.data.links;
133
- if (this.index[this.options.jsonapiResourceConfig]) {
134
- const resources = await this.axios.get(this.index[this.options.jsonapiResourceConfig].href);
276
+ let index = ((await this.axios.get(this.options.endpoint) || {}).data || {}).links;
277
+ const baseUrl = this.options.baseUrl;
278
+ index = Object.fromEntries(Object.entries(index).map(([key, value]) => {
279
+ value.href = value.href.replace(baseUrl, "");
280
+ return [key, value];
281
+ }));
282
+ if (index[this.options.jsonapiResourceConfig]) {
283
+ const resources = await this.axios.get(index[this.options.jsonapiResourceConfig].href);
135
284
  for (const resourceType in resources.data.data) {
136
285
  const resource2 = resources.data.data[resourceType];
137
286
  const internal = resource2.attributes.drupal_internal__id.split("--");
@@ -142,17 +291,35 @@ class DruxtClient {
142
291
  resourceFields: resource2.attributes.resourceFields
143
292
  };
144
293
  const id = [item.entityType, item.bundle].join("--");
145
- this.index[id] = {
294
+ index[id] = {
146
295
  ...item,
147
- ...this.index[id]
296
+ ...index[id]
148
297
  };
149
298
  }
150
299
  }
300
+ this.index = index;
151
301
  if (resource) {
152
- return this.index[resource] ? this.index[resource] : false;
302
+ const response = this.index[resource] ? this.index[resource] : false;
303
+ return response;
153
304
  }
154
305
  return this.index;
155
306
  }
307
+ async getRelated(type, id, related, query) {
308
+ if (!id || !type || !related) {
309
+ return false;
310
+ }
311
+ let { href } = await this.getIndex(type);
312
+ if (!href) {
313
+ href = this.options.endpoint + "/" + type.replace("--", "/");
314
+ }
315
+ const url = this.buildQueryUrl(`${href}/${id}/${related}`, query);
316
+ try {
317
+ const related2 = await this.axios.get(url);
318
+ return related2.data;
319
+ } catch (e) {
320
+ return false;
321
+ }
322
+ }
156
323
  async getResource(type, id, query) {
157
324
  if (!id || !type) {
158
325
  return false;
@@ -169,6 +336,24 @@ class DruxtClient {
169
336
  return false;
170
337
  }
171
338
  }
339
+ async updateResource(resource) {
340
+ const { href } = await this.getIndex(resource.type);
341
+ if (!href) {
342
+ return false;
343
+ }
344
+ const url = [href, resource.id].join("/");
345
+ let response;
346
+ try {
347
+ response = await this.axios.patch(url, { data: resource }, {
348
+ headers: {
349
+ "Content-Type": "application/vnd.api+json"
350
+ }
351
+ });
352
+ } catch (err) {
353
+ response = (err.response || {}).data || err.message;
354
+ }
355
+ return response;
356
+ }
172
357
  }
173
358
 
174
359
  const getDrupalJsonApiParams = (query) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "druxt",
3
- "version": "0.11.0",
3
+ "version": "0.15.0",
4
4
  "description": "The Fully Decoupled Drupal Framework for Nuxt.js.",
5
5
  "keywords": [
6
6
  "cms",
@@ -37,6 +37,7 @@
37
37
  "templates"
38
38
  ],
39
39
  "dependencies": {
40
+ "@nuxtjs/proxy": "^2.1.0",
40
41
  "axios": "^0.21.1",
41
42
  "chalk": "^4.1.2",
42
43
  "deepmerge": "^4.2.2",
@@ -45,6 +46,9 @@
45
46
  "querystring": "^0.2.0",
46
47
  "scule": "^0.2.0"
47
48
  },
49
+ "peerDependencies": {
50
+ "consola": "*"
51
+ },
48
52
  "optionalDependencies": {
49
53
  "core-js": "^3.16.1",
50
54
  "vue": "^2.6.14",
@@ -1,7 +1,12 @@
1
1
  import { DruxtClient } from 'druxt'
2
2
 
3
3
  export default (context, inject) => {
4
- const options = <%= devalue(options) %>
4
+ const options = <%= JSON.stringify(options) %>
5
+
6
+ // Disable the proxy for server side requests.
7
+ if (!process.client && (options.proxy || {}).api) {
8
+ options.proxy.api = false
9
+ }
5
10
 
6
11
  const druxt = new DruxtClient(options.baseUrl, options)
7
12
  druxt.settings = options