-
Notifications
You must be signed in to change notification settings - Fork 340
/
hash-fns.js
133 lines (114 loc) · 3.51 KB
/
hash-fns.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
const path = require('path')
const { promisify } = require('util')
const zipIt = require('@netlify/zip-it-and-ship-it')
const fromArray = require('from2-array')
const pump = promisify(require('pump'))
const { hasherCtor, manifestCollectorCtor } = require('./hasher-segments')
// Maximum age of functions manifest (2 minutes).
const MANIFEST_FILE_TTL = 12e4
const getFunctionZips = async ({
directories,
functionsConfig,
manifestPath,
rootDir,
skipFunctionsCache,
statusCb,
tmpDir,
}) => {
statusCb({
type: 'functions-manifest',
msg: 'Looking for a functions cache...',
phase: 'start',
})
if (manifestPath) {
try {
// eslint-disable-next-line import/no-dynamic-require, n/global-require
const { functions, timestamp } = require(manifestPath)
const manifestAge = Date.now() - timestamp
if (manifestAge > MANIFEST_FILE_TTL) {
throw new Error('Manifest expired')
}
statusCb({
type: 'functions-manifest',
msg: 'Deploying functions from cache (use --skip-functions-cache to override)',
phase: 'stop',
})
return functions
} catch {
statusCb({
type: 'functions-manifest',
msg: 'Ignored invalid or expired functions cache',
phase: 'stop',
})
}
} else {
const msg = skipFunctionsCache
? 'Ignoring functions cache (use without --skip-functions-cache to change)'
: 'No cached functions were found'
statusCb({
type: 'functions-manifest',
msg,
phase: 'stop',
})
}
return await zipIt.zipFunctions(directories, tmpDir, { basePath: rootDir, config: functionsConfig })
}
const hashFns = async (
directories,
{
assetType = 'function',
concurrentHash,
functionsConfig,
hashAlgorithm = 'sha256',
manifestPath,
rootDir,
skipFunctionsCache,
statusCb,
tmpDir,
},
) => {
// Early out if no functions directories are configured.
if (directories.length === 0) {
return { functions: {}, functionsWithNativeModules: [], shaMap: {} }
}
if (!tmpDir) {
throw new Error('Missing tmpDir directory for zipping files')
}
const functionZips = await getFunctionZips({
directories,
functionsConfig,
manifestPath,
rootDir,
skipFunctionsCache,
statusCb,
tmpDir,
})
const fileObjs = functionZips.map(({ path: functionPath, runtime }) => ({
filepath: functionPath,
root: tmpDir,
relname: path.relative(tmpDir, functionPath),
basename: path.basename(functionPath),
extname: path.extname(functionPath),
type: 'file',
assetType: 'function',
normalizedPath: path.basename(functionPath, path.extname(functionPath)),
runtime,
}))
const functionSchedules = functionZips
.map(({ name, schedule }) => schedule && { name, cron: schedule })
.filter(Boolean)
const functionsWithNativeModules = functionZips.filter(
({ nativeNodeModules }) => nativeNodeModules !== undefined && Object.keys(nativeNodeModules).length !== 0,
)
const functionStream = fromArray.obj(fileObjs)
const hasher = hasherCtor({ concurrentHash, hashAlgorithm })
// Written to by manifestCollector
// normalizedPath: hash (wanted by deploy API)
const functions = {}
// hash: [fileObj, fileObj, fileObj]
const fnShaMap = {}
const manifestCollector = manifestCollectorCtor(functions, fnShaMap, { statusCb, assetType })
await pump(functionStream, hasher, manifestCollector)
return { functionSchedules, functions, functionsWithNativeModules, fnShaMap }
}
module.exports = { hashFns }