@bscotch/stitch
Version:
Stitch: The GameMaker Studio 2 Asset Pipeline Development Kit.
81 lines • 3.15 kB
JavaScript
import fs from 'fs-extra';
import http from 'http';
import https from 'https';
import path from 'path';
import unzipper from 'unzipper';
import Url from 'url';
import { StitchError } from './errors.js';
import { debug } from './log.js';
export function get(url, headers) {
const { protocol } = Url.parse(url);
const httpType = protocol?.match(/^(https?):$/)?.[1];
if (!httpType) {
throw new StitchError('URL must include protocol (http(s))');
}
return new Promise((resolve, reject) => {
const getter = { http, https }[httpType];
const options = { headers: headers || {} };
options.headers['User-Agent'] = 'Bscotch Stitch';
getter
.get(url, options, (res) => {
const chunks = [];
res.on('data', (chunk) => {
chunks.push(chunk);
});
res.on('end', () => {
const status = res.statusCode || 500;
if (status > 300 && status < 400) {
// Then is probably a redirect
if (!res.headers.location) {
throw new StitchError(`Got status ${status} but no location header for redirect.`);
}
return resolve(get(res.headers.location));
}
if (status > 399) {
throw new StitchError(`Got non-200 response code ${status} when trying to download ${url}`);
}
const contentType = res.headers['content-type'];
const data = Buffer.concat(chunks);
const response = {
contentType: contentType || 'application/octet-stream',
data,
};
if (contentType?.startsWith('text')) {
response.data = data.toString('utf8');
return resolve(response);
}
else if (contentType?.startsWith('application/json')) {
try {
response.data = JSON.parse(data.toString('utf8'));
return resolve(response);
}
catch {
throw new StitchError(`Response from ${url} was invalid JSON: ${data.toString('utf8')}`);
}
}
return resolve(response);
});
})
.on('error', (err) => {
reject(err);
});
});
}
/**
* Downloads and unzip a remote zip file, returning the root path
* to the unzipped contents.
*/
export async function unzipRemote(url, toDir, headers) {
fs.ensureDirSync(toDir);
if (fs.readdirSync(toDir).length > 0) {
throw new StitchError(`Output directory ${toDir} is not empty.`);
}
debug('Downloading...');
const response = await get(url, headers);
debug('Unzipping...');
const zipDir = await unzipper.Open.buffer(response.data);
await zipDir.extract({ concurrency: 10, path: toDir });
debug('Unzipped!');
return path.join(toDir, zipDir.files[0].path);
}
//# sourceMappingURL=http.js.map