UNPKG

@architect/deploy

Version:
178 lines (161 loc) 4.64 kB
let { globSync, statSync } = require('node:fs') let { pathToUnix, chalk, waterfall } = require('@architect/utils') let { join, sep } = require('path') let filterFiles = require('./filter-files') let writeStaticManifest = require('./write-static-manifest') let putFiles = require('./s3/put-files') let deleteFiles = require('./s3/delete-files') // Allow file list to be cached between invocations let files, staticManifest module.exports = function publishStaticAssets (params, callback) { let { aws, Bucket, deployAction, inventory, prefix, prune, region, update, verbose, } = params let { inv, get } = inventory let folder = inv.static.folder let publicDir = join(inv._project.cwd, folder) let publishing = [ 'all', 'put' ].includes(deployAction) let deleting = [ 'all', 'delete' ].includes(deployAction) && prune // Assigned later let uploaded let notModified // Settings let fingerprint = get.static('fingerprint') let ignore = get.static('ignore') ? [ ...get.static('ignore') ] : [] // Second-pass, post-deploy, static asset pruning-only operation if (files && prune && deployAction === 'delete') { return deleteFiles({ aws, Bucket, files, fingerprint, folder, ignore, inventory, prefix, region, staticManifest, update, }, done) } // Notices if ((publishing && fingerprint) || (publishing && verbose)) { update.done(`Static asset fingerprinting ${fingerprint ? 'enabled' : 'disabled'}`) } if (prune || verbose) { update.done(`Orphaned file pruning ${prune ? 'enabled' : 'disabled'}`) } waterfall([ // Scan for files in the public directory function _globAndFilter (callback) { try { let path = pathToUnix(publicDir + '/**/*') let globbed = globSync(path) // Filter out directories (native fs.globSync doesn't have nodir option) globbed = globbed.filter(filePath => { try { return statSync(filePath).isFile() } catch { return false } }) // Filter based on default and user-specified @static ignore rules filterFiles({ globbed, ignore }, callback) } catch (err) { callback(err) } }, // Write, reuse, or possibly remove fingerprinted static asset manifest function _maybeWriteStaticManifest (filtered, ignored, callback) { files = filtered writeStaticManifest({ ignore: ignored, inventory, publishing, publicDir, }, callback) }, // Upload files to S3 function _put (manifest = {}, callback) { // Fingerprinter may or may not return a manifest if (!callback) { callback = manifest manifest = {} } staticManifest = manifest // static.json is intentionally ignored during fingerprinting; ensure it's uploaded if (fingerprint && (fingerprint !== 'external')) { files.unshift(join(publicDir, 'static.json')) } putFiles({ aws, Bucket, files, fingerprint, inventory, publicDir, prefix, region, staticManifest, update, verbose, }, callback) }, // Prune old files (if requested) function _delete (uploadCount, notModifiedCount, callback) { uploaded = uploadCount notModified = notModifiedCount if (deleting) { deleteFiles({ aws, Bucket, files, fingerprint, folder, ignore, inventory, prefix, region, staticManifest, update, }, callback) } else callback() }, ], done) function done (err) { if (err?.message === 'no_files_to_publish') { update.done('Done!', `No static assets found to deploy from ${folder}${sep}`) callback() } else if (err?.message === 'access_denied') { update.error(`${chalk.red.bold('S3 access denied:')} could not access S3 bucket (${Bucket})`) update.error('Possible reason: bucket already exists & belongs to another AWS account') callback() } else if (err) { callback(err) } else { if (notModified) { update.done(`Skipped ${notModified} file${notModified > 1 ? 's' : ''} (already up to date)`) } if (uploaded) { let msg = `Deployed ${uploaded} static asset${uploaded > 1 ? 's' : ''} from ${folder}${sep}` update.done(msg) } callback() } } }