Skip to content

Instantly share code, notes, and snippets.

@noxify
Last active May 29, 2020 10:00
Show Gist options
  • Save noxify/7f3085b400991535ef997dedaacf2b1d to your computer and use it in GitHub Desktop.
Save noxify/7f3085b400991535ef997dedaacf2b1d to your computer and use it in GitHub Desktop.
.
|-src
| |-components
| |-layouts
| |-templates
| |-assets
| | |-remoteImages
| | | |- image.png ( <-- my example image which is used in the code below )
| |-pages
|-packages
| |-gridsome-plugin-remote-image
| | |-gridsome.server.js ( <-- package-gridsome.server.js )
|-gridsome.config.js ( <-- root-gridsome.config.js )
const fs = require('fs')
const path = require('path')
const crypto = require('crypto')
const imageType = require('image-type')
const imageDownload = require('image-download')
const validate = require('validate.js')
const chalk = require('chalk')
const _ = require('lodash')
class ImageDownloader {
constructor(api, options) {
this.options = options;
this.api = api;
//initialize the `loadImage` event and make
//it available before we run the `onBootstrap` command
this.initializeEvent(api);
//create a new type `Images` which is required
//for array support
//also add a new field to the defined collection
//to store the downloaded images
api.createSchema(({ addSchemaTypes }) => {
const fieldType = this.getFieldType(api, options);
this.generateSchemaType(addSchemaTypes, fieldType);
});
//run the plugin code, after gridsome finished all their work ( right? )
api.onBootstrap(() => this.loadImages())
}
/**
* Create a new event via the gridsome plugin api
* reference: node_modules/gridsome/lib/app/PluginAPI.js
*/
initializeEvent(api) {
api._on('loadImage', this.runDownloader)
}
/**
* Run the defined event with the required
* arguments - i have no clue why `this` is not available
* but I'm too tired to check this in detail...
* Defining the needed methods is fine for me :)
*/
async loadImages() {
await this.run('loadImage', null, {
getFieldType: this.getFieldType,
getRemoteImage: this.getRemoteImage,
updateNodes: this.updateNodes,
options: this.options
})
}
/**
* Defined in `initializeEvent`
* Called via `loadImages`
*/
async runDownloader(plugin, api) {
const fieldType = plugin.getFieldType(api, plugin.options);
await plugin.updateNodes(api, fieldType, plugin.options)
}
getFieldType(api, options) {
const nodeCollection = api._app.store.getCollection(options.typeName);
let findQuery = {};
//details about this definition can be found here
//https://github.com/techfort/LokiJS/wiki/Query-Examples#find-operator-examples-
findQuery[options.sourceField] = {
'$exists': true
};
const node = nodeCollection.findNode(findQuery);
//we're using the lodash get functionality
//to allow a dot notation in the source field name
return (node) ? typeof _.get(node, options.sourceField) : false;
}
generateSchemaType(addSchemaTypes, fieldType) {
const schemaType = (fieldType == 'string') ? 'Image' : '[Images]';
addSchemaTypes(
`
type Images {
image: Image
}
`
);
//extend the existing schema
addSchemaTypes(
`
type ${this.options.typeName} implements Node @infer {
${this.options.targetField}: ${schemaType}
}
`
);
}
async updateNodes(api, fieldType, options) {
var collection = api._app.store.getCollection(options.typeName);
collection.data().forEach(async function (node) {
if (_.get(node,options.sourceField)) {
//const imagePaths = await that.getRemoteImage(node, fieldType);
const image = path.resolve(
options.targetPath,
`image.png`
)
const imagePaths = [image];
if( fieldType == 'string' ) {
node[options.targetField] = imagePaths[0];
} else {
node[options.targetField] = _.map(imagePaths, function(imagePath) {
return {
image: imagePath
};
});
}
var res = collection.updateNode(node);
}
})
}
/**********************
* Helpers
**********************/
/**
* Copied from node_modules/gridsome/lib/app/Plugins.js
*/
async run(eventName, cb, ...args) {
if (!this.api._app.plugins._listeners[eventName]) return []
const results = []
for (const entry of this.api._app.plugins._listeners[eventName]) {
if (entry.options.once && entry.done) continue
const { api, handler } = entry
const result = typeof cb === 'function'
? await handler(cb(api))
: await handler(...args, api)
results.push(result)
entry.done = true
}
return results
}
validateOptions(options = {}) {
const contraintOption = {
presence: {
allowEmpty: false
}
};
const constraints = {
typeName: contraintOption,
sourceField: contraintOption,
targetField: contraintOption,
targetPath: contraintOption
};
const validationResult = validate(options, constraints, {
format: "flat"
});
return validationResult;
}
}
module.exports = ImageDownloader
module.exports = {
siteName: 'Gridsome',
plugins: [
{
use: '@gridsome/source-contentful',
options: {
space: 'XXXX', // required
accessToken: 'XXX', // required
host: 'cdn.contentful.com',
environment: 'master',
typeName: 'Contentful'
}
},
{
use: '~/packages/gridsome-plugin-remote-image',
options: {
'typeName' : 'ContentfulAsset',
'sourceField': 'file.url',
'targetField': 'imageDownloaded',
'targetPath': './src/assets/remoteImages'
}
}
],
templates : {
ContentfulArticles: '/contentful/:title'
},
transformer : {
remark: {}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment