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

Commit

Permalink
refactor: migrate components to TypeScript (#751)
Browse files Browse the repository at this point in the history
* refactor: create FunctionSource interface

* refactor: create non_nullable util

* refactor: migrate config util to TypeScript

* refactor: migrate feature_flags to TypeScript

* refactor: migrate Node function finder to TypeScript

* refactor: migrate esbuild bundler_target to TypeScript

* refactor: migrate parser

* refactor: migrate ZISI resolve

* refactor: migrate esbuild special_cases

* refactor: migrate ZISI src_files

* refactor: migrate Node bundlers index

* refactor: migrate esbuild src_files

* refactor: migrate native modules esbuild plugin

* refactor: migrate dynamic imports esbuild plugin

* refactor: migrate esbuild bundler (inner file)

* refactor: migrate esbuild bundler

* refactor: migrate nft bundler

* refactor: migrate ZISI bundler

* refactor: migrate Node runtime entry

* refactor: add missing prop to PackageJson

* refactor: add config properties

* refactor: add Runtime

* refactor: various updates

* refactor: fix linting issues

* chore: fix test

* refactor: use nullish coalescing operator

* refactor: add GlobPattern type

* refactor: use Template Literal type

* refactor: remove duplication of FeatureFlags keys

* refactor: change CleanupFunction type

* refactor: make BundleFunction a type

* refactor: make GetSrcFilesFunction a type

* refactor: use optional chaining operator

* refactor: make FindFunctionsInPathsFunction a type

* refactor: make GetSrcFilesFunction a type

* refactor: make ZipFunction a type

* refactor: fix nonNullable check

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
eduardoboucas and kodiakhq[bot] committed Oct 19, 2021
1 parent 9af28ae commit 076b192
Show file tree
Hide file tree
Showing 30 changed files with 649 additions and 231 deletions.
14 changes: 14 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,11 @@
"yargs": "^16.0.0"
},
"devDependencies": {
"@babel/types": "^7.15.6",
"@netlify/eslint-config-node": "^3.3.3",
"@types/archiver": "^5.1.1",
"@types/end-of-stream": "^1.4.1",
"@types/resolve": "^1.20.1",
"@types/semver": "^7.3.8",
"@types/unixify": "^1.0.0",
"adm-zip": "0.5.5",
Expand Down
36 changes: 32 additions & 4 deletions src/config.js → src/config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,34 @@
const mergeOptions = require('merge-options')
const minimatch = require('minimatch')
import mergeOptions from 'merge-options'
import minimatch from 'minimatch'

const getConfigForFunction = ({ config, func }) => {
import { FunctionSource } from './function'
import type { NodeBundler } from './runtimes/node'

// eslint-disable-next-line no-magic-numbers
type SupportedVersionNumbers = 8 | 10 | 12 | 14
type NodeVersion = `${SupportedVersionNumbers}.x` | `nodejs${SupportedVersionNumbers}.x`

interface FunctionConfig {
externalNodeModules?: string[]
includedFiles?: string[]
includedFilesBasePath?: string
ignoredNodeModules?: string[]
nodeBundler?: NodeBundler
nodeSourcemap?: boolean
nodeVersion?: NodeVersion
processDynamicNodeImports?: boolean
rustTargetDirectory?: string
}

type GlobPattern = string

const getConfigForFunction = ({
config,
func,
}: {
config: Record<GlobPattern, FunctionConfig>
func: FunctionSource
}): FunctionConfig => {
if (!config) {
return {}
}
Expand Down Expand Up @@ -29,4 +56,5 @@ const getConfigForFunction = ({ config, func }) => {
return mergeOptions.apply({ concatArrays: true, ignoreUndefined: true }, matches)
}

module.exports = { getConfigForFunction }
export { getConfigForFunction }
export type { FunctionConfig }
10 changes: 10 additions & 0 deletions src/deps.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,13 @@ declare module 'require-package-name' {
declare module 'is-builtin-module' {
export default function isBuiltInModule(moduleName: string): boolean
}

declare module 'precinct' {
export function paperwork(path: string, { includeCore: boolean }): Promise<string[]>
}

declare module 'read-package-json-fast' {
export default function readPackageJsonFast(
path: string,
): Promise<import('./runtimes/node/utils/package_json').PackageJson>
}
15 changes: 10 additions & 5 deletions src/feature_flags.js → src/feature_flags.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
const { env } = require('process')
import { env } from 'process'

// List of supported flags and their default value.
const FLAGS = {
const FLAGS: Record<string, boolean> = {
buildGoSource: Boolean(env.NETLIFY_EXPERIMENTAL_BUILD_GO_SOURCE),
buildRustSource: Boolean(env.NETLIFY_EXPERIMENTAL_BUILD_RUST_SOURCE),
defaultEsModulesToEsbuild: Boolean(env.NETLIFY_EXPERIMENTAL_DEFAULT_ES_MODULES_TO_ESBUILD),
parseWithEsbuild: false,
}

const getFlags = (input = {}, flags = FLAGS) =>
type FeatureFlag = keyof typeof FLAGS
type FeatureFlags = Record<FeatureFlag, boolean>

// List of supported flags and their default value.

const getFlags = (input: Record<string, boolean> = {}, flags = FLAGS) =>
Object.entries(flags).reduce(
(result, [key, defaultValue]) => ({
...result,
Expand All @@ -17,4 +21,5 @@ const getFlags = (input = {}, flags = FLAGS) =>
{},
)

module.exports = { FLAGS, getFlags }
export { getFlags }
export type { FeatureFlag, FeatureFlags }
17 changes: 17 additions & 0 deletions src/function.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Stats } from 'fs'

interface SourceFile {
extension: string
filename: string
mainFile: string
name: string
srcDir: string
srcPath: string
stat: Stats
}

type FunctionSource = SourceFile & {
runtime: string
}

export { FunctionSource, SourceFile }
2 changes: 1 addition & 1 deletion src/runtimes/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const { extname, basename } = require('path')
const { getConfigForFunction } = require('../config')

const goRuntime = require('./go')
const jsRuntime = require('./node')
const { default: jsRuntime } = require('./node')
const rustRuntime = require('./rust')

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
const { basename, dirname, extname, resolve, join } = require('path')
import { basename, dirname, extname, resolve, join } from 'path'

const esbuild = require('@netlify/esbuild')
const { tmpName } = require('tmp-promise')
import { build, Metafile } from '@netlify/esbuild'
import { tmpName } from 'tmp-promise'

const { JS_BUNDLER_ESBUILD, RUNTIME_JS } = require('../../../../utils/consts')
const { getPathWithExtension, safeUnlink } = require('../../../../utils/fs')
import type { FunctionConfig } from '../../../../config'
import { JS_BUNDLER_ESBUILD, RUNTIME_JS } from '../../../../utils/consts'
import { getPathWithExtension, safeUnlink } from '../../../../utils/fs'

const { getBundlerTarget } = require('./bundler_target')
const { getDynamicImportsPlugin } = require('./plugin_dynamic_imports')
const { getNativeModulesPlugin } = require('./plugin_native_modules')
import { getBundlerTarget } from './bundler_target'
import { getDynamicImportsPlugin } from './plugin_dynamic_imports'
import { getNativeModulesPlugin } from './plugin_native_modules'

// Maximum number of log messages that an esbuild instance will produce. This
// limit is important to avoid out-of-memory errors due to too much data being
Expand All @@ -29,6 +30,15 @@ const bundleJsFile = async function ({
name,
srcDir,
srcFile,
}: {
additionalModulePaths?: string[]
basePath: string
config: FunctionConfig
externalModules: string[]
ignoredModules: string[]
name: string
srcDir: string
srcFile: string
}) {
// We use a temporary directory as the destination for esbuild files to avoid
// any naming conflicts with files generated by other functions.
Expand All @@ -43,12 +53,12 @@ const bundleJsFile = async function ({

// To be populated by the dynamic imports plugin with the names of the Node
// modules that include imports with dynamic expressions.
const nodeModulesWithDynamicImports = new Set()
const nodeModulesWithDynamicImports: Set<string> = new Set()

// To be populated by the dynamic imports plugin with any paths (in a glob
// format) to be included in the bundle in order to make a dynamic import
// work at runtime.
const dynamicImportsIncludedPaths = new Set()
const dynamicImportsIncludedPaths: Set<string> = new Set()

// The list of esbuild plugins to enable for this build.
const plugins = [
Expand All @@ -72,7 +82,7 @@ const bundleJsFile = async function ({
const sourceRoot = targetDirectory.replace(/\\/g, '/')

try {
const { metafile, warnings } = await esbuild.build({
const { metafile = { inputs: {}, outputs: {} }, warnings } = await build({
bundle: true,
entryPoints: [srcFile],
external,
Expand Down Expand Up @@ -119,10 +129,18 @@ const bundleJsFile = async function ({
// absolute paths of the generated files as keys, and the paths that those
// files should take in the generated bundle as values. This is compatible
// with the `aliases` format used upstream.
const getBundlePaths = ({ destFolder, outputs, srcFile }) => {
const getBundlePaths = ({
destFolder,
outputs,
srcFile,
}: {
destFolder: string
outputs: Metafile['outputs']
srcFile: string
}) => {
const bundleFilename = `${basename(srcFile, extname(srcFile))}.js`
const mainFileDirectory = dirname(srcFile)
const bundlePaths = new Map()
const bundlePaths: Map<string, string> = new Map()

// The paths returned by esbuild are relative to the current directory, which
// is a problem on Windows if the target directory is in a different drive
Expand All @@ -147,8 +165,8 @@ const getBundlePaths = ({ destFolder, outputs, srcFile }) => {
return bundlePaths
}

const getCleanupFunction = (paths) => async () => {
const getCleanupFunction = (paths: string[]) => async () => {
await Promise.all(paths.filter(Boolean).map(safeUnlink))
}

module.exports = { bundleJsFile, ESBUILD_LOG_LIMIT }
export { bundleJsFile, ESBUILD_LOG_LIMIT }
22 changes: 0 additions & 22 deletions src/runtimes/node/bundlers/esbuild/bundler_target.js

This file was deleted.

29 changes: 29 additions & 0 deletions src/runtimes/node/bundlers/esbuild/bundler_target.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
const DEFAULT_VERSION = 'node12'

const versionMap = {
'8.x': 'node8',
'10.x': 'node10',
'12.x': 'node12',
'14.x': 'node14',
} as const

type VersionKeys = keyof typeof versionMap
type VersionValues = typeof versionMap[VersionKeys]

const getBundlerTarget = (suppliedVersion?: string): VersionValues => {
const version = normalizeVersion(suppliedVersion)

if (version && version in versionMap) {
return versionMap[version as VersionKeys]
}

return DEFAULT_VERSION
}

const normalizeVersion = (version?: string) => {
const match = version && version.match(/^nodejs(.*)$/)

return match ? match[1] : version
}

export { getBundlerTarget }

1 comment on commit 076b192

@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: 9s

largeDepsNft: 58.1s

largeDepsZisi: 1m 13.3s

Please sign in to comment.