diff --git a/packages/blocks/package.json b/packages/blocks/package.json index df8edc4c5..d3338adba 100644 --- a/packages/blocks/package.json +++ b/packages/blocks/package.json @@ -33,15 +33,18 @@ "require": "./dist/druxt-blocks.ssr.js", "import": "./dist/druxt-blocks.esm.js" }, - "./components/*": "./dist/components/*" + "./components/*": "./dist/components/*", + "./nuxt/*": "./nuxt/*" }, "main": "dist/druxt-blocks.ssr.js", "module": "dist/druxt-blocks.esm.js", "files": [ "dist", + "nuxt", "templates" ], "dependencies": { + "@nuxt/kit": "^3.12.4", "axios": "0.27.2", "drupal-jsonapi-params": "^2.2.0", "druxt": "^0.22.0", diff --git a/packages/blocks/src/components/DruxtBlock.vue b/packages/blocks/src/components/DruxtBlock.vue index 7eb55279a..a182204b8 100644 --- a/packages/blocks/src/components/DruxtBlock.vue +++ b/packages/blocks/src/components/DruxtBlock.vue @@ -93,7 +93,7 @@ export default { * * @return {object} */ - block: ({ resource }) => (resource || {}).data, + block: ({ resource }) => resource?.data, }, watch: { @@ -156,7 +156,7 @@ export default { const type = 'block--block' const query = new DrupalJsonApiParams() - const fields = ((this.$druxt.settings.blocks || {}).query || {}).fields + const fields = this.$druxt?.settings.blocks?.query?.fields if (Array.isArray(fields)) { query.addFields(type, [ ...fields, @@ -214,10 +214,10 @@ export default { scopedSlots.default = () => { let summary, description - if ((this.block || {}).attributes) { + if (this.block?.attributes) { summary = `Missing Vue template for the '${this.block.attributes.drupal_internal__id}' block` description = [ - h('p', `Create a Druxt theme component to render the "${this.block.attributes.settings.label}" block.`), + h('p', `Create a Druxt theme component to render the "${this.block.attributes?.settings?.label}" block.`), ] // Ensure an ID or UUID. } else if (!this.id && !this.uuid) { @@ -229,7 +229,7 @@ export default { { props: { summary } }, [ h('div', description), - !!this.component.options.length && h('DruxtDevelTemplate', { props: { options: this.component.options }}), + !!this.component.options?.length && h('DruxtDevelTemplate', { props: { options: this.component.options }}), !!this.block && h('details', [h('summary', 'JSON:API resource'), h('pre', [h('code', [JSON.stringify(this.block, null, ' ')])])]) ] ) diff --git a/packages/blocks/src/components/DruxtBlockRegion.vue b/packages/blocks/src/components/DruxtBlockRegion.vue index e70d78349..3d8629b41 100644 --- a/packages/blocks/src/components/DruxtBlockRegion.vue +++ b/packages/blocks/src/components/DruxtBlockRegion.vue @@ -172,7 +172,7 @@ export default { type, query }) - this.blocks = collection.data + this.blocks = collection?.data }, /** @@ -207,7 +207,7 @@ export default { slots(h) { // Build scoped slots for each block. const scopedSlots = {} - this.blocks.map((block) => { + this.blocks?.map((block) => { scopedSlots[block.attributes.drupal_internal__id] = (attrs) => { delete (attrs || {})['data-fetch-key'] return h('DruxtBlock', { @@ -223,7 +223,7 @@ export default { }) // Build default slot. - scopedSlots.default = (attrs) => h('div', this.blocks.map((block) => + scopedSlots.default = (attrs) => h('div', this.blocks?.map((block) => this.isVisible(block) ? scopedSlots[block.attributes.drupal_internal__id](attrs) : false diff --git a/packages/blocks/src/index.js b/packages/blocks/src/index.js index 09f76b1eb..de7672aa1 100644 --- a/packages/blocks/src/index.js +++ b/packages/blocks/src/index.js @@ -1,27 +1,3 @@ -import { DruxtBlocksNuxtModule } from './nuxtModule' - -/** - * The Nuxt.js module function. - * - * Installs the module functionality in a Nuxt application. - * - * @type {Function} - * @exports default - * @name DruxtBlocksModule - * @see {@link /api/packages/blocks/nuxtModule|DruxtBlocksModule} - * - * @example nuxt.config.js @lang js - * module.exports = { - * modules: [ - * 'druxt-blocks' - * ], - * druxt: { - * baseUrl: 'https://demo-api.druxtjs.org' - * } - * } - */ -export default DruxtBlocksNuxtModule - /** * The DruxtBlocksBlockMixin adds props and computed props to your DruxtBlock * wrapper component. diff --git a/packages/blocks/src/nuxt/index.js b/packages/blocks/src/nuxt/index.js new file mode 100644 index 000000000..cfc2bcf22 --- /dev/null +++ b/packages/blocks/src/nuxt/index.js @@ -0,0 +1,73 @@ +import { defineNuxtModule, installModule } from '@nuxt/kit' +import { join } from 'path' +// import DruxtBlocksStorybook from './storybook' + +/** + * The Nuxt.js module function. + * + * - Adds the Vue.js components to the Nuxt.js frontend. + * + * The module function should not be used directly, but rather installed via yout Nuxt.js configuration file. + * + * Options are set on the root level `druxt` Nuxt.js config object. + * + * @example @lang js + * // `nuxt.config.js` + * module.exports = { + * modules: [ + * 'druxt-blocks' + * ], + * druxt: { + * baseUrl: 'https://demo-api.druxtjs.org' + * } + * } + * + * @param {object} moduleOptions - Nuxt.js module options object. + */ +const DruxtBlocksNuxtModule = defineNuxtModule({ + meta: { + name: 'druxt-blocks' + }, + defaults: { + baseUrl: '', + endpoint: '/jsonapi', + }, + + async setup(moduleOptions, nuxt) { + // Prevent issue "FATAL: Cannot determine nuxt version! Is current + // instance passed?". + nuxt._version = nuxt._version || '2.' + // This is required to prevent "FATAL: nuxt.options._layers is not iterable" + // error when using `installModule()`. + nuxt.options._layers = nuxt.options._layers || [] + + // Set default options. + const options = { + baseUrl: moduleOptions.baseUrl, + ...nuxt.options?.druxt || {}, + blocks: { + query: {}, + ...nuxt.options?.druxt?.blocks, + ...moduleOptions, + } + } + + // Add Druxt module. + await installModule('druxt', options, nuxt) + + // Register components directories. + nuxt.hook('components:dirs', dirs => { + dirs.push({ path: join(__dirname, '../dist/components') }) + dirs.push({ path: join(__dirname, '../dist/components/blocks') }) + }) + + // Nuxt Storybook. + // @TODO - @nuxt/kit and @nuxt/storybook aren't compatible. + // nuxt.hook('storybook:config', async ({ stories }) => { + // await DruxtBlocksStorybook.call(nuxt, { stories }) + // }) + } +}) + +export default DruxtBlocksNuxtModule + diff --git a/packages/blocks/src/nuxtStorybook.js b/packages/blocks/src/nuxt/storybook.js similarity index 97% rename from packages/blocks/src/nuxtStorybook.js rename to packages/blocks/src/nuxt/storybook.js index 4b0e1a23b..2cfd94e2f 100644 --- a/packages/blocks/src/nuxtStorybook.js +++ b/packages/blocks/src/nuxt/storybook.js @@ -1,3 +1,4 @@ +import { addTemplate } from '@nuxt/kit' import { resolve } from 'path' import { DrupalJsonApiParams } from 'drupal-jsonapi-params' import { DruxtClient } from 'druxt' @@ -8,7 +9,7 @@ const titleFn = (parts) => ).join('/') export default async function ({ stories }) { - const { addTemplate, options } = this + const { options } = this // Setup DruxtClient instance. const druxt = new DruxtClient(options.druxt.baseUrl, { ...options.druxt, proxy: { api: false } }) diff --git a/packages/blocks/src/nuxtModule.js b/packages/blocks/src/nuxtModule.js deleted file mode 100644 index f39000923..000000000 --- a/packages/blocks/src/nuxtModule.js +++ /dev/null @@ -1,55 +0,0 @@ -import { join } from 'path' -import DruxtBlocksStorybook from './nuxtStorybook' - -/** - * The Nuxt.js module function. - * - * - Adds the Vue.js components to the Nuxt.js frontend. - * - * The module function should not be used directly, but rather installed via yout Nuxt.js configuration file. - * - * Options are set on the root level `druxt` Nuxt.js config object. - * - * @example @lang js - * // `nuxt.config.js` - * module.exports = { - * modules: [ - * 'druxt-blocks' - * ], - * druxt: { - * baseUrl: 'https://demo-api.druxtjs.org' - * } - * } - * - * @param {object} moduleOptions - Nuxt.js module options object. - */ -const DruxtBlocksNuxtModule = async function (moduleOptions = {}) { - // Set default options. - const options = { - baseUrl: moduleOptions.baseUrl, - ...(this.options || {}).druxt || {}, - blocks: { - query: {}, - ...((this.options || {}).druxt || {}).site, - ...moduleOptions, - } - } - - // Add Druxt module. - await this.addModule(['druxt', options]) - - // Register components directories. - this.nuxt.hook('components:dirs', dirs => { - dirs.push({ path: join(__dirname, 'components') }) - dirs.push({ path: join(__dirname, 'components/blocks') }) - }) - - // Nuxt Storybook. - this.nuxt.hook('storybook:config', async ({ stories }) => { - await DruxtBlocksStorybook.call(this, { stories }) - }) -} - -DruxtBlocksNuxtModule.meta = require('../package.json') - -export { DruxtBlocksNuxtModule }