UNPKG

@linked-helper/framework.build-tools.aws-artifacts

Version:

LH framework build tools: upload artifacts

186 lines (179 loc) 6.62 kB
'use strict'; 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;