@linked-helper/framework.build-tools.aws-artifacts
Version:
LH framework build tools: upload artifacts
186 lines (179 loc) • 6.62 kB
JavaScript
;
var clientS3 = require('@aws-sdk/client-s3');
var _glob = require('glob');
var fs = require('node:fs');
var path = require('node:path');
var node_stream = require('node:stream');
var node_util = require('node:util');
var uploadFiles = require('./uploadFiles-DxoCy-HV.cjs');
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
var _glob__default = /*#__PURE__*/_interopDefault(_glob);
var fs__default = /*#__PURE__*/_interopDefault(fs);
var path__default = /*#__PURE__*/_interopDefault(path);
async function downloadFiles({ prefix, root, bucket, files, platform, ...client }, { onListFiles, onFileDownloaded, onFileDownloadFailed, onDownloaded, } = {}) {
const glob = (() => {
return (pattern) => _glob__default.default(pattern, {
cwd: root,
nodir: true,
absolute: true,
});
})();
const s3 = uploadFiles.getS3Client(client);
const listResult = await s3.send(new clientS3.ListObjectsCommand({
Bucket: bucket,
Prefix: prefix + '/',
}));
const entries = listResult.Contents;
if (!entries) {
throw new Error(`no objects found with prefix "${prefix}/"`);
}
const platforms = platform === 'all'
? uploadFiles.IPlatform$1.all
: [platform];
const fileInfos = [];
// filter files to download
{
const entriesPathsByKey = new Map(entries.map(e => [e.Key, path__default.default.resolve(root, e.Key.replace(prefix + '/', ''))]));
// first create empty files as in s3 bucket
// and wait for them to be created
await Promise.all([...entriesPathsByKey.values()].map(async (entryPath, i) => {
const delay = (i % 10) * 16;
await sleep(delay);
await touchFile(entryPath, 200 + delay);
}));
// match entries by glob patterns
// and remove matched from entries map
for (const p of [...platforms, 'all']) {
for (const pattern of files[p]) {
for (const filePath of await glob(pattern)) {
const key = path__default.default.join(prefix, path__default.default.relative(root, filePath)).split(path__default.default.sep).join(path__default.default.posix.sep);
if (entriesPathsByKey.has(key)) {
fileInfos.push({
path: filePath,
relativePath: path__default.default.relative(root, filePath).split(path__default.default.sep).join(path__default.default.posix.sep),
key,
});
entriesPathsByKey.delete(key);
}
}
}
}
// delete unused empty files
await Promise.all([...entriesPathsByKey.values()].map(async (entryPath, i) => {
const delay = (i % 10) * 8;
await sleep(delay);
await deleteFile(entryPath, 200 + delay);
}));
}
try {
onListFiles?.(fileInfos);
}
catch (dontCare) { /* do nothing */ }
if (!fileInfos.length) {
throw new Error('no files found');
}
const downloaded = [];
await Promise.all(fileInfos.map(async (file) => {
try {
await fs.promises.mkdir(path__default.default.dirname(file.path), { recursive: true });
await node_util.promisify(node_stream.pipeline)(await download({ s3, bucket, key: file.key }), fs__default.default.createWriteStream(file.path));
downloaded.push(file);
try {
onFileDownloaded?.(file, [...downloaded], fileInfos);
}
catch (dontCare) { /* do nothing */ }
}
catch (err) {
try {
onFileDownloadFailed?.(file, err, [...downloaded], fileInfos);
}
catch (dontCare) { /* do nothing */ }
throw err;
}
}));
try {
onDownloaded?.(fileInfos);
}
catch (dontCare) { /* do nothing */ }
return downloaded;
}
async function download({ bucket, key, ...client }) {
const s3 = client.s3 ?? new clientS3.S3Client(client);
const result = await s3.send(new clientS3.GetObjectCommand({
Bucket: bucket,
Key: key,
}));
return result.Body;
}
async function touchFile(filePath, delayBetweenTries = 300, maxTries = 10) {
await fs.promises.mkdir(path__default.default.dirname(filePath), { recursive: true });
await fs.promises.writeFile(filePath, '');
let tries = 0;
while (true) {
try {
await fs.promises.access(filePath, fs__default.default.constants.W_OK);
break;
}
catch (e) {
if (++tries >= maxTries) {
throw e;
}
await sleep(delayBetweenTries);
}
}
}
async function deleteFile(filePath, delayBetweenTries = 300, maxTries = 10) {
await fs.promises.unlink(filePath);
let tries = 0;
while (true) {
try {
await fs.promises.access(filePath, fs__default.default.constants.F_OK);
}
catch (e) {
if (e && e.errno === 'ENOENT') {
break;
}
}
if (++tries >= maxTries) {
// tslint:disable-next-line: no-console
console.warn('failed to delete', filePath);
break;
}
await sleep(delayBetweenTries);
}
}
async function sleep(ms) {
return new Promise(r => setTimeout(r, ms));
}
function isDependency({ cwd = process.cwd() } = {}) {
const parts = path__default.default.resolve(cwd).split(path__default.default.sep);
// tslint:disable-next-line: no-string-literal
const packageName = process.env['npm_package_name'];
if (packageName) {
const [, scope, name] = /^(@.*)\/(.*)$/.exec(packageName) ?? [];
if (scope && name) {
if (parts[parts.length - 1] === name) {
parts.pop();
}
if (parts[parts.length - 1] === scope) {
parts.pop();
}
}
else {
if (parts[parts.length - 1] === packageName) {
parts.pop();
}
}
}
const parent1Folder = parts.pop();
const parent2Folder = parts.pop();
if (parent1Folder === 'node_modules') {
return true;
}
else if (parent1Folder && /^@/.test(parent1Folder) && parent2Folder === 'node_modules') {
return true;
}
return false;
}
exports.downloadFiles = downloadFiles;
exports.isDependency = isDependency;