UNPKG

@agondata/blobpack

Version:

Packaging Benthos configs for AWS Lambda was too exciting, now it's acceptably boring.

143 lines (119 loc) 3.8 kB
import fs from 'fs' import path from 'path' import mkdirp from 'mkdirp' import jsYaml from 'js-yaml' import jszip from 'jszip' import { loadConfig } from './config.js' import { zipName } from './zip-name.js' import { mergeArrayProps, mergeConfig } from './merge.js' const { load: yamlLoad, dump: yamlDump } = jsYaml const { loadAsync: zipLoadAsync } = jszip const staticConfigName = 'benthos.yaml' export const build = async ({ configPath = 'package.json', tmpRoot = 'tmp', configRoot = 'config', resourcesRoot = '', distRoot = 'dist', logger = console } = {}) => { try { const config = await loadConfig(configPath) const artifacts = await createArtifacts(config, { tmpRoot, configRoot, resourcesRoot, distRoot }) for (const artifact of artifacts) { logger.log(`Built artifact: ${artifact}`) } return artifacts } catch (err) { logger.error(err) throw err } } const createArtifacts = async ( { name, version, platform, include = {}, artifacts = [] }, { tmpRoot, configRoot, resourcesRoot, distRoot } ) => { if (!tmpRoot) throw new Error('Missing tmpRoot') if (!configRoot) throw new Error('Missing configRoot') if (!distRoot) throw new Error('Missing distRoot') const srcZipPath = path.resolve(tmpRoot, zipName({ name, version, platform })) const srcZipBuffer = await fs.promises.readFile(srcZipPath) const createArtifact = createArtifactFrom( srcZipBuffer, configRoot, resourcesRoot, distRoot ) await mkdirp(path.resolve(distRoot)) return Promise.all(artifacts.map(normalizeInput(include)).map(createArtifact)) } const normalizeInput = (include) => (input) => { if (typeof input === 'string') return { name: input, ...include } const { name, ...rest } = input return { name, ...mergeArrayProps(rest, include) } } const createArtifactFrom = (srcZipBuffer, configRoot, resourcesRoot, distRoot) => async (artifact) => { const data = await loadArtifactConfig(configRoot, resourcesRoot, artifact) const artifactBuffer = await generateZipFrom(srcZipBuffer, [ { name: staticConfigName, data } ]) const outputName = `${artifact.name}.zip` const outputPath = path.resolve(distRoot, outputName) await fs.promises.writeFile(outputPath, artifactBuffer) return outputPath } const loadArtifactConfig = async ( configRoot, resourcesRoot, { name, ...rest } ) => { const resources = Object.entries(rest).reduce(reduceResources, []) const [config, resourceConfig] = await Promise.all([ loadYaml(path.resolve(configRoot, `${name}.yaml`)), loadResources(resourcesRoot, resources) ]) const data = mergeConfig(resourceConfig, config) return yamlDump(data) } const reduceResources = (accumulator, [root, names]) => { const paths = names .map((name) => path.join(...name.split('/'))) .map((name) => path.join(root, name)) return [...accumulator, ...paths] } const loadResources = async (resourcesRoot, resources) => { const loadResource = (name) => loadYaml(path.resolve(resourcesRoot, `${name}.yaml`)) const data = await Promise.all(resources.map(loadResource)) return data.reduce(mergeConfig, { input_resources: [], cache_resources: [], rate_limit_resources: [], processor_resources: [], output_resources: [] }) } const loadYaml = async (name) => { const buf = await fs.promises.readFile(path.resolve(name)) return yamlLoad(buf) } const generateZipFrom = async (srcZipBuffer, files = []) => { const zip = await zipLoadAsync(srcZipBuffer) for (const { name, data } of files) { zip.file(name, data, { unixPermissions: '644' }) } return zip.generateAsync({ type: 'nodebuffer', compression: 'DEFLATE', platform: process.platform }) }