Skip to content
This repository has been archived by the owner on May 22, 2024. It is now read-only.

Commit

Permalink
feat: add support for manifest file (#601)
Browse files Browse the repository at this point in the history
* feat: add support for manifest file

* chore: add `manifest` to README

* chore: update README

* refactor: make path property absolute

* chore: fix test

* chore: doh

* refactor: propagate errors from manifest creation

* refactor: conditionally create manifest
  • Loading branch information
eduardoboucas committed Aug 2, 2021
1 parent e6490d6 commit 65c4b94
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 5 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,22 @@ The following properties are accepted:

See [feature flags](#feature-flags).

#### `manifest`

- _Type_: `string`
- _Default value_: `undefined`

Defines the path for a manifest file to be created with the results of the functions bundling. This file is a
JSON-formatted string with the following properties:

- `functions`: An array with the functions created, in the same format as returned by `zipFunctions`
- `system.arch`: The operating system CPU architecture, as returned by
[`process.arch`](https://nodejs.org/api/process.html#process_process_arch)
- `system.platform`: The operating system, as returned by
[`process.platform`](https://nodejs.org/api/process.html#process_process_platform)
- `timestamp`: The timestamp (in milliseconds) at the time of the functions bundling process
- `version`: The version of the manifest file (current version is `1`)

#### `parallelLimit`

- _Type_: `number`\
Expand Down
4 changes: 4 additions & 0 deletions src/bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ const OPTIONS = {
describe:
'An object matching glob-like expressions to objects containing configuration properties. Whenever a function name matches one of the expressions, it inherits the configuration properties',
},
manifest: {
string: true,
describe: 'If a manifest file is to be created, specifies its path',
},
'parallel-limit': {
number: true,
describe: 'Maximum number of Functions to bundle at the same time',
Expand Down
22 changes: 22 additions & 0 deletions src/manifest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
const { resolve } = require('path')
const { arch, platform } = require('process')

const { writeFile } = require('./utils/fs')

const MANIFEST_VERSION = 1

const createManifest = async ({ functions, path }) => {
const formattedFunctions = functions.map(formatFunction)
const payload = {
functions: formattedFunctions,
system: { arch, platform },
timestamp: Date.now(),
version: MANIFEST_VERSION,
}

await writeFile(path, JSON.stringify(payload))
}

const formatFunction = (fn) => ({ ...fn, path: resolve(fn.path) })

module.exports = { createManifest }
4 changes: 3 additions & 1 deletion src/utils/fs.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
const { lstat, readdir, readFile, unlink } = require('fs')
const { lstat, readdir, readFile, unlink, writeFile } = require('fs')
const { format, join, parse, resolve } = require('path')
const { promisify } = require('util')

const pLstat = promisify(lstat)
const pReaddir = promisify(readdir)
const pReadFile = promisify(readFile)
const pUnlink = promisify(unlink)
const pWriteFile = promisify(writeFile)

// This caches multiple FS calls to the same path. It creates a cache key with
// the name of the function and the path (e.g. "readdir:/some/directory").
Expand Down Expand Up @@ -83,4 +84,5 @@ module.exports = {
listFunctionsDirectory,
resolveFunctionsDirectories,
safeUnlink,
writeFile: pWriteFile,
}
12 changes: 10 additions & 2 deletions src/zip.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ const makeDir = require('make-dir')
const pMap = require('p-map')

const { getFlags } = require('./feature_flags')
const { createManifest } = require('./manifest')
const { getPluginsModulesPath } = require('./node_dependencies')
const { getFunctionsFromPaths } = require('./runtimes')
const { ARCHIVE_FORMAT_NONE, ARCHIVE_FORMAT_ZIP } = require('./utils/consts')
Expand Down Expand Up @@ -59,6 +60,7 @@ const zipFunctions = async function (
basePath,
config = {},
featureFlags: inputFeatureFlags,
manifest,
parallelLimit = DEFAULT_PARALLEL_LIMIT,
} = {},
) {
Expand All @@ -75,7 +77,7 @@ const zipFunctions = async function (
// source directories.
getPluginsModulesPath(srcFolders[0]),
])
const zipped = await pMap(
const results = await pMap(
functions.values(),
async (func) => {
const zipResult = await func.runtime.zipFunction({
Expand All @@ -100,7 +102,13 @@ const zipFunctions = async function (
concurrency: parallelLimit,
},
)
return zipped.filter(Boolean).map(formatZipResult)
const formattedResults = results.filter(Boolean).map(formatZipResult)

if (manifest !== undefined) {
await createManifest({ functions: formattedResults, path: resolve(manifest) })
}

return formattedResults
}

const zipFunction = async function (
Expand Down
26 changes: 24 additions & 2 deletions tests/main.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const { readFile, chmod, symlink, unlink, rename, stat, writeFile } = require('fs')
const { tmpdir } = require('os')
const { dirname, join, normalize, resolve, sep } = require('path')
const { env, platform } = require('process')
const { dirname, isAbsolute, join, normalize, resolve, sep } = require('path')
const { arch, env, platform } = require('process')
const { promisify } = require('util')

const test = require('ava')
Expand Down Expand Up @@ -1748,3 +1748,25 @@ if (platform !== 'win32') {
)
})
}

test('Creates a manifest file with the list of created functions if the `manifest` property is supplied', async (t) => {
const FUNCTIONS_COUNT = 6
const { path: tmpDir } = await getTmpDir({ prefix: 'zip-it-test' })
const manifestPath = join(tmpDir, 'manifest.json')
const { files } = await zipNode(t, 'many-functions', {
length: FUNCTIONS_COUNT,
opts: { manifest: manifestPath },
})

// eslint-disable-next-line import/no-dynamic-require, node/global-require
const manifest = require(manifestPath)

t.deepEqual(files, manifest.functions)
t.is(manifest.version, 1)
t.is(manifest.system.arch, arch)
t.is(manifest.system.platform, platform)
t.is(typeof manifest.timestamp, 'number')

// The `path` property of each function must be an absolute path.
manifest.functions.every(({ path }) => isAbsolute(path))
})

1 comment on commit 65c4b94

@github-actions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⏱ Benchmark results

largeDepsEsbuild: 12.9s

largeDepsZisi: 1m 15s

Please sign in to comment.