From 2fb7a417dbebc379ca65951b028cfb3c69fa020b Mon Sep 17 00:00:00 2001 From: jeffloop Date: Fri, 9 Sep 2022 09:39:30 -0700 Subject: [PATCH 1/3] fix: children of imageFile missing on build --- .gitignore | 1 + gatsby-node.js | 452 +++++++++++++++++++++++++------------------------ 2 files changed, 233 insertions(+), 220 deletions(-) diff --git a/.gitignore b/.gitignore index 6423b8b..b5bbbe7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ .DS_Store node_modules .vscode +yarn.lock diff --git a/gatsby-node.js b/gatsby-node.js index dbfa74e..c9da386 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -8,256 +8,268 @@ const { createRemoteFileNode } = require('gatsby-source-filesystem'); * Validate plugin options */ exports.pluginOptionsSchema = ({ Joi }) => { - return Joi.object().keys({ - url: Joi.string().required(), - auth: Joi.object() - .keys({ - token: Joi.string(), - email: Joi.string(), - password: Joi.string(), - }) - .with('email', 'password') - .with('password', 'email') - .xor('token', 'email'), - type: Joi.object() - .keys({ - name: Joi.string(), - field: Joi.string(), - }) - .optional(), - dev: Joi.object().keys({ - refresh: [Joi.number(), Joi.string()], - }), - graphql: Joi.object(), - }); + return Joi.object().keys({ + url: Joi.string().required(), + auth: Joi.object() + .keys({ + token: Joi.string(), + email: Joi.string(), + password: Joi.string(), + }) + .with('email', 'password') + .with('password', 'email') + .xor('token', 'email'), + type: Joi.object() + .keys({ + name: Joi.string(), + field: Joi.string(), + }) + .optional(), + dev: Joi.object().keys({ + refresh: [Joi.number(), Joi.string()], + }), + graphql: Joi.object(), + }); }; /** * Gatsby source implementation. */ -exports.sourceNodes = async (gatsbyOptions, pluginOptions) => { - await plugin.setOptions(pluginOptions); - - const optionsSystem = plugin.getOptionsSystem(); - const options = plugin.getOptions(); - - const createNode = gatsbyOptions.actions.createNode; - // Avoid type conflict with gatsby-source-graphql - gatsbyOptions.actions.createNode = (node) => { - if (node.internal.type === 'GraphQLSource') { - if (node.typeName === optionsSystem.typeName) node.internal.type = 'DirectusSystemGraphQLSource'; - if (node.typeName === options.typeName) node.internal.type = 'DirectusGraphQLSource'; - } - - return createNode(node); - }; - - await sourceNodes(gatsbyOptions, optionsSystem); - await sourceNodes(gatsbyOptions, options); +exports.sourceNodes = async (gatsbyOptions, pluginOptions) => { + const { actions: { createNode }, createNodeId, store, cache, reporter } = gatsbyOptions + const { headers } = await plugin.getOptions(); + const { Authorization } = await headers(); + + await plugin.setOptions(pluginOptions); + + const optionsSystem = plugin.getOptionsSystem(); + const options = plugin.getOptions(); + + // Avoid type conflict with gatsby-source-graphql + gatsbyOptions.actions.createNode = (node) => { + if (node.internal.type === 'GraphQLSource') { + if (node.typeName === optionsSystem.typeName) node.internal.type = 'DirectusSystemGraphQLSource'; + if (node.typeName === options.typeName) node.internal.type = 'DirectusGraphQLSource'; + } + + return createNode(node); + }; + + await sourceNodes(gatsbyOptions, optionsSystem); + await sourceNodes(gatsbyOptions, options); + + // Load images here rather than on file resolution. + // Create a node for each image and store it in the cache + // so it can bre retrieved on file resolution. + const remoteImages = await plugin.getAllImages(); + remoteImages.forEach(async (image) => { + const cachedImage = await cache.get(image.id) + if (cachedImage !== undefined) { + return + } + const nameParts = image.filename_download.split('.'); + const ext = nameParts.length > 1 ? `.${nameParts.pop()}` : ''; + const name = nameParts.join('.'); + const imageUrl = `${plugin.url}assets/${image.id}`; + const img = await createRemoteFileNode({ + url: imageUrl, + parentNodeId: image.id, + store, + cache, + createNode, + createNodeId, + httpHeaders: { Authorization }, + reporter, + ext, + name, + }); + await cache.set(image.id, img); + }) }; exports.createSchemaCustomization = async (gatsby, pluginOptions) => { - await plugin.setOptions(pluginOptions); + await plugin.setOptions(pluginOptions); - await createSchemaCustomization(gatsby, plugin.getOptionsSystem()); - await createSchemaCustomization(gatsby, plugin.getOptions()); + await createSchemaCustomization(gatsby, plugin.getOptionsSystem()); + await createSchemaCustomization(gatsby, plugin.getOptions()); }; /** * Gatsby file implementation. */ -exports.createResolvers = async ({ actions, cache, createNodeId, createResolvers, store, reporter }, pluginOptions) => { - await plugin.setOptions(pluginOptions); - - const { createNode } = actions; - - const { headers } = await plugin.getOptions(); - const { Authorization } = await headers(); - - const fileResolver = { - imageFile: { - type: `File`, - async resolve(source) { - if (!source || !source.id) return null; - - let filename_download = plugin.fileCache.get(source.id); - - if (!filename_download) { - if (source.filename_download) filename_download = source.filename_download; - else ({ filename_download } = await plugin.directus.files.readOne(source.id)); - - plugin.fileCache.set(source.id, filename_download); - } - - const nameParts = filename_download.split('.'); - const ext = nameParts.length > 1 ? `.${nameParts.pop()}` : ''; - const name = nameParts.join('.'); - - return createRemoteFileNode({ - url: `${plugin.url}assets/${source.id}`, - store, - cache, - createNode, - createNodeId, - httpHeaders: { Authorization }, - reporter, - ext, - name, - }); - }, - }, - }; - - await createResolvers({ - DirectusData_directus_files: fileResolver, - DirectusSystemData_directus_files: fileResolver, - }); +exports.createResolvers = async ({ cache, createResolvers }, pluginOptions) => { + await plugin.setOptions(pluginOptions); + + const fileResolver = { + imageFile: { + type: `File`, + async resolve (source) { + // Lookup the cached image node and return it + const cachedFile = await cache.get(source.id); + return cachedFile; + }, + }, + }; + + await createResolvers({ + DirectusData_directus_files: fileResolver, + DirectusSystemData_directus_files: fileResolver, + }); }; class Plugin { - constructor() { - // eslint-disable-next-line no-undef - this.fileCache = new Map(); - this.directus = null; - this.options = null; - this.urlGraphqlSystem = ''; - this.urlGraphql = ''; - this.url = ''; - this.refreshInterval = 0; - this.authPromise = null; - } - - async setOptions(options) { - const { url, dev, auth } = options; - - if (isEmpty(url)) error('"url" must be defined'); - - if (this.directus) return this.authPromise; - - const hasAuth = !!auth; - const hasToken = !isEmpty(auth?.token); - const hasEmail = !isEmpty(auth?.email); - const hasPassword = !isEmpty(auth?.password); - const hasCredentials = hasEmail && hasPassword; - - if (hasAuth) { - if (!hasToken && !hasCredentials) error('"auth.token" or ("auth.email" and "auth.password") must be defined'); - } else warning('no "auth" option were defined. Resources will be fetched with public role'); - - try { - const baseUrl = new URL(url); - - baseUrl.pathname = '/'; - this.url = baseUrl.toString(); - - baseUrl.pathname = '/graphql'; - this.urlGraphql = baseUrl.toString(); - - baseUrl.pathname = '/graphql/system'; - this.urlGraphqlSystem = baseUrl.toString(); - } catch (err) { - error('"url" should be a valid URL'); - } - - try { - this.directus = new Directus(this.url); - - if (hasToken) this.authPromise = await this.directus.auth.static(auth.token); - - if (hasCredentials) - this.authPromise = await this.directus.auth.login({ email: auth?.email, password: auth?.password }); - } catch (err) { - error(`authentication failed with: ${err.message}\nAre credentials valid?`); - } - - this.refreshInterval = typeof dev?.refresh === 'string' ? ms(dev.refresh) / 1000 : dev?.refresh || 15; - - if (Number.isNaN(this.refreshInterval)) - error('"dev.refresh" should be a number in seconds or a string with ms format, i.e. 5s, 5m, 5h, ...'); - - this.options = options; - - return this.authPromise; - } - - getOptions() { - const internalOptions = ['url', 'dev', 'auth', 'type']; - const gatsbyPluginOptions = Object.fromEntries( - Object.entries(this.options).flatMap(([key, value]) => (internalOptions.includes(key) ? [] : [[key, value]])) - ); - - return { - ...this.options.graphql, - ...gatsbyPluginOptions, - url: this.urlGraphql, - typeName: this.options?.type?.name || 'DirectusData', - fieldName: this.options?.type?.field || 'directus', - headers: this.headers.bind(this), - }; - } - - getOptionsSystem() { - const options = this.getOptions(); - - return { - ...options, - url: this.urlGraphqlSystem, - typeName: this.options?.type?.system_name || 'DirectusSystemData', - fieldName: this.options?.type?.system_field || 'directus_system', - }; - } - - async headers() { - let headers = {}; - if (typeof this.options?.headers === 'object') { - Object.assign(headers, this.options.headers || {}); - } else if (typeof this.options?.headers === 'function') { - Object.assign(headers, (await this.options.headers()) || {}); - } - - if (this.directus.auth.token) { - Object.assign(headers, { - Authorization: `Bearer ${this.directus.auth.token}`, - }); - } - - return headers; - } + constructor() { + // eslint-disable-next-line no-undef + this.fileCache = new Map(); + this.directus = null; + this.options = null; + this.urlGraphqlSystem = ''; + this.urlGraphql = ''; + this.url = ''; + this.refreshInterval = 0; + this.authPromise = null; + } + + async setOptions (options) { + const { url, dev, auth } = options; + + if (isEmpty(url)) error('"url" must be defined'); + + if (this.directus) return this.authPromise; + + const hasAuth = !!auth; + const hasToken = !isEmpty(auth?.token); + const hasEmail = !isEmpty(auth?.email); + const hasPassword = !isEmpty(auth?.password); + const hasCredentials = hasEmail && hasPassword; + + if (hasAuth) { + if (!hasToken && !hasCredentials) error('"auth.token" or ("auth.email" and "auth.password") must be defined'); + } else warning('no "auth" option were defined. Resources will be fetched with public role'); + + try { + const baseUrl = new URL(url); + + baseUrl.pathname = '/'; + this.url = baseUrl.toString(); + + baseUrl.pathname = '/graphql'; + this.urlGraphql = baseUrl.toString(); + + baseUrl.pathname = '/graphql/system'; + this.urlGraphqlSystem = baseUrl.toString(); + } catch (err) { + error('"url" should be a valid URL'); + } + + try { + this.directus = new Directus(this.url); + + if (hasToken) this.authPromise = await this.directus.auth.static(auth.token); + + if (hasCredentials) + this.authPromise = await this.directus.auth.login({ email: auth?.email, password: auth?.password }); + } catch (err) { + error(`authentication failed with: ${err.message}\nAre credentials valid?`); + } + + this.refreshInterval = typeof dev?.refresh === 'string' ? ms(dev.refresh) / 1000 : dev?.refresh || 15; + + if (Number.isNaN(this.refreshInterval)) + error('"dev.refresh" should be a number in seconds or a string with ms format, i.e. 5s, 5m, 5h, ...'); + + this.options = options; + + return this.authPromise; + } + + getOptions () { + const internalOptions = ['url', 'dev', 'auth', 'type']; + const gatsbyPluginOptions = Object.fromEntries( + Object.entries(this.options).flatMap(([key, value]) => (internalOptions.includes(key) ? [] : [[key, value]])) + ); + + return { + ...this.options.graphql, + ...gatsbyPluginOptions, + url: this.urlGraphql, + typeName: this.options?.type?.name || 'DirectusData', + fieldName: this.options?.type?.field || 'directus', + headers: this.headers.bind(this), + }; + } + + getOptionsSystem () { + const options = this.getOptions(); + + return { + ...options, + url: this.urlGraphqlSystem, + typeName: this.options?.type?.system_name || 'DirectusSystemData', + fieldName: this.options?.type?.system_field || 'directus_system', + }; + } + + /** + * Method to retrieve all of the images in directus.files + */ + async getAllImages () { + const files = await this.directus.files.readByQuery({ limit: -1 }); + const imageFiles = files.data.filter(file => file.type.indexOf('image') > -1); + return imageFiles; + } + + async headers () { + let headers = {}; + if (typeof this.options?.headers === 'object') { + Object.assign(headers, this.options.headers || {}); + } else if (typeof this.options?.headers === 'function') { + Object.assign(headers, (await this.options.headers()) || {}); + } + + if (this.directus.auth.token) { + Object.assign(headers, { + Authorization: `Bearer ${this.directus.auth.token}`, + }); + } + + return headers; + } } class Log { - static log(level, message) { - let color = level === 'error' ? 'red' : level === 'warning' ? 'yellow' : 'white'; - - // eslint-disable-next-line no-console - console.log(chalk.cyan('gatsby-source-directus'), ':', chalk[color](message)); - } - static error(message) { - Log.log('error', message); - } - static warning(message) { - Log.log('error', message); - } + static log (level, message) { + let color = level === 'error' ? 'red' : level === 'warning' ? 'yellow' : 'white'; + + // eslint-disable-next-line no-console + console.log(chalk.cyan('gatsby-source-directus'), ':', chalk[color](message)); + } + static error (message) { + Log.log('error', message); + } + static warning (message) { + Log.log('error', message); + } } -function isEmpty(value) { - if (value?.constructor === String) return value.length === 0; +function isEmpty (value) { + if (value?.constructor === String) return value.length === 0; - return true; + return true; } -function error(message) { - Log.error(message); +function error (message) { + Log.error(message); - const error = new Error(`gatsby-source-directus: ${message}`); - error.stack = undefined; + const error = new Error(`gatsby-source-directus: ${message}`); + error.stack = undefined; - throw error; + throw error; } -function warning(message) { - Log.warning(message); +function warning (message) { + Log.warning(message); } const plugin = new Plugin(); From a82045753f8b4a8b3742d1ed8f2aad1490cc3817 Mon Sep 17 00:00:00 2001 From: jeffloop Date: Tue, 25 Oct 2022 09:50:53 -0700 Subject: [PATCH 2/3] Reformatting tabs/apaces Adding editorconfig, .eslintrc.js and .prettierrc.js from main directus repo. --- .editorconfig | 18 ++ .eslintrc.js | 71 ++++++++ .prettierrc.js | 7 + gatsby-node.js | 454 ++++++++++++++++++++++++------------------------- 4 files changed, 323 insertions(+), 227 deletions(-) create mode 100644 .editorconfig create mode 100644 .eslintrc.js create mode 100644 .prettierrc.js diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..0718e1b --- /dev/null +++ b/.editorconfig @@ -0,0 +1,18 @@ +root=true + +[*] +end_of_line = lf +insert_final_newline = true +charset = utf-8 +indent_style = tab +trim_trailing_whitespace = true + +[{package.json,*.yml,*.yaml}] +indent_style = space +indent_size = 2 + +[Dockerfile] +indent_style = tab + +[Makefile] +indent_style = tab diff --git a/.eslintrc.js b/.eslintrc.js new file mode 100644 index 0000000..1ba3db8 --- /dev/null +++ b/.eslintrc.js @@ -0,0 +1,71 @@ +const defaultRules = { + // No console statements in production + 'no-console': process.env.NODE_ENV !== 'development' ? 'error' : 'off', + // No debugger statements in production + 'no-debugger': process.env.NODE_ENV !== 'development' ? 'error' : 'off', + // Enforce prettier formatting + 'prettier/prettier': 'error', +}; + +module.exports = { + // Stop looking for ESLint configurations in parent folders + root: true, + // Global variables: Browser and Node.js + env: { + browser: true, + node: true, + }, + // Basic configuration for js files + plugins: ['@typescript-eslint', 'prettier'], + extends: ['eslint:recommended', 'prettier'], + rules: defaultRules, + parserOptions: { + ecmaVersion: 2020, + }, + overrides: [ + // Parse rollup configuration as module + { + files: ['rollup.config.js', 'vite.config.js'], + parserOptions: { + sourceType: 'module', + }, + }, + { + files: ['**/*.test.js'], + env: { + jest: true, + }, + plugins: ['jest'], + }, + // Configuration for ts/vue files + { + files: ['*.ts', '*.vue'], + parser: 'vue-eslint-parser', + parserOptions: { + parser: '@typescript-eslint/parser', + }, + extends: [ + 'plugin:vue/vue3-recommended', + 'eslint:recommended', + 'plugin:@typescript-eslint/recommended', + 'prettier', + ], + rules: { + ...defaultRules, + 'vue/multi-word-component-names': 'off', + // It's recommended to turn off this rule on TypeScript projects + 'no-undef': 'off', + // Allow ts-directive comments (used to suppress TypeScript compiler errors) + '@typescript-eslint/ban-ts-comment': 'off', + // Allow usage of the any type (consider to enable this rule later on) + '@typescript-eslint/no-explicit-any': 'off', + // Allow usage of require statements (consider to enable this rule later on) + '@typescript-eslint/no-var-requires': 'off', + // Allow non-null assertions for now (consider to enable this rule later on) + '@typescript-eslint/no-non-null-assertion': 'off', + // Allow unused arguments and variables when they begin with an underscore + '@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }], + }, + }, + ], +}; diff --git a/.prettierrc.js b/.prettierrc.js new file mode 100644 index 0000000..758f6fe --- /dev/null +++ b/.prettierrc.js @@ -0,0 +1,7 @@ +module.exports = { + htmlWhitespaceSensitivity: 'ignore', + printWidth: 120, + singleQuote: true, + useTabs: true, + proseWrap: 'always', +}; diff --git a/gatsby-node.js b/gatsby-node.js index c9da386..4b467ae 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -8,28 +8,28 @@ const { createRemoteFileNode } = require('gatsby-source-filesystem'); * Validate plugin options */ exports.pluginOptionsSchema = ({ Joi }) => { - return Joi.object().keys({ - url: Joi.string().required(), - auth: Joi.object() - .keys({ - token: Joi.string(), - email: Joi.string(), - password: Joi.string(), - }) - .with('email', 'password') - .with('password', 'email') - .xor('token', 'email'), - type: Joi.object() - .keys({ - name: Joi.string(), - field: Joi.string(), - }) - .optional(), - dev: Joi.object().keys({ - refresh: [Joi.number(), Joi.string()], - }), - graphql: Joi.object(), - }); + return Joi.object().keys({ + url: Joi.string().required(), + auth: Joi.object() + .keys({ + token: Joi.string(), + email: Joi.string(), + password: Joi.string(), + }) + .with('email', 'password') + .with('password', 'email') + .xor('token', 'email'), + type: Joi.object() + .keys({ + name: Joi.string(), + field: Joi.string(), + }) + .optional(), + dev: Joi.object().keys({ + refresh: [Joi.number(), Joi.string()], + }), + graphql: Joi.object(), + }); }; /** @@ -37,239 +37,239 @@ exports.pluginOptionsSchema = ({ Joi }) => { */ exports.sourceNodes = async (gatsbyOptions, pluginOptions) => { - const { actions: { createNode }, createNodeId, store, cache, reporter } = gatsbyOptions - const { headers } = await plugin.getOptions(); - const { Authorization } = await headers(); - - await plugin.setOptions(pluginOptions); - - const optionsSystem = plugin.getOptionsSystem(); - const options = plugin.getOptions(); - - // Avoid type conflict with gatsby-source-graphql - gatsbyOptions.actions.createNode = (node) => { - if (node.internal.type === 'GraphQLSource') { - if (node.typeName === optionsSystem.typeName) node.internal.type = 'DirectusSystemGraphQLSource'; - if (node.typeName === options.typeName) node.internal.type = 'DirectusGraphQLSource'; - } - - return createNode(node); - }; - - await sourceNodes(gatsbyOptions, optionsSystem); - await sourceNodes(gatsbyOptions, options); - - // Load images here rather than on file resolution. - // Create a node for each image and store it in the cache - // so it can bre retrieved on file resolution. - const remoteImages = await plugin.getAllImages(); - remoteImages.forEach(async (image) => { - const cachedImage = await cache.get(image.id) - if (cachedImage !== undefined) { - return - } - const nameParts = image.filename_download.split('.'); - const ext = nameParts.length > 1 ? `.${nameParts.pop()}` : ''; - const name = nameParts.join('.'); - const imageUrl = `${plugin.url}assets/${image.id}`; - const img = await createRemoteFileNode({ - url: imageUrl, - parentNodeId: image.id, - store, - cache, - createNode, - createNodeId, - httpHeaders: { Authorization }, - reporter, - ext, - name, - }); - await cache.set(image.id, img); - }) + const { actions: { createNode }, createNodeId, store, cache, reporter } = gatsbyOptions + const { headers } = await plugin.getOptions(); + const { Authorization } = await headers(); + + await plugin.setOptions(pluginOptions); + + const optionsSystem = plugin.getOptionsSystem(); + const options = plugin.getOptions(); + + // Avoid type conflict with gatsby-source-graphql + gatsbyOptions.actions.createNode = (node) => { + if (node.internal.type === 'GraphQLSource') { + if (node.typeName === optionsSystem.typeName) node.internal.type = 'DirectusSystemGraphQLSource'; + if (node.typeName === options.typeName) node.internal.type = 'DirectusGraphQLSource'; + } + + return createNode(node); + }; + + await sourceNodes(gatsbyOptions, optionsSystem); + await sourceNodes(gatsbyOptions, options); + + // Load images here rather than on file resolution. + // Create a node for each image and store it in the cache + // so it can bre retrieved on file resolution. + const remoteImages = await plugin.getAllImages(); + remoteImages.forEach(async (image) => { + const cachedImage = await cache.get(image.id) + if (cachedImage !== undefined) { + return + } + const nameParts = image.filename_download.split('.'); + const ext = nameParts.length > 1 ? `.${nameParts.pop()}` : ''; + const name = nameParts.join('.'); + const imageUrl = `${plugin.url}assets/${image.id}`; + const img = await createRemoteFileNode({ + url: imageUrl, + parentNodeId: image.id, + store, + cache, + createNode, + createNodeId, + httpHeaders: { Authorization }, + reporter, + ext, + name, + }); + await cache.set(image.id, img); + }) }; exports.createSchemaCustomization = async (gatsby, pluginOptions) => { - await plugin.setOptions(pluginOptions); + await plugin.setOptions(pluginOptions); - await createSchemaCustomization(gatsby, plugin.getOptionsSystem()); - await createSchemaCustomization(gatsby, plugin.getOptions()); + await createSchemaCustomization(gatsby, plugin.getOptionsSystem()); + await createSchemaCustomization(gatsby, plugin.getOptions()); }; /** * Gatsby file implementation. */ exports.createResolvers = async ({ cache, createResolvers }, pluginOptions) => { - await plugin.setOptions(pluginOptions); - - const fileResolver = { - imageFile: { - type: `File`, - async resolve (source) { - // Lookup the cached image node and return it - const cachedFile = await cache.get(source.id); - return cachedFile; - }, - }, - }; - - await createResolvers({ - DirectusData_directus_files: fileResolver, - DirectusSystemData_directus_files: fileResolver, - }); + await plugin.setOptions(pluginOptions); + + const fileResolver = { + imageFile: { + type: `File`, + async resolve (source) { + // Lookup the cached image node and return it + const cachedFile = await cache.get(source.id); + return cachedFile; + }, + }, + }; + + await createResolvers({ + DirectusData_directus_files: fileResolver, + DirectusSystemData_directus_files: fileResolver, + }); }; class Plugin { - constructor() { - // eslint-disable-next-line no-undef - this.fileCache = new Map(); - this.directus = null; - this.options = null; - this.urlGraphqlSystem = ''; - this.urlGraphql = ''; - this.url = ''; - this.refreshInterval = 0; - this.authPromise = null; - } - - async setOptions (options) { - const { url, dev, auth } = options; - - if (isEmpty(url)) error('"url" must be defined'); - - if (this.directus) return this.authPromise; - - const hasAuth = !!auth; - const hasToken = !isEmpty(auth?.token); - const hasEmail = !isEmpty(auth?.email); - const hasPassword = !isEmpty(auth?.password); - const hasCredentials = hasEmail && hasPassword; - - if (hasAuth) { - if (!hasToken && !hasCredentials) error('"auth.token" or ("auth.email" and "auth.password") must be defined'); - } else warning('no "auth" option were defined. Resources will be fetched with public role'); - - try { - const baseUrl = new URL(url); - - baseUrl.pathname = '/'; - this.url = baseUrl.toString(); - - baseUrl.pathname = '/graphql'; - this.urlGraphql = baseUrl.toString(); - - baseUrl.pathname = '/graphql/system'; - this.urlGraphqlSystem = baseUrl.toString(); - } catch (err) { - error('"url" should be a valid URL'); - } - - try { - this.directus = new Directus(this.url); - - if (hasToken) this.authPromise = await this.directus.auth.static(auth.token); - - if (hasCredentials) - this.authPromise = await this.directus.auth.login({ email: auth?.email, password: auth?.password }); - } catch (err) { - error(`authentication failed with: ${err.message}\nAre credentials valid?`); - } - - this.refreshInterval = typeof dev?.refresh === 'string' ? ms(dev.refresh) / 1000 : dev?.refresh || 15; - - if (Number.isNaN(this.refreshInterval)) - error('"dev.refresh" should be a number in seconds or a string with ms format, i.e. 5s, 5m, 5h, ...'); - - this.options = options; - - return this.authPromise; - } - - getOptions () { - const internalOptions = ['url', 'dev', 'auth', 'type']; - const gatsbyPluginOptions = Object.fromEntries( - Object.entries(this.options).flatMap(([key, value]) => (internalOptions.includes(key) ? [] : [[key, value]])) - ); - - return { - ...this.options.graphql, - ...gatsbyPluginOptions, - url: this.urlGraphql, - typeName: this.options?.type?.name || 'DirectusData', - fieldName: this.options?.type?.field || 'directus', - headers: this.headers.bind(this), - }; - } - - getOptionsSystem () { - const options = this.getOptions(); - - return { - ...options, - url: this.urlGraphqlSystem, - typeName: this.options?.type?.system_name || 'DirectusSystemData', - fieldName: this.options?.type?.system_field || 'directus_system', - }; - } - - /** - * Method to retrieve all of the images in directus.files - */ - async getAllImages () { - const files = await this.directus.files.readByQuery({ limit: -1 }); - const imageFiles = files.data.filter(file => file.type.indexOf('image') > -1); - return imageFiles; - } - - async headers () { - let headers = {}; - if (typeof this.options?.headers === 'object') { - Object.assign(headers, this.options.headers || {}); - } else if (typeof this.options?.headers === 'function') { - Object.assign(headers, (await this.options.headers()) || {}); - } - - if (this.directus.auth.token) { - Object.assign(headers, { - Authorization: `Bearer ${this.directus.auth.token}`, - }); - } - - return headers; - } + constructor() { + // eslint-disable-next-line no-undef + this.fileCache = new Map(); + this.directus = null; + this.options = null; + this.urlGraphqlSystem = ''; + this.urlGraphql = ''; + this.url = ''; + this.refreshInterval = 0; + this.authPromise = null; + } + + async setOptions (options) { + const { url, dev, auth } = options; + + if (isEmpty(url)) error('"url" must be defined'); + + if (this.directus) return this.authPromise; + + const hasAuth = !!auth; + const hasToken = !isEmpty(auth?.token); + const hasEmail = !isEmpty(auth?.email); + const hasPassword = !isEmpty(auth?.password); + const hasCredentials = hasEmail && hasPassword; + + if (hasAuth) { + if (!hasToken && !hasCredentials) error('"auth.token" or ("auth.email" and "auth.password") must be defined'); + } else warning('no "auth" option were defined. Resources will be fetched with public role'); + + try { + const baseUrl = new URL(url); + + baseUrl.pathname = '/'; + this.url = baseUrl.toString(); + + baseUrl.pathname = '/graphql'; + this.urlGraphql = baseUrl.toString(); + + baseUrl.pathname = '/graphql/system'; + this.urlGraphqlSystem = baseUrl.toString(); + } catch (err) { + error('"url" should be a valid URL'); + } + + try { + this.directus = new Directus(this.url); + + if (hasToken) this.authPromise = await this.directus.auth.static(auth.token); + + if (hasCredentials) + this.authPromise = await this.directus.auth.login({ email: auth?.email, password: auth?.password }); + } catch (err) { + error(`authentication failed with: ${err.message}\nAre credentials valid?`); + } + + this.refreshInterval = typeof dev?.refresh === 'string' ? ms(dev.refresh) / 1000 : dev?.refresh || 15; + + if (Number.isNaN(this.refreshInterval)) + error('"dev.refresh" should be a number in seconds or a string with ms format, i.e. 5s, 5m, 5h, ...'); + + this.options = options; + + return this.authPromise; + } + + getOptions () { + const internalOptions = ['url', 'dev', 'auth', 'type']; + const gatsbyPluginOptions = Object.fromEntries( + Object.entries(this.options).flatMap(([key, value]) => (internalOptions.includes(key) ? [] : [[key, value]])) + ); + + return { + ...this.options.graphql, + ...gatsbyPluginOptions, + url: this.urlGraphql, + typeName: this.options?.type?.name || 'DirectusData', + fieldName: this.options?.type?.field || 'directus', + headers: this.headers.bind(this), + }; + } + + getOptionsSystem () { + const options = this.getOptions(); + + return { + ...options, + url: this.urlGraphqlSystem, + typeName: this.options?.type?.system_name || 'DirectusSystemData', + fieldName: this.options?.type?.system_field || 'directus_system', + }; + } + + /** + * Method to retrieve all of the images in directus.files + */ + async getAllImages () { + const files = await this.directus.files.readByQuery({ limit: -1 }); + const imageFiles = files.data.filter(file => file.type.indexOf('image') > -1); + return imageFiles; + } + + async headers () { + let headers = {}; + if (typeof this.options?.headers === 'object') { + Object.assign(headers, this.options.headers || {}); + } else if (typeof this.options?.headers === 'function') { + Object.assign(headers, (await this.options.headers()) || {}); + } + + if (this.directus.auth.token) { + Object.assign(headers, { + Authorization: `Bearer ${this.directus.auth.token}`, + }); + } + + return headers; + } } class Log { - static log (level, message) { - let color = level === 'error' ? 'red' : level === 'warning' ? 'yellow' : 'white'; - - // eslint-disable-next-line no-console - console.log(chalk.cyan('gatsby-source-directus'), ':', chalk[color](message)); - } - static error (message) { - Log.log('error', message); - } - static warning (message) { - Log.log('error', message); - } + static log (level, message) { + let color = level === 'error' ? 'red' : level === 'warning' ? 'yellow' : 'white'; + + // eslint-disable-next-line no-console + console.log(chalk.cyan('gatsby-source-directus'), ':', chalk[color](message)); + } + static error (message) { + Log.log('error', message); + } + static warning (message) { + Log.log('error', message); + } } function isEmpty (value) { - if (value?.constructor === String) return value.length === 0; + if (value?.constructor === String) return value.length === 0; - return true; + return true; } function error (message) { - Log.error(message); + Log.error(message); - const error = new Error(`gatsby-source-directus: ${message}`); - error.stack = undefined; + const error = new Error(`gatsby-source-directus: ${message}`); + error.stack = undefined; - throw error; + throw error; } function warning (message) { - Log.warning(message); + Log.warning(message); } const plugin = new Plugin(); From eb6f66c51b5fcff273ef5f310ea627a479c89717 Mon Sep 17 00:00:00 2001 From: jeffloop Date: Tue, 25 Oct 2022 10:30:03 -0700 Subject: [PATCH 3/3] Changed spaces Changed spaces before function argument parens --- gatsby-node.js | 24 ++++++++++++------------ package.json | 5 ++++- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/gatsby-node.js b/gatsby-node.js index 4b467ae..042f8f6 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -104,7 +104,7 @@ exports.createResolvers = async ({ cache, createResolvers }, pluginOptions) => { const fileResolver = { imageFile: { type: `File`, - async resolve (source) { + async resolve(source) { // Lookup the cached image node and return it const cachedFile = await cache.get(source.id); return cachedFile; @@ -131,7 +131,7 @@ class Plugin { this.authPromise = null; } - async setOptions (options) { + async setOptions(options) { const { url, dev, auth } = options; if (isEmpty(url)) error('"url" must be defined'); @@ -184,7 +184,7 @@ class Plugin { return this.authPromise; } - getOptions () { + getOptions() { const internalOptions = ['url', 'dev', 'auth', 'type']; const gatsbyPluginOptions = Object.fromEntries( Object.entries(this.options).flatMap(([key, value]) => (internalOptions.includes(key) ? [] : [[key, value]])) @@ -200,7 +200,7 @@ class Plugin { }; } - getOptionsSystem () { + getOptionsSystem() { const options = this.getOptions(); return { @@ -214,13 +214,13 @@ class Plugin { /** * Method to retrieve all of the images in directus.files */ - async getAllImages () { + async getAllImages() { const files = await this.directus.files.readByQuery({ limit: -1 }); const imageFiles = files.data.filter(file => file.type.indexOf('image') > -1); return imageFiles; } - async headers () { + async headers() { let headers = {}; if (typeof this.options?.headers === 'object') { Object.assign(headers, this.options.headers || {}); @@ -239,27 +239,27 @@ class Plugin { } class Log { - static log (level, message) { + static log(level, message) { let color = level === 'error' ? 'red' : level === 'warning' ? 'yellow' : 'white'; // eslint-disable-next-line no-console console.log(chalk.cyan('gatsby-source-directus'), ':', chalk[color](message)); } - static error (message) { + static error(message) { Log.log('error', message); } - static warning (message) { + static warning(message) { Log.log('error', message); } } -function isEmpty (value) { +function isEmpty(value) { if (value?.constructor === String) return value.length === 0; return true; } -function error (message) { +function error(message) { Log.error(message); const error = new Error(`gatsby-source-directus: ${message}`); @@ -268,7 +268,7 @@ function error (message) { throw error; } -function warning (message) { +function warning(message) { Log.warning(message); } diff --git a/package.json b/package.json index 6bb6422..5819517 100644 --- a/package.json +++ b/package.json @@ -19,5 +19,8 @@ "bugs": { "url": "https://github.com/directus/directus/issues" }, - "gitHead": "24621f3934dc77eb23441331040ed13c676ceffd" + "gitHead": "24621f3934dc77eb23441331040ed13c676ceffd", + "devDependencies": { + "eslint-config-prettier": "^8.5.0" + } }