-
Notifications
You must be signed in to change notification settings - Fork 1
/
index.js
129 lines (119 loc) · 4.35 KB
/
index.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
'use strict'
const fs = require('fs')
const path = require('path')
const parse = require('parse-gitignore')
const findUp = require('find-up')
const ignore = require('ignore')
const merge = require('lodash/merge')
const Utils = require('serverless/lib/classes/utils')
const getDirInfo = (folderPath) => {
const dirExists = fs.existsSync(folderPath)
if (!dirExists) return []
return fs.readdirSync(folderPath).map(f => {
const newPath = `${folderPath}/${f}`
const fStats = fs.statSync(newPath)
return {
dir: folderPath,
path: newPath,
file: f,
isFile: fStats.isFile(),
isDir: fStats.isDirectory()
}
})
}
function getContentFactory (serverless) {
return (absolutePath) => {
let content
const isYml = absolutePath.match(/.*\.yml/i) || absolutePath.match(/.*\.yaml/i)
if (isYml) {
content = serverless.utils.readFileSync(absolutePath)
}
const isJsOrJSON = absolutePath.match(/.*\.js/i) || absolutePath.match(/.*\.ts/i) || absolutePath.match(/.*\.json/i)
if (isJsOrJSON) {
const jsRequire = require(absolutePath)
if (typeof jsRequire === 'function') {
content = jsRequire(serverless)
} else {
content = jsRequire
}
}
return content
}
}
const findResourceInDirectoryInfosFactory = (serverless, matchPatterns, ignorePatterns, getContent, asFileArray = false) => {
const ig = ignore().add(ignorePatterns)
const ig2 = ignore().add(matchPatterns)
const findResourceInDirectoryInfos = (dirInfos) => {
const resources = asFileArray ? [] : {}
dirInfos.forEach(dirInfo => {
if (dirInfo.isDir && !ig.ignores(dirInfo.path)) {
const subDirInfos = getDirInfo(dirInfo.path)
const subDirResources = findResourceInDirectoryInfos(subDirInfos)
merge(resources, subDirResources)
} else if (dirInfo.isFile && !ig.ignores(dirInfo.path) && ig2.ignores(dirInfo.path)) {
if (asFileArray) {
resources.push('.' + path.join('/', dirInfo.path))
} else {
var absolutePath = path.resolve(dirInfo.path)
const resourceContent = getContent(absolutePath)
if (resourceContent) {
const contentKeys = Object.keys(resourceContent)
if (!contentKeys) throw new Error('Resource definition missing.')
const existingResourceDefinition = contentKeys.some(k => resources.hasOwnProperty(k))
if (existingResourceDefinition) {
const duplicateResourceDefinition = contentKeys.find(k => resources.hasOwnProperty(k))
serverless.cli.warn(`WARNING: Resource ${duplicateResourceDefinition} has multiple definitions. They will be merged.`)
}
serverless.cli.log(`Including resource definition: ${dirInfo.path}`)
merge(resources, resourceContent)
}
}
}
})
return resources
}
return findResourceInDirectoryInfos
}
const folderResourceReducer = (findResourceInDirectoryInfos) => {
return (resource, folder) => {
const dirInfos = getDirInfo(folder)
const folderResource = findResourceInDirectoryInfos(dirInfos)
return merge(resource, folderResource)
}
}
module.exports = async function (serverless) {
let serverlessMod
let convention = {}
if (serverless.resolveVariable) {
serverlessMod = {
cli: console,
utils: new Utils({})
}
convention = await serverless.resolveVariable('self:custom.convention')
} else {
serverlessMod = serverless
convention = serverless.service.custom.convention
}
const gitignorepath = await findUp('.gitignore')
let ignoreResourcePatterns = []
if (gitignorepath) {
ignoreResourcePatterns = parse(fs.readFileSync(gitignorepath))
}
const getContent = getContentFactory(serverlessMod)
const keys = Object.keys(convention)
let result = keys.reduce((acc, key) => {
if (convention[key].pattern && convention[key].folders) {
const asFileArray = convention[key].asFileArray
const findResourcesInDirInfos = findResourceInDirectoryInfosFactory(serverlessMod,
convention[key].pattern,
ignoreResourcePatterns,
getContent,
asFileArray)
acc[key] = convention[key].folders.reduce(folderResourceReducer(findResourcesInDirInfos), asFileArray ? [] : {})
} else {
throw new Error(`Include "${key}" is missing pattern or folders.`)
}
return acc
}, {})
return result
}