Spaces:
Sleeping
Sleeping
import fs from 'fs'; | |
import path from 'path'; | |
import {promisify} from 'util'; | |
import fetch from 'cross-fetch'; | |
import {name} from '../../../package.json'; | |
import defaultIcon from '../images/default-icon.png'; | |
import Image from './image'; | |
const readFile = promisify(fs.readFile); | |
const writeFile = promisify(fs.writeFile); | |
const mkdir = promisify(fs.mkdir); | |
const safeJoin = (root, file) => { | |
root = path.join(root, '/'); | |
const joined = path.join(root, file); | |
if (joined.startsWith(root)) { | |
return joined; | |
} | |
return null; | |
}; | |
const cacheDirectory = path.join(__dirname, '..', '.packager-cache'); | |
const getCachePath = async (asset) => { | |
if (!asset.sha256) return null; | |
const path = safeJoin(cacheDirectory, asset.sha256); | |
if (path) { | |
await mkdir(cacheDirectory, { | |
recursive: true | |
}); | |
return path; | |
} | |
return null; | |
}; | |
const nodeBufferToArrayBuffer = (buffer) => buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength); | |
const arrayBufferToNodeBuffer = (buffer) => Buffer.from(buffer); | |
class NodeAdapter { | |
async getCachedAsset (asset) { | |
const urls = asset.src; | |
const src = Array.isArray(urls) ? urls[0] : urls; | |
if (src.startsWith('scaffolding/')) { | |
const file = safeJoin(__dirname, src); | |
if (file) { | |
return readFile(file, 'utf-8'); | |
} | |
} | |
if (src.startsWith('https:')) { | |
const cachePath = await getCachePath(asset); | |
if (cachePath) { | |
try { | |
return nodeBufferToArrayBuffer(await readFile(cachePath)); | |
} catch (e) { | |
// ignore | |
} | |
} | |
console.log(`[${name}]: downloading large asset ${src}; this may take a while`); | |
const res = await fetch(src); | |
if (!res.ok) { | |
throw new Error(`Unexpected status code: ${res.status}`); | |
} | |
const arrayBuffer = await res.arrayBuffer(); | |
if (cachePath) { | |
await writeFile(cachePath, arrayBufferToNodeBuffer(arrayBuffer)); | |
} | |
return arrayBuffer; | |
} | |
} | |
async cacheAsset (asset, result) { | |
// all of our caching logic lives in getCachedAsset | |
} | |
async getAppIcon (file) { | |
if (!file) { | |
// Use the default icon when no icon is given | |
const buffer = await readFile(path.join(__dirname, defaultIcon)); | |
return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength); | |
} | |
if (file instanceof Image) { | |
if (file.mimeType === 'image/png') { | |
return file.readAsBuffer(); | |
} | |
throw new Error('icon must be of type image/png but found ' + file.mimeType + ' instead.'); | |
} | |
throw new Error('file must be an instance of Packager.Image or null but found ' + file + ' instead.'); | |
} | |
readAsURL (file) { | |
if (!(file instanceof Image)) { | |
throw new Error('file must be an instance of Packager.Image but found ' + file + ' instead.'); | |
} | |
return file.readAsURL(); | |
} | |
fetchExtensionScript (url) { | |
return fetch(url) | |
.then(res => { | |
if (res.ok) { | |
return res.text(); | |
} | |
throw new Error(`Unexpected status code: ${res.status}`); | |
}); | |
} | |
} | |
export default NodeAdapter; | |