@architect/inventory 2.2.1-RC.0 → 3.0.0-RC.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/changelog.md +54 -1
- package/package.json +12 -10
- package/readme.md +5 -4
- package/src/config/_upsert.js +1 -1
- package/src/config/arc.js +3 -3
- package/src/config/pragmas/app.js +1 -1
- package/src/config/pragmas/events.js +3 -2
- package/src/config/pragmas/http.js +5 -4
- package/src/config/pragmas/index.js +16 -5
- package/src/config/pragmas/meta/custom-lambdas.js +10 -0
- package/src/config/pragmas/{src-dirs.js → meta/src-dirs.js} +13 -10
- package/src/config/pragmas/plugins.js +109 -4
- package/src/config/pragmas/populate-lambda/_custom-lambdas.js +10 -0
- package/src/config/pragmas/populate-lambda/_events.js +17 -11
- package/src/config/pragmas/populate-lambda/_http.js +18 -10
- package/src/config/pragmas/populate-lambda/_scheduled.js +18 -10
- package/src/config/pragmas/populate-lambda/_tables-streams.js +20 -23
- package/src/config/pragmas/populate-lambda/_ws.js +26 -0
- package/src/config/pragmas/populate-lambda/get-handler.js +86 -13
- package/src/config/pragmas/populate-lambda/get-lambda.js +23 -0
- package/src/config/pragmas/populate-lambda/get-runtime.js +8 -7
- package/src/config/pragmas/populate-lambda/index.js +134 -84
- package/src/config/pragmas/queues.js +3 -2
- package/src/config/pragmas/scheduled.js +3 -2
- package/src/config/pragmas/shared.js +41 -44
- package/src/config/pragmas/sort/http.js +3 -2
- package/src/config/pragmas/static.js +5 -4
- package/src/config/pragmas/tables-indexes.js +3 -10
- package/src/config/pragmas/tables-streams.js +7 -5
- package/src/config/pragmas/tables.js +1 -1
- package/src/config/pragmas/validate/_events.js +1 -1
- package/src/config/pragmas/validate/_http.js +4 -4
- package/src/config/pragmas/validate/_lib.js +3 -10
- package/src/config/pragmas/validate/_scheduled.js +2 -2
- package/src/config/pragmas/validate/_shared.js +1 -1
- package/src/config/pragmas/validate/_tables-streams.js +6 -8
- package/src/config/pragmas/validate/_tables.js +2 -2
- package/src/config/pragmas/validate/index.js +2 -2
- package/src/config/pragmas/views.js +39 -37
- package/src/config/pragmas/ws.js +6 -4
- package/src/config/project/index.js +36 -20
- package/src/config/project/plugins/env.js +71 -0
- package/src/config/project/plugins/index.js +7 -0
- package/src/config/project/plugins/runtimes.js +67 -0
- package/src/config/project/prefs/dotenv.js +81 -0
- package/src/config/project/{prefs.js → prefs/index.js} +41 -22
- package/src/config/project/validate/index.js +15 -8
- package/src/defaults/index.js +20 -13
- package/src/env/index.js +76 -61
- package/src/get.js +1 -2
- package/src/index.js +17 -15
- package/src/lib/asap-src.js +3 -3
- package/src/lib/error-fmt.js +2 -10
- package/src/lib/get-lambda-dirs.js +37 -0
- package/src/lib/index.js +42 -0
- package/src/lib/is.js +3 -1
- package/src/lib/merge-env-vars.js +32 -0
- package/src/lib/pragmas.js +19 -3
- package/src/read/index.js +1 -3
- package/src/read/reader.js +2 -2
- package/src/validate/config.js +12 -6
- package/src/validate/index.js +17 -18
- package/src/validate/layers.js +2 -2
- package/src/validate/paths.js +17 -0
- package/src/validate/tables-children.js +5 -5
- package/src/config/pragmas/indexes.js +0 -19
- package/src/config/pragmas/macros.js +0 -5
- package/src/config/pragmas/populate-lambda/_plugins.js +0 -25
- package/src/config/pragmas/populate-lambda/_websockets.js +0 -19
- package/src/config/project/plugins.js +0 -31
- package/src/lib/http-methods.js +0 -2
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
let populate = require('./populate-lambda')
|
|
2
2
|
let validate = require('./validate')
|
|
3
|
-
let is = require('../../lib
|
|
3
|
+
let { is } = require('../../lib')
|
|
4
|
+
let ts = 'tables-streams'
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* `@tables-streams`
|
|
@@ -9,8 +10,9 @@ let is = require('../../lib/is')
|
|
|
9
10
|
* - If a project has an existing `@tables` Lambda, we'll continue using that so long as the directory exists
|
|
10
11
|
*/
|
|
11
12
|
module.exports = function configureTablesStreams ({ arc, inventory, errors }) {
|
|
12
|
-
|
|
13
|
-
if (arc[
|
|
13
|
+
let tablesStreamsPlugins = inventory.plugins?._methods?.set?.[ts]
|
|
14
|
+
if (!arc[ts]?.length && !tablesStreamsPlugins?.length && !arc.tables?.length) return null
|
|
15
|
+
if ((arc[ts] || tablesStreamsPlugins) && !arc.tables) {
|
|
14
16
|
errors.push(`Specifying @tables-streams requires specifying corresponding @tables`)
|
|
15
17
|
return null
|
|
16
18
|
}
|
|
@@ -18,12 +20,12 @@ module.exports = function configureTablesStreams ({ arc, inventory, errors }) {
|
|
|
18
20
|
// Populate @tables
|
|
19
21
|
let tables = arc.tables.filter(t => is.object(t) && t[Object.keys(t)[0]].stream === true)
|
|
20
22
|
if (tables.length) {
|
|
21
|
-
tables = populate.tables(
|
|
23
|
+
tables = populate.tables({ arc, inventory, errors, pragma: tables })
|
|
22
24
|
}
|
|
23
25
|
else tables = null
|
|
24
26
|
|
|
25
27
|
// Populate @tables-streams
|
|
26
|
-
let streams = populate[
|
|
28
|
+
let streams = populate[ts]({ arc, inventory, errors })
|
|
27
29
|
|
|
28
30
|
if (tables && streams) {
|
|
29
31
|
let uniqueTables = tables.filter(t => !streams.some(s => s.table === t.table))
|
|
@@ -8,7 +8,7 @@ let { regex, size, unique } = require('./_lib')
|
|
|
8
8
|
* See: https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/sqs-message-metadata.html
|
|
9
9
|
*/
|
|
10
10
|
module.exports = function validateEventsAndQueues (pragma, pragmaName, errors) {
|
|
11
|
-
if (pragma
|
|
11
|
+
if (pragma?.length) {
|
|
12
12
|
unique(pragma, pragmaName, errors)
|
|
13
13
|
|
|
14
14
|
pragma.forEach(event => {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
let { unique } = require('./_lib')
|
|
2
|
-
let
|
|
2
|
+
let { httpMethods } = require('../../../lib')
|
|
3
3
|
|
|
4
4
|
module.exports = function validateHTTP (http, errors) {
|
|
5
|
-
if (http
|
|
5
|
+
if (http?.length) {
|
|
6
6
|
unique(http, '@http routes', errors)
|
|
7
7
|
|
|
8
|
-
let validMethod = str =>
|
|
8
|
+
let validMethod = str => httpMethods.includes(str.toLowerCase())
|
|
9
9
|
let validPath = str => str.match(/^\/[a-zA-Z0-9/\-:._\*]*$/)
|
|
10
10
|
http.forEach(route => {
|
|
11
11
|
let { name, method, path } = route
|
|
@@ -49,7 +49,7 @@ module.exports = function validateHTTP (http, errors) {
|
|
|
49
49
|
let params = path.match(/\/:/g)
|
|
50
50
|
if (params) {
|
|
51
51
|
// Params cannot have non-alphanumeric characters
|
|
52
|
-
let match = path.match(/\/:[
|
|
52
|
+
let match = path.match(/\/:[\w.-]+(\/|$)/g)
|
|
53
53
|
if (!match) errors.push(`Invalid @http path (parameters must have only alphanumeric characters): ${name}`)
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -1,15 +1,8 @@
|
|
|
1
|
-
let is = require('../../../lib
|
|
2
|
-
|
|
3
|
-
let patterns = {
|
|
4
|
-
looseName: new RegExp(/^[a-z][a-zA-Z0-9-_]+$/),
|
|
5
|
-
strictName: new RegExp(/^[a-z][a-z0-9-]+$/),
|
|
6
|
-
// DynamoDB, SNS, SQS
|
|
7
|
-
veryLooseName: new RegExp(/^[a-zA-Z0-9/\-._]*$/),
|
|
8
|
-
}
|
|
1
|
+
let { is, validationPatterns } = require('../../../lib')
|
|
9
2
|
|
|
10
3
|
function regex (value, pattern, pragmaName, errors) {
|
|
11
|
-
if (!
|
|
12
|
-
if (!
|
|
4
|
+
if (!validationPatterns[pattern]) throw ReferenceError(`Invalid validation pattern specified: ${pattern}`)
|
|
5
|
+
if (!validationPatterns[pattern].test(value)) errors.push(`Invalid ${pragmaName} item: '${value}' must match ${validationPatterns[pattern]}`)
|
|
13
6
|
}
|
|
14
7
|
|
|
15
8
|
function size (value, min, max, pragmaName, errors) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
let is = require('../../../lib
|
|
1
|
+
let { is } = require('../../../lib')
|
|
2
2
|
let { regex, size, unique } = require('./_lib')
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -10,7 +10,7 @@ let { regex, size, unique } = require('./_lib')
|
|
|
10
10
|
* See: https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-create-rule-schedule.html
|
|
11
11
|
*/
|
|
12
12
|
module.exports = function validateScheduled (scheduled, errors) {
|
|
13
|
-
if (scheduled
|
|
13
|
+
if (scheduled?.length) {
|
|
14
14
|
unique(scheduled, '@scheduled', errors)
|
|
15
15
|
|
|
16
16
|
scheduled.forEach(schedule => {
|
|
@@ -7,13 +7,11 @@ let { regex, size, unique } = require('./_lib')
|
|
|
7
7
|
* See: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html
|
|
8
8
|
*/
|
|
9
9
|
module.exports = function validateTablesStreams (tablesStreams, errors) {
|
|
10
|
-
|
|
11
|
-
unique(tablesStreams, '@tables-streams', errors)
|
|
10
|
+
unique(tablesStreams, '@tables-streams', errors)
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
12
|
+
tablesStreams.forEach(stream => {
|
|
13
|
+
let { name } = stream
|
|
14
|
+
size(name, 3, 255, '@tables-streams', errors)
|
|
15
|
+
regex(name, 'veryLooseName', '@tables-streams', errors)
|
|
16
|
+
})
|
|
19
17
|
}
|
|
@@ -2,13 +2,13 @@ let { regex, size, unique } = require('./_lib')
|
|
|
2
2
|
let { deepStrictEqual } = require('assert')
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
|
-
* Validate @tables + @indexes
|
|
5
|
+
* Validate @tables + @tables-indexes
|
|
6
6
|
*
|
|
7
7
|
* Where possible, attempts to follow DynamoDB validation
|
|
8
8
|
* See: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.NamingRulesDataTypes.html
|
|
9
9
|
*/
|
|
10
10
|
module.exports = function validateTablesAndIndexes (pragma, pragmaName, errors) {
|
|
11
|
-
if (pragma
|
|
11
|
+
if (pragma?.length) {
|
|
12
12
|
pragma.forEach(table => {
|
|
13
13
|
let { name, indexName, partitionKey, sortKey } = table
|
|
14
14
|
|
|
@@ -4,12 +4,12 @@ module.exports = {
|
|
|
4
4
|
aws: require('./_aws'),
|
|
5
5
|
events: require('./_events'),
|
|
6
6
|
http: require('./_http'),
|
|
7
|
-
indexes: require('./_tables'), // Same ruleset as @tables (more or less)
|
|
8
7
|
proxy: require('./_proxy'),
|
|
9
|
-
tables: require('./_tables'),
|
|
10
8
|
queues: require('./_events'), // Same ruleset as @events
|
|
11
9
|
scheduled: require('./_scheduled'),
|
|
12
10
|
shared: require('./_shared'), // Also includes @views
|
|
11
|
+
tables: require('./_tables'),
|
|
12
|
+
tablesIndexes: require('./_tables'), // Same ruleset as @tables (more or less)
|
|
13
13
|
tablesStreams: require('./_tables-streams'),
|
|
14
14
|
websockets: require('./_websockets'),
|
|
15
15
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
let { join } = require('path')
|
|
2
2
|
let validate = require('./validate')
|
|
3
|
-
let is = require('../../lib
|
|
3
|
+
let { is } = require('../../lib')
|
|
4
4
|
|
|
5
5
|
module.exports = function configureViews ({ arc, pragmas, inventory, errors }) {
|
|
6
6
|
if (arc.views && !arc.http) {
|
|
@@ -9,46 +9,28 @@ module.exports = function configureViews ({ arc, pragmas, inventory, errors }) {
|
|
|
9
9
|
}
|
|
10
10
|
if (!arc.http) return null
|
|
11
11
|
|
|
12
|
-
let cwd = inventory._project
|
|
13
|
-
let src = join(
|
|
12
|
+
let { cwd, src: projSrc } = inventory._project
|
|
13
|
+
let src = join(projSrc, 'views')
|
|
14
14
|
let views = {
|
|
15
15
|
src,
|
|
16
16
|
views: [] // Revert to null later if none are defined
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
// First pass to get + check views folder (if any)
|
|
19
|
+
// First pass to get + check views folder (if any)
|
|
20
|
+
let foundSrc = false
|
|
21
|
+
if (arc?.views?.length) {
|
|
23
22
|
for (let view of arc.views) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if (some) {
|
|
35
|
-
// Reset views settings
|
|
36
|
-
for (let route of pragmas.http) {
|
|
37
|
-
route.config.views = false
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// Set new views settings
|
|
41
|
-
for (let view of arc.views) {
|
|
42
|
-
let method = view[0].toLowerCase()
|
|
43
|
-
let path = view[1]
|
|
44
|
-
if (method === 'src') continue
|
|
45
|
-
let name = `${method} ${path}`
|
|
46
|
-
let route = pragmas.http.find(n => n.name === name)
|
|
47
|
-
if (!route) {
|
|
48
|
-
return errors.push(`@views ${name} not found in @http routes`)
|
|
23
|
+
if (is.array(view)) {
|
|
24
|
+
let key = view[0]?.toLowerCase()
|
|
25
|
+
if (key === 'src' && is.string(view[1])) {
|
|
26
|
+
views.src = view[1]
|
|
27
|
+
foundSrc = true
|
|
28
|
+
validate.shared(views.src, cwd, errors)
|
|
29
|
+
continue
|
|
30
|
+
}
|
|
31
|
+
if (key === 'src' && !is.string(view[1])) {
|
|
32
|
+
errors.push(`@shared invalid setting: ${key}`)
|
|
49
33
|
}
|
|
50
|
-
// Ignore views into ASAP
|
|
51
|
-
if (!route.arcStaticAssetProxy) route.config.views = true
|
|
52
34
|
}
|
|
53
35
|
}
|
|
54
36
|
}
|
|
@@ -56,6 +38,29 @@ module.exports = function configureViews ({ arc, pragmas, inventory, errors }) {
|
|
|
56
38
|
// Exit if default views folder doesn't exist
|
|
57
39
|
if (!is.exists(views.src)) return null
|
|
58
40
|
|
|
41
|
+
// Proceeding from here resets all views config, so make sure it's only if specific views are specified
|
|
42
|
+
let some = arc.views?.length && !(arc?.views?.length === 1 && foundSrc)
|
|
43
|
+
if (some) {
|
|
44
|
+
// Reset views settings
|
|
45
|
+
for (let route of pragmas.http) {
|
|
46
|
+
route.config.views = false
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Set new views settings
|
|
50
|
+
for (let view of arc.views) {
|
|
51
|
+
let method = view?.[0]?.toLowerCase()
|
|
52
|
+
let path = view?.[1]
|
|
53
|
+
if (method === 'src') continue
|
|
54
|
+
let name = `${method} ${path}`
|
|
55
|
+
let route = pragmas.http.find(n => n.name === name)
|
|
56
|
+
if (!route) {
|
|
57
|
+
return errors.push(`@views ${name} not found in @http routes`)
|
|
58
|
+
}
|
|
59
|
+
// Ignore views into ASAP
|
|
60
|
+
if (!route.arcStaticAssetProxy) route.config.views = true
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
59
64
|
// lambda.config.views was added by Lambda populator defaults, or added above
|
|
60
65
|
for (let { src, config } of pragmas.http) {
|
|
61
66
|
if (config.views === true && !views.views.includes(src)) {
|
|
@@ -63,8 +68,5 @@ module.exports = function configureViews ({ arc, pragmas, inventory, errors }) {
|
|
|
63
68
|
}
|
|
64
69
|
}
|
|
65
70
|
|
|
66
|
-
// De-dupe (in case multiple functions live at the same src path)
|
|
67
|
-
views.views = [ ...new Set(views.views) ]
|
|
68
|
-
|
|
69
71
|
return views
|
|
70
72
|
}
|
package/src/config/pragmas/ws.js
CHANGED
|
@@ -2,21 +2,23 @@ let populate = require('./populate-lambda')
|
|
|
2
2
|
let validate = require('./validate')
|
|
3
3
|
|
|
4
4
|
module.exports = function configureWS ({ arc, inventory, errors }) {
|
|
5
|
-
|
|
5
|
+
let wsPlugins = inventory.plugins?._methods?.set?.ws
|
|
6
|
+
if (!arc.ws && !wsPlugins?.length) return null
|
|
6
7
|
|
|
7
|
-
let ws = [
|
|
8
|
+
let ws = [ ]
|
|
9
|
+
if (arc.ws) ws.push(...arc.ws)
|
|
8
10
|
|
|
9
11
|
// Backfill required routes if not already present
|
|
10
12
|
let defaults = [ 'disconnect', 'default', 'connect' ]
|
|
11
13
|
defaults.forEach(route => {
|
|
12
|
-
let found = arc
|
|
14
|
+
let found = arc?.ws?.find(item => {
|
|
13
15
|
if (item === route) return true
|
|
14
16
|
if (item[route]) return true
|
|
15
17
|
})
|
|
16
18
|
if (!found) ws.unshift(route)
|
|
17
19
|
})
|
|
18
20
|
|
|
19
|
-
let websockets = populate.ws(
|
|
21
|
+
let websockets = populate.ws({ arc, inventory, errors, pragma: ws })
|
|
20
22
|
|
|
21
23
|
// Forgive and normalize userland use of '$default', '$connect', '$disconnect'
|
|
22
24
|
websockets.forEach(({ name }, i) => {
|
|
@@ -1,60 +1,76 @@
|
|
|
1
|
+
let { join } = require('path')
|
|
1
2
|
let upsert = require('../_upsert')
|
|
2
3
|
let prefs = require('./prefs')
|
|
3
|
-
let is = require('../../lib/is')
|
|
4
4
|
let plugins = require('./plugins')
|
|
5
|
+
let { is, mergeEnvVars } = require('../../lib')
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* Get the project-level configuration, overlaying arc.aws settings (if present)
|
|
8
9
|
*/
|
|
9
|
-
module.exports = function getProjectConfig (params
|
|
10
|
-
let { arc, raw, filepath, inventory } = params
|
|
11
|
-
let
|
|
10
|
+
module.exports = function getProjectConfig (params) {
|
|
11
|
+
let { arc, errors, raw, filepath, inventory } = params
|
|
12
|
+
let _project = {
|
|
12
13
|
...inventory._project,
|
|
13
14
|
arc,
|
|
14
15
|
raw,
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
if (arc.aws) {
|
|
18
|
-
|
|
19
|
+
_project.defaultFunctionConfig = upsert(_project.defaultFunctionConfig, arc.aws)
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
if (filepath) {
|
|
22
|
-
|
|
23
|
-
// TODO add manifestCreated once we determine we can get birthtime reliably
|
|
23
|
+
_project.manifest = filepath
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
//
|
|
27
|
-
project.plugins = plugins(project, errors)
|
|
28
|
-
|
|
29
|
-
// parse local and global arc preferences
|
|
26
|
+
// Parse local and global project preferences
|
|
30
27
|
let scopes = [ 'global', 'local' ]
|
|
31
28
|
for (let scope of scopes) {
|
|
32
29
|
let p = prefs({ scope, inventory, errors })
|
|
33
30
|
if (p) {
|
|
34
31
|
// Set up the scoped metadata
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
_project[`${scope}Preferences`] = p.preferences
|
|
33
|
+
_project[`${scope}PreferencesFile`] = p.preferencesFile
|
|
37
34
|
|
|
38
35
|
// Build out the final preferences
|
|
39
|
-
/* istanbul ignore else */
|
|
40
|
-
if (!
|
|
36
|
+
/* istanbul ignore else: jic */
|
|
37
|
+
if (!_project.preferences) _project.preferences = {}
|
|
41
38
|
Object.keys(p.preferences).forEach(pragma => {
|
|
42
39
|
// Ignore the raw data
|
|
43
40
|
if (pragma === '_arc' || pragma === '_raw') return
|
|
44
41
|
// Allow booleans, etc.
|
|
45
42
|
if (!is.object(p.preferences[pragma])) {
|
|
46
|
-
|
|
43
|
+
_project.preferences[pragma] = p.preferences[pragma]
|
|
47
44
|
return
|
|
48
45
|
}
|
|
49
46
|
// Traverse and merge individual settings
|
|
50
|
-
/* istanbul ignore else */
|
|
51
|
-
if (!
|
|
47
|
+
/* istanbul ignore else: jic */
|
|
48
|
+
if (!_project.preferences[pragma]) _project.preferences[pragma] = {}
|
|
52
49
|
Object.entries(p.preferences[pragma]).forEach(([ setting, value ]) => {
|
|
53
|
-
|
|
50
|
+
_project.preferences[pragma][setting] = value
|
|
54
51
|
})
|
|
55
52
|
})
|
|
56
53
|
}
|
|
57
54
|
}
|
|
58
55
|
|
|
59
|
-
|
|
56
|
+
// Populate local env from preferences
|
|
57
|
+
if (_project.preferences?.env) {
|
|
58
|
+
_project.env.local = _project.preferences.env
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (inventory.plugins?._methods) {
|
|
62
|
+
_project.env.plugins = plugins.env(params, _project)
|
|
63
|
+
_project.env.local = mergeEnvVars({
|
|
64
|
+
name: 'Local',
|
|
65
|
+
source: _project.env.plugins,
|
|
66
|
+
target: _project.env.local,
|
|
67
|
+
errors,
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
let { build, runtimes } = plugins.runtimes(params, _project)
|
|
71
|
+
if (build) _project.build = join(_project.cwd, build)
|
|
72
|
+
if (runtimes) _project.customRuntimes = runtimes
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return _project
|
|
60
76
|
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
let { deepFrozenCopy } = require('@architect/utils')
|
|
2
|
+
let { is, tidyError, validationPatterns: valid } = require('../../../lib')
|
|
3
|
+
let envs = [ 'testing', 'staging', 'production' ]
|
|
4
|
+
let str = value => {
|
|
5
|
+
if (is.object(value) || is.array(value)) return JSON.stringify(value)
|
|
6
|
+
return String(value)
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
module.exports = function setEnvPlugins (params, project) {
|
|
10
|
+
let { errors, inventory } = params
|
|
11
|
+
let envPlugins = inventory.plugins?._methods?.set?.env
|
|
12
|
+
if (envPlugins?.length) {
|
|
13
|
+
let env = {
|
|
14
|
+
testing: null,
|
|
15
|
+
staging: null,
|
|
16
|
+
production: null,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// inventory._project is not yet built, so provide as much as we can to plugins for now
|
|
20
|
+
let inv = deepFrozenCopy({ ...inventory, _project: project })
|
|
21
|
+
envPlugins.forEach(fn => {
|
|
22
|
+
let errType = `plugin: ${fn.plugin}, method: set.env`
|
|
23
|
+
try {
|
|
24
|
+
let result = fn({ arc: inv._project.arc, inventory: { inv } })
|
|
25
|
+
if (!is.object(result) || !Object.keys(result).length) {
|
|
26
|
+
return errors.push(`Env plugin returned invalid data, must return an Object with one or more keys + values: ${errType}`)
|
|
27
|
+
}
|
|
28
|
+
// Populate env vars based on environment
|
|
29
|
+
// If any keys are environment names, disregard all keys except environment names
|
|
30
|
+
if (Object.keys(result).some(k => envs.includes(k))) {
|
|
31
|
+
envs.forEach(e => {
|
|
32
|
+
if (result[e]) Object.entries(result[e]).forEach(([ k, v ]) => {
|
|
33
|
+
if (!valid.envVar.test(k)) {
|
|
34
|
+
return errors.push(`Env var '${k}' is invalid, must be [a-zA-Z0-9_]`)
|
|
35
|
+
}
|
|
36
|
+
let errored = false, val = str(v)
|
|
37
|
+
if (!env[e]) env[e] = { [k]: val }
|
|
38
|
+
else if (env[e][k] && !errored) {
|
|
39
|
+
errored = true
|
|
40
|
+
errors.push(`Env var '${k}' already registered: ${errType}`)
|
|
41
|
+
}
|
|
42
|
+
else env[e][k] = val
|
|
43
|
+
})
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
// Populate all environments based on env var
|
|
47
|
+
else {
|
|
48
|
+
Object.entries(result).forEach(([ k, v ]) => {
|
|
49
|
+
if (!valid.envVar.test(k)) {
|
|
50
|
+
return errors.push(`Env var '${k}' is invalid, must be [a-zA-Z0-9_]`)
|
|
51
|
+
}
|
|
52
|
+
let errored = false, val = str(v)
|
|
53
|
+
envs.forEach(e => {
|
|
54
|
+
if (!env[e]) env[e] = { [k]: val }
|
|
55
|
+
else if (env[e][k] && !errored) {
|
|
56
|
+
errored = true
|
|
57
|
+
errors.push(`Env var '${k}' already registered: ${errType}`)
|
|
58
|
+
}
|
|
59
|
+
else env[e][k] = val
|
|
60
|
+
})
|
|
61
|
+
})
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
errors.push(`Runtime plugin '${fn.plugin}' failed: ${tidyError(err)}`)
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
return env
|
|
69
|
+
}
|
|
70
|
+
return inventory._project.env.plugins
|
|
71
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
let { aliases, runtimeList } = require('lambda-runtimes')
|
|
2
|
+
let { deepFrozenCopy } = require('@architect/utils')
|
|
3
|
+
let { is, validationPatterns } = require('../../../lib')
|
|
4
|
+
let { looserName } = validationPatterns
|
|
5
|
+
let allRuntimes = runtimeList.concat([ 'deno', ...Object.keys(aliases) ])
|
|
6
|
+
let validTypes = [ 'transpiled', 'compiled', 'interpreted' ]
|
|
7
|
+
let builtTypes = validTypes.filter(t => t !== 'interpreted')
|
|
8
|
+
|
|
9
|
+
module.exports = function setRuntimePlugins (params, project) {
|
|
10
|
+
let { errors, inventory } = params
|
|
11
|
+
let runtimePlugins = inventory.plugins?._methods?.set?.runtimes
|
|
12
|
+
if (runtimePlugins?.length) {
|
|
13
|
+
let runtimes = {
|
|
14
|
+
runtimes: [],
|
|
15
|
+
}
|
|
16
|
+
// inventory._project is not yet built, so provide as much as we can to plugins for now
|
|
17
|
+
let inv = deepFrozenCopy({ ...inventory, _project: project })
|
|
18
|
+
let build
|
|
19
|
+
runtimePlugins.forEach(fn => {
|
|
20
|
+
let errType = `plugin: ${fn.plugin}, method: set.runtimes`
|
|
21
|
+
try {
|
|
22
|
+
var result = fn({ arc: inv._project.arc, inventory: { inv } })
|
|
23
|
+
}
|
|
24
|
+
catch (err) {
|
|
25
|
+
err.message = `Runtime plugin exception: ${errType}`
|
|
26
|
+
+ `\n` + err.message
|
|
27
|
+
throw err
|
|
28
|
+
}
|
|
29
|
+
// Accept one or more results, then loop through them
|
|
30
|
+
result = is.array(result) ? result : [ result ]
|
|
31
|
+
result.forEach(runtime => {
|
|
32
|
+
let { name, type, baseRuntime } = runtime
|
|
33
|
+
if (!name || !looserName.test(name)) {
|
|
34
|
+
let msg = `Runtime plugin must provide a valid name: ${errType}`
|
|
35
|
+
return errors.push(msg)
|
|
36
|
+
}
|
|
37
|
+
if (!type || !validTypes.includes(type)) {
|
|
38
|
+
let msg = `Runtime plugin must provide a valid type: ${errType}`
|
|
39
|
+
return errors.push(msg)
|
|
40
|
+
}
|
|
41
|
+
if (allRuntimes.includes(name)) {
|
|
42
|
+
let msg = `Runtime name '${name}' is reserved: ${errType}`
|
|
43
|
+
return errors.push(msg)
|
|
44
|
+
}
|
|
45
|
+
if (runtimes[name]) {
|
|
46
|
+
let msg = `Runtime name '${name}' already registered: ${errType}`
|
|
47
|
+
return errors.push(msg)
|
|
48
|
+
}
|
|
49
|
+
if (builtTypes.includes(type)) {
|
|
50
|
+
if (build && runtime.build && build !== runtime.build) {
|
|
51
|
+
return errors.push(`Runtime '${name}' cannot set a build directory, as it is already configured to: ${build}`)
|
|
52
|
+
}
|
|
53
|
+
// Adhere to Postel's Law
|
|
54
|
+
build = 'build'
|
|
55
|
+
if (is.string(runtime.build)) build = runtime.build
|
|
56
|
+
}
|
|
57
|
+
if (type === 'transpiled' && !allRuntimes.includes(baseRuntime)) {
|
|
58
|
+
return errors.push(`Runtime '${name}' must include a valid baseRuntime property corresponding to a valid Lambda runtime (e.g. 'nodejs14.x')`)
|
|
59
|
+
}
|
|
60
|
+
runtimes.runtimes.push(name)
|
|
61
|
+
runtimes[name] = runtime
|
|
62
|
+
})
|
|
63
|
+
})
|
|
64
|
+
return { build, runtimes }
|
|
65
|
+
}
|
|
66
|
+
return {}
|
|
67
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// Copyright (c) 2015, Scott Motte
|
|
2
|
+
// All rights reserved.
|
|
3
|
+
|
|
4
|
+
/* istanbul ignore file */
|
|
5
|
+
/* eslint-disable */
|
|
6
|
+
// node_modules/dotenv/lib/main.js
|
|
7
|
+
var fs = require("fs");
|
|
8
|
+
var path = require("path");
|
|
9
|
+
var os = require("os");
|
|
10
|
+
var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
|
|
11
|
+
function parse(src) {
|
|
12
|
+
const obj = {};
|
|
13
|
+
let lines = src.toString();
|
|
14
|
+
lines = lines.replace(/\r\n?/mg, "\n");
|
|
15
|
+
let match;
|
|
16
|
+
while ((match = LINE.exec(lines)) != null) {
|
|
17
|
+
const key = match[1];
|
|
18
|
+
let value = match[2] || "";
|
|
19
|
+
value = value.trim();
|
|
20
|
+
const maybeQuote = value[0];
|
|
21
|
+
value = value.replace(/^(['"])([\s\S]+)\1$/mg, "$2");
|
|
22
|
+
if (maybeQuote === '"') {
|
|
23
|
+
value = value.replace(/\\n/g, "\n");
|
|
24
|
+
value = value.replace(/\\r/g, "\r");
|
|
25
|
+
}
|
|
26
|
+
obj[key] = value;
|
|
27
|
+
}
|
|
28
|
+
return obj;
|
|
29
|
+
}
|
|
30
|
+
function _log(message) {
|
|
31
|
+
console.log(`[dotenv][DEBUG] ${message}`);
|
|
32
|
+
}
|
|
33
|
+
function _resolveHome(envPath) {
|
|
34
|
+
return envPath[0] === "~" ? path.join(os.homedir(), envPath.slice(1)) : envPath;
|
|
35
|
+
}
|
|
36
|
+
function config(options) {
|
|
37
|
+
let dotenvPath = path.resolve(process.cwd(), ".env");
|
|
38
|
+
let encoding = "utf8";
|
|
39
|
+
const debug = Boolean(options && options.debug);
|
|
40
|
+
const override = Boolean(options && options.override);
|
|
41
|
+
if (options) {
|
|
42
|
+
if (options.path != null) {
|
|
43
|
+
dotenvPath = _resolveHome(options.path);
|
|
44
|
+
}
|
|
45
|
+
if (options.encoding != null) {
|
|
46
|
+
encoding = options.encoding;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
const parsed = DotenvModule.parse(fs.readFileSync(dotenvPath, { encoding }));
|
|
51
|
+
Object.keys(parsed).forEach(function(key) {
|
|
52
|
+
if (!Object.prototype.hasOwnProperty.call(process.env, key)) {
|
|
53
|
+
process.env[key] = parsed[key];
|
|
54
|
+
} else {
|
|
55
|
+
if (override === true) {
|
|
56
|
+
process.env[key] = parsed[key];
|
|
57
|
+
}
|
|
58
|
+
if (debug) {
|
|
59
|
+
if (override === true) {
|
|
60
|
+
_log(`"${key}" is already defined in \`process.env\` and WAS overwritten`);
|
|
61
|
+
} else {
|
|
62
|
+
_log(`"${key}" is already defined in \`process.env\` and was NOT overwritten`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
return { parsed };
|
|
68
|
+
} catch (e) {
|
|
69
|
+
if (debug) {
|
|
70
|
+
_log(`Failed to load ${dotenvPath} ${e.message}`);
|
|
71
|
+
}
|
|
72
|
+
return { error: e };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
var DotenvModule = {
|
|
76
|
+
config,
|
|
77
|
+
parse
|
|
78
|
+
};
|
|
79
|
+
module.exports.config = DotenvModule.config;
|
|
80
|
+
module.exports.parse = DotenvModule.parse;
|
|
81
|
+
module.exports = DotenvModule;
|