Skip to content

Commit

Permalink
feat: Make additional function attributes available via functions man…
Browse files Browse the repository at this point in the history
…ifest (#1221)

* feat: pass additional-function-attributes

* chore: make attributes available to functions manifest

* fix: fix linting

* fix: use optional chaining

* fix: add ext

* fix: fix tests

* fix: change internal directory name in constants.ts

* feat: add test for go functions with displayName and from an internal functions folder

* feat: add test for rust functions build from internal folder with displayName property

* feat: add test for nodejs functions build from internal folder with displayName property

* test: figure out windows breakn

* fix: take windows paths into account when checking for internal functions

* test: add unit test for checkIsInternalFunction

* docs: add new return values

* test: move tests into a better fixtures structure

* fix: use unixify for checkIsInternalFunction, config, bundler, module and resolve

* feat: add internalFunctionsFolder option to zipfunctionoptions

* test: fix tests

* test: add test for zipFunction and code to support that as well

* test: change toBeTruthy to toBe(true) and isInternalFunction to internalFunction

* chore: change displayName input to name

* chore: change internalFunction to isInternal

* chore: revert unixify, rename tests and internalFunctionsFolder to internalSrcFolder

* test: revert unixify for module to see if windows test still fails

* Revert "test: revert unixify for module to see if windows test still fails"

This reverts commit b444d1c.

Co-authored-by: khen <30577427+khendrikse@users.noreply.github.com>
  • Loading branch information
jackiewmacharia and khendrikse committed Jan 12, 2023
1 parent de48712 commit ea4008e
Show file tree
Hide file tree
Showing 25 changed files with 1,722 additions and 7 deletions.
25 changes: 22 additions & 3 deletions README.md
Expand Up @@ -150,6 +150,10 @@ The following properties are accepted:
The `[name]` placeholder will be replaced by the name of the function, allowing you to use it to construct the path to
the target directory.

- `name`

A name to use when displaying the function in the Netlify UI. Populates the `displayName` property in the functions manifest for the specified function.

#### `featureFlags`

See [feature flags](#feature-flags).
Expand All @@ -159,7 +163,7 @@ See [feature flags](#feature-flags).
- _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
Defines the full path, including the file name, to use for the manifest file that will be created with the functions bundling results. For example, `path/to/manifest.json`. 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`
Expand All @@ -172,11 +176,18 @@ JSON-formatted string with the following properties:

#### `parallelLimit`

- _Type_: `number`\
- _Type_: `number`
- _Default value_: `5`

Maximum number of functions to bundle at the same time.

#### `internalSrcFolder`

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

Defines the path to the folder with internal functions. Used to populate a function's `isInternal` property, if its path is within this specified internal functions folder.

### Return value

This returns a `Promise` resolving to an array of objects describing each archive. Every object has the following
Expand All @@ -202,6 +213,14 @@ properties.

The size of the generated archive, in bytes.

- `isInternal` `boolean`

If the function path has a match with the `internalSrcFolder` property, this boolean will be true.

- `displayName` `string`

If there was a user-defined configuration object applied to the function, and it had a `name` defined. This will be returned here.

Additionally, the following properties also exist for Node.js functions:

- `bundler`: `string`
Expand Down Expand Up @@ -257,7 +276,7 @@ Additionally, the following properties also exist for Node.js functions:
```js
import { zipFunction } from '@netlify/zip-it-and-ship-it'

const archive = await zipFunctions('functions/function.js', 'functions-dist')
const archive = await zipFunction('functions/function.js', 'functions-dist')
```

This is like [`zipFunctions()`](#zipfunctionssrcfolder-destfolder-options) except it bundles a single Function.
Expand Down
1 change: 1 addition & 0 deletions src/config.ts
Expand Up @@ -24,6 +24,7 @@ interface FunctionConfig {
rustTargetDirectory?: string
schedule?: string
zipGo?: boolean
name?: string

// Temporary configuration property, only meant to be used by the deploy
// configuration API. Once we start emitting ESM files for all ESM functions,
Expand Down
17 changes: 16 additions & 1 deletion src/manifest.ts
Expand Up @@ -10,6 +10,9 @@ interface ManifestFunction {
path: string
runtime: string
schedule?: string
displayName?: string
bundler?: string
isInternal?: boolean
}

export interface Manifest {
Expand All @@ -36,10 +39,22 @@ export const createManifest = async ({ functions, path }: { functions: FunctionR
await fs.writeFile(path, JSON.stringify(payload))
}

const formatFunctionForManifest = ({ mainFile, name, path, runtime, schedule }: FunctionResult): ManifestFunction => ({
const formatFunctionForManifest = ({
mainFile,
name,
path,
runtime,
schedule,
displayName,
bundler,
isInternal,
}: FunctionResult): ManifestFunction => ({
mainFile,
name,
path: resolve(path),
runtime,
schedule,
displayName,
bundler,
isInternal,
})
18 changes: 16 additions & 2 deletions src/runtimes/go/index.ts
Expand Up @@ -109,7 +109,16 @@ const processSource = async ({
}
}

const zipFunction: ZipFunction = async function ({ config, destFolder, filename, mainFile, srcDir, srcPath, stat }) {
const zipFunction: ZipFunction = async function ({
config,
destFolder,
filename,
mainFile,
srcDir,
srcPath,
stat,
isInternal,
}) {
const destPath = join(destFolder, filename)
const isSource = extname(mainFile) === '.go'

Expand Down Expand Up @@ -151,7 +160,12 @@ const zipFunction: ZipFunction = async function ({ config, destFolder, filename,
await copyFile(binary.path, destPath)
}

return { config, path: destPath }
return {
config,
path: destPath,
displayName: config?.name,
isInternal,
}
}

const runtime: Runtime = { findFunctionsInPaths, findFunctionInPath, name: RuntimeType.GO, zipFunction }
Expand Down
3 changes: 3 additions & 0 deletions src/runtimes/node/index.ts
Expand Up @@ -45,6 +45,7 @@ const zipFunction: ZipFunction = async function ({
srcDir,
srcPath,
stat,
isInternal,
}) {
const pluginsModulesPath = await getPluginsModulesPath(srcDir)
const bundlerName = await getBundlerName({
Expand Down Expand Up @@ -126,6 +127,8 @@ const zipFunction: ZipFunction = async function ({
nativeNodeModules,
nodeModulesWithDynamicImports,
path: zipPath,
displayName: config?.name,
isInternal,
}
}

Expand Down
3 changes: 3 additions & 0 deletions src/runtimes/runtime.ts
Expand Up @@ -45,6 +45,8 @@ export interface ZipFunctionResult {
nativeNodeModules?: object
nodeModulesWithDynamicImports?: string[]
path: string
isInternal?: boolean
displayName?: string
}

export type ZipFunction = (
Expand All @@ -56,6 +58,7 @@ export type ZipFunction = (
destFolder: string
featureFlags: FeatureFlags
repositoryRoot?: string
isInternal?: boolean
} & FunctionSource,
) => Promise<ZipFunctionResult>

Expand Down
8 changes: 7 additions & 1 deletion src/runtimes/rust/index.ts
Expand Up @@ -137,6 +137,7 @@ const zipFunction: ZipFunction = async function ({
srcDir,
srcPath,
stat,
isInternal,
}) {
const destPath = join(destFolder, `${filename}.zip`)
const isSource = extname(mainFile) === '.rs'
Expand All @@ -157,7 +158,12 @@ const zipFunction: ZipFunction = async function ({
await zipBinary({ ...zipOptions, srcPath, stat })
}

return { config, path: destPath }
return {
config,
path: destPath,
displayName: config?.name,
isInternal,
}
}

const runtime: Runtime = { findFunctionsInPaths, findFunctionInPath, name: RuntimeType.RUST, zipFunction }
Expand Down
10 changes: 10 additions & 0 deletions src/zip.ts
@@ -1,6 +1,7 @@
import { promises as fs } from 'fs'
import { resolve } from 'path'

import isPathInside from 'is-path-inside'
import pMap from 'p-map'

import { ArchiveFormat } from './archive.js'
Expand All @@ -27,12 +28,14 @@ interface ZipFunctionOptions {
zipGo?: boolean
systemLog?: LogFunction
debug?: boolean
internalSrcFolder?: string
}

export type ZipFunctionsOptions = ZipFunctionOptions & {
configFileDirectories?: string[]
manifest?: string
parallelLimit?: number
internalSrcFolder?: string
}

const DEFAULT_PARALLEL_LIMIT = 5
Expand Down Expand Up @@ -60,6 +63,7 @@ export const zipFunctions = async function (
repositoryRoot = basePath,
systemLog,
debug,
internalSrcFolder,
}: ZipFunctionsOptions = {},
) {
validateArchiveFormat(archiveFormat)
Expand All @@ -68,6 +72,8 @@ export const zipFunctions = async function (
const cache = new RuntimeCache()
const featureFlags = getFlags(inputFeatureFlags)
const srcFolders = resolveFunctionsDirectories(relativeSrcFolders)
const internalFunctionsPath = internalSrcFolder && resolve(internalSrcFolder)

const [paths] = await Promise.all([listFunctionsDirectories(srcFolders), fs.mkdir(destFolder, { recursive: true })])
const functions = await getFunctionsFromPaths(paths, {
cache,
Expand Down Expand Up @@ -104,6 +110,7 @@ export const zipFunctions = async function (
srcDir: func.srcDir,
srcPath: func.srcPath,
stat: func.stat,
isInternal: Boolean(internalFunctionsPath && isPathInside(func.srcPath, internalFunctionsPath)),
})
const durationNs = endTimer(startIntervalTime)
const logObject = {
Expand Down Expand Up @@ -148,6 +155,7 @@ export const zipFunction = async function (
repositoryRoot = basePath,
systemLog,
debug,
internalSrcFolder,
}: ZipFunctionOptions = {},
) {
validateArchiveFormat(archiveFormat)
Expand All @@ -157,6 +165,7 @@ export const zipFunction = async function (
const srcPath = resolve(relativeSrcPath)
const cache = new RuntimeCache()
const functions = await getFunctionsFromPaths([srcPath], { cache, config: inputConfig, dedupe: true, featureFlags })
const internalFunctionsPath = internalSrcFolder && resolve(internalSrcFolder)

if (functions.size === 0) {
return
Expand Down Expand Up @@ -199,6 +208,7 @@ export const zipFunction = async function (
srcDir,
srcPath,
stat: stats,
isInternal: Boolean(internalFunctionsPath && isPathInside(srcPath, internalFunctionsPath)),
})
const durationNs = endTimer(startIntervalTime)
const logObject = {
Expand Down
@@ -0,0 +1,9 @@
package main

import (
"fmt"
)

func main() {
fmt.Println("Hello, world!")
}
@@ -0,0 +1,9 @@
package main

import (
"fmt"
)

func main() {
fmt.Println("Hello, world!")
}
@@ -0,0 +1,3 @@
module github.com/netlify/zip-it-and-ship-it/tests/fixtures/go-source

go 1.15
Empty file.
1 change: 1 addition & 0 deletions tests/fixtures/node-display-name/function-1.js
@@ -0,0 +1 @@
module.exports = true
@@ -0,0 +1 @@
module.exports = true
@@ -0,0 +1 @@
module.exports = true
@@ -0,0 +1 @@
/target

1 comment on commit ea4008e

@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: 2.1s
  • largeDepsNft: 8.1s
  • largeDepsZisi: 15.5s

Please sign in to comment.