Skip to content

Commit

Permalink
feat: allow top level provider options
Browse files Browse the repository at this point in the history
  • Loading branch information
farnabaz committed Nov 16, 2020
1 parent 70fe852 commit 7b47d6e
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 111 deletions.
26 changes: 12 additions & 14 deletions playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,18 @@ export default {
'@nuxt/typescript-build'
],
image: {
twicpics: {
baseURL: 'https://i5acur1u.twic.pics'
},
cloudinary: {
baseURL: 'https://res.cloudinary.com/nuxt/image/upload'
},
fastly: {
baseURL: 'https://www.fastly.io'
},
imgix: {
baseURL: 'https://assets.imgix.net'
},
presets: [
{
name: 's50',
Expand All @@ -17,20 +29,6 @@ export default {
}
}
],
providers: {
twicpics: {
baseURL: 'https://i5acur1u.twic.pics'
},
cloudinary: {
baseURL: 'https://res.cloudinary.com/nuxt/image/upload'
},
fastly: {
baseURL: 'https://www.fastly.io'
},
imgix: {
baseURL: 'https://assets.imgix.net'
}
},
intersectOptions: {
rootMargin: '50px'
}
Expand Down
97 changes: 10 additions & 87 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,23 @@
import path from 'path'
import defu from 'defu'
import fs from 'fs-extra'
import upath from 'upath'
import { ModuleOptions, ProviderFactory } from 'types'
import { downloadImage, getFileExtension, hash, logger, tryRequire } from './utils'
import { ModuleOptions } from 'types'
import { downloadImage, getFileExtension, getProviders, hash } from './utils'
import { cleanDoubleSlashes } from './runtime/utils'
export type { Provider, RuntimeProvider } from 'types'

function imageModule (moduleOptions: ModuleOptions) {
async function imageModule (moduleOptions: ModuleOptions) {
const { nuxt, addServerMiddleware, addPlugin } = this

const options: ModuleOptions = {
provider: 'local',
providers: {}, // user custom providers
presets: [],
intersectOptions: {},
sizes: [320, 420, 768, 1024, 1200],
providers: {},
...nuxt.options.image,
...moduleOptions
}

if (typeof options.providers.local !== 'undefined') {
logger.warn("'local' is a reserved name for provider. Please choose another name for your provider. This provider will ignore.")
}

options.providers.local = prepareLocalProvider(this, options.local || {})

interface ModuleProvider {
name: string,
options: any
provider: ProviderFactory
}

const providers: ModuleProvider[] = Object.entries(options.providers)
.map(([key, provider]) => loadProvider.call(this, key, provider))

const pluginOptions = {
sizes: options.sizes,
defaultProvider: options.provider,
Expand All @@ -44,20 +27,19 @@ function imageModule (moduleOptions: ModuleOptions) {
presets: options.presets
}

const providers = await getProviders(nuxt, options)
for (const p of providers) {
const { middleware, runtime, runtimeOptions } = p.provider(p.options)
const importName = 'runtime_' + hash(runtime).substr(0, 8)
pluginOptions.imports[importName] = upath.normalize(runtime)
pluginOptions.imports[p.importName] = p.runtime
pluginOptions.providers.push({
name: p.name,
import: importName,
options: runtimeOptions
import: p.importName,
options: p.runtimeOptions
})

if (typeof middleware === 'function') {
if (typeof p.middleware === 'function') {
addServerMiddleware({
path: '/_image/' + p.name,
handler: middleware
handler: p.middleware
})
}
}
Expand Down Expand Up @@ -91,28 +73,6 @@ function imageModule (moduleOptions: ModuleOptions) {
}
}

function loadProvider (key: string, provider: any) {
const { nuxt } = this
if (typeof provider === 'string') {
provider = { provider }
} else if (typeof provider === 'object') {
provider = { options: provider }
}

if (!provider.name) {
provider.name = key
}
if (!provider.provider) {
provider.provider = provider.name
}
if (typeof provider.provider === 'string') {
provider.provider = tryRequire('./providers/' + provider.provider) ||
nuxt.resolver.requireModule(provider.provider)
}
// TODO: verify provider.provider and warn+skip if invalid
return provider
}

function handleStaticGeneration (nuxt: any, options: ModuleOptions) {
const staticImages = {} // url ~> hash

Expand Down Expand Up @@ -149,42 +109,5 @@ function handleStaticGeneration (nuxt: any, options: ModuleOptions) {
})
}

function prepareLocalProvider ({ nuxt, options }, providerOptions) {
// Default port
const defaultPort =
process.env.PORT ||
process.env.npm_package_config_nuxt_port ||
(options.server && options.server.port) ||
3000

// Default host
let defaultHost =
process.env.HOST ||
process.env.npm_package_config_nuxt_host ||
(options.server && options.server.host) ||
'localhost'

/* istanbul ignore if */
if (defaultHost === '0.0.0.0') {
defaultHost = 'localhost'
}

// Default prefix
const prefix = '/'

providerOptions = defu(providerOptions, {
baseURL: `http://${defaultHost}:${defaultPort}${prefix}`,
dir: path.join('~', nuxt.options.dir.static),
clearCache: false,
cacheDir: '~~/node_modules/.cache/nuxt-image',
sharp: {}
})

providerOptions.dir = nuxt.resolver.resolveAlias(providerOptions.dir)
providerOptions.cacheDir = nuxt.resolver.resolveAlias(providerOptions.cacheDir)

return providerOptions
}

(imageModule as any).meta = require('../package.json')
export default imageModule
85 changes: 85 additions & 0 deletions src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import path from 'path'
import util from 'util'
import defu from 'defu'
import consola from 'consola'
import fetch from 'node-fetch'
import hasha from 'hasha'
import fs from 'fs-extra'
import upath from 'upath'
import { ModuleOptions, ModuleProvider } from 'types'

const streamPipeline = util.promisify(require('stream').pipeline)

Expand Down Expand Up @@ -35,3 +38,85 @@ export function getFileExtension (url: string) {
export function hash (value: string, length = 6) {
return hasha(value).substr(0, length)
}

export async function getProviders (nuxt, options: ModuleOptions): Promise<ModuleProvider[]> {
const providerNames = await fs.readdir(path.resolve(__dirname, './providers'))

// enrich local provider
options.local = enrichLocalProvider(nuxt, options.local || {})

const providers = [
// official providers
...providerNames.map(name => options[name] && [name, options[name]]).filter(Boolean),
// user custom providers
...Object.entries(options.providers)
]
return providers
.map(([key, provider]) => loadProvider(nuxt, key, provider))
}

export function enrichLocalProvider (nuxt, providerOptions) {
const { options } = nuxt
// Default port
const defaultPort =
process.env.PORT ||
process.env.npm_package_config_nuxt_port ||
(options.server && options.server.port) ||
3000

// Default host
let defaultHost =
process.env.HOST ||
process.env.npm_package_config_nuxt_host ||
(options.server && options.server.host) ||
'localhost'

/* istanbul ignore if */
if (defaultHost === '0.0.0.0') {
defaultHost = 'localhost'
}

// Default prefix
const prefix = '/'

providerOptions = defu(providerOptions, {
baseURL: `http://${defaultHost}:${defaultPort}${prefix}`,
dir: path.join('~', options.dir.static),
clearCache: false,
cacheDir: '~~/node_modules/.cache/nuxt-image',
sharp: {}
})

providerOptions.dir = nuxt.resolver.resolveAlias(providerOptions.dir)
providerOptions.cacheDir = nuxt.resolver.resolveAlias(providerOptions.cacheDir)

return providerOptions
}

export function loadProvider (nuxt, key: string, provider: any) {
if (typeof provider === 'string') {
provider = { provider }
} else if (typeof provider === 'object') {
provider = { options: provider }
}

if (!provider.name) {
provider.name = key
}
if (!provider.provider) {
provider.provider = provider.name
}
if (typeof provider.provider === 'string') {
provider.provider = tryRequire('./providers/' + provider.provider) ||
nuxt.resolver.requireModule(provider.provider)
}
const { middleware, runtime, runtimeOptions } = provider.provider(provider.options)
// TODO: verify provider.provider and warn+skip if invalid
return {
...provider,
middleware,
runtimeOptions,
runtime: upath.normalize(runtime),
importName: 'runtime_' + hash(runtime).substr(0, 8)
}
}
20 changes: 20 additions & 0 deletions types/module.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,23 @@ export interface ModuleOptions {
}

export const imageModule: Module<ModuleOptions>

export type ProviderServerMiddleware = (req, res, next) => void

export type ProviderFactory = (options: any) => Provider

export interface Provider {
runtime: string
runtimeOptions: any
middleware?(): ProviderServerMiddleware
}

export interface ModuleProvider {
name: string
importName: string
options: any
provider: ProviderFactory
runtime: string
runtimeOptions: any
middleware?: any
}
10 changes: 0 additions & 10 deletions types/runtime.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,16 +44,6 @@ export interface ImageSize {

// -- Provider --

export type ProviderFactory = (options: any) => Provider

export interface Provider {
runtime: string
runtimeOptions: any
middleware?(): ProviderServerMiddleware
}

export type ProviderServerMiddleware = (req, res, next) => void

export interface RuntimeProvider {
// Apply provider base
// Add additional params (like signuture)
Expand Down

0 comments on commit 7b47d6e

Please sign in to comment.