Skip to content

Commit

Permalink
feat(assets): enhance config deduction
Browse files Browse the repository at this point in the history
  • Loading branch information
shigma committed Apr 1, 2021
1 parent 95adc17 commit 8ec40d7
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 28 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ temp
/tsconfig.temp.json

/addons
/public
/atri
/coverage
/docs
Expand Down
67 changes: 39 additions & 28 deletions packages/plugin-assets/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,16 @@ async function getAssetBuffer(url: string, axiosConfig: AxiosRequestConfig) {
return Buffer.from(data)
}

interface ServerConfig {
interface LocalConfig {
type: 'local'
path?: string
root?: string
selfUrl?: string
secret?: string
axiosConfig?: AxiosRequestConfig
}

class AssetServer implements Assets {
class LocalAssets implements Assets {
types = ['video', 'audio', 'image'] as const

private _promise: Promise<void>
Expand All @@ -35,27 +36,31 @@ class AssetServer implements Assets {
assetSize: 0,
}

constructor(public ctx: Context, public config: ServerConfig) {
const path = sanitize(config.path || '/assets')
config.root ||= resolve(__dirname, '../public')
constructor(public ctx: Context, public config: LocalConfig) {
config.path = sanitize(config.path || '/assets')
if (config.root) {
config.root = resolve(process.cwd(), config.root)
} else {
config.root = resolve(__dirname, '../public')
}

if (config.selfUrl) {
config.selfUrl = trimSlash(config.selfUrl)
} else if (!(config.selfUrl = ctx.app.options.selfUrl)) {
throw new Error(`missing configuration "selfUrl" or "server"`)
}

ctx.router.get(path, async (ctx) => {
ctx.router.get(config.path, async (ctx) => {
return ctx.body = await this.stats()
})

ctx.router.get(path + '/:name', (ctx) => {
ctx.router.get(config.path + '/:name', (ctx) => {
const filename = resolve(config.root, ctx.params.name)
ctx.type = extname(filename)
return ctx.body = createReadStream(filename)
})

ctx.router.post(path, async (ctx) => {
ctx.router.post(config.path, async (ctx) => {
const { salt, sign, url, file } = ctx.query
if (Array.isArray(file) || Array.isArray(url)) {
return ctx.status = 400
Expand Down Expand Up @@ -85,15 +90,25 @@ class AssetServer implements Assets {
}))
}

async write(buffer: Buffer, filename: string) {
await fs.writeFile(filename, buffer)
this._stats.assetCount += 1
this._stats.assetSize += buffer.byteLength
}

async upload(url: string, file: string) {
await this._promise
const { selfUrl, path, root, axiosConfig } = this.config
const filename = resolve(root, file)
if (!existsSync(filename)) {
if (file) {
const filename = resolve(root, file)
if (!existsSync(filename)) {
const buffer = await getAssetBuffer(url, axiosConfig)
await this.write(buffer, filename)
}
} else {
const buffer = await getAssetBuffer(url, axiosConfig)
await fs.writeFile(filename, buffer)
this._stats.assetCount += 1
this._stats.assetSize += buffer.byteLength
file = createHash('sha1').update(buffer).digest('hex')
await this.write(buffer, resolve(root, file))
}
return `${selfUrl}${path}/${file}`
}
Expand All @@ -104,16 +119,17 @@ class AssetServer implements Assets {
}
}

interface ClientConfig {
interface RemoteConfig {
type: 'remote'
server: string
secret?: string
axiosConfig?: AxiosRequestConfig
}

class AssetClient implements Assets {
class RemoteAssets implements Assets {
types = ['video', 'audio', 'image'] as const

constructor(public ctx: Context, public config: ClientConfig) {}
constructor(public ctx: Context, public config: RemoteConfig) {}

async upload(url: string, file: string) {
const { server, secret, axiosConfig } = this.config
Expand Down Expand Up @@ -183,25 +199,20 @@ class SmmsAssets implements Assets {
}
}

export type Config = ServerConfig | ClientConfig | SmmsConfig
export type Config = LocalConfig | RemoteConfig | SmmsConfig

export const name = 'assets'

export function apply(ctx: Context, config: Config = {}) {
export function apply(ctx: Context, config: Config) {
config.axiosConfig = {
...ctx.app.options.axiosConfig,
...config.axiosConfig,
}

if ('type' in config) {
if (config.type === 'smms') {
ctx.assets = new SmmsAssets(ctx, config)
} else {
throw new Error(`unsupported asset provider type "${config.type}"`)
}
} else if ('server' in config) {
ctx.assets = new AssetClient(ctx, config)
} else {
ctx.assets = new AssetServer(ctx, config)
switch (config.type) {
case 'local': ctx.assets = new LocalAssets(ctx, config); break
case 'remote': ctx.assets = new RemoteAssets(ctx, config); break
case 'smms': ctx.assets = new SmmsAssets(ctx, config); break
default: throw new Error(`unsupported asset provider type "${config['type']}"`)
}
}

0 comments on commit 8ec40d7

Please sign in to comment.