@architect/inventory 2.2.0 → 3.0.0-RC.1

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.
Files changed (62) hide show
  1. package/changelog.md +40 -0
  2. package/package.json +5 -5
  3. package/src/config/_upsert.js +1 -1
  4. package/src/config/pragmas/app.js +1 -1
  5. package/src/config/pragmas/events.js +3 -2
  6. package/src/config/pragmas/http.js +8 -4
  7. package/src/config/pragmas/index.js +16 -5
  8. package/src/config/pragmas/meta/custom-lambdas.js +10 -0
  9. package/src/config/pragmas/{src-dirs.js → meta/src-dirs.js} +13 -10
  10. package/src/config/pragmas/plugins.js +104 -4
  11. package/src/config/pragmas/populate-lambda/_custom-lambdas.js +10 -0
  12. package/src/config/pragmas/populate-lambda/_events.js +17 -11
  13. package/src/config/pragmas/populate-lambda/_http.js +18 -10
  14. package/src/config/pragmas/populate-lambda/_scheduled.js +18 -10
  15. package/src/config/pragmas/populate-lambda/_tables-streams.js +20 -23
  16. package/src/config/pragmas/populate-lambda/_ws.js +26 -0
  17. package/src/config/pragmas/populate-lambda/get-handler.js +86 -13
  18. package/src/config/pragmas/populate-lambda/get-lambda.js +23 -0
  19. package/src/config/pragmas/populate-lambda/get-runtime.js +8 -7
  20. package/src/config/pragmas/populate-lambda/index.js +104 -86
  21. package/src/config/pragmas/queues.js +3 -2
  22. package/src/config/pragmas/scheduled.js +3 -2
  23. package/src/config/pragmas/shared.js +41 -44
  24. package/src/config/pragmas/sort/http.js +72 -0
  25. package/src/config/pragmas/static.js +1 -2
  26. package/src/config/pragmas/tables-indexes.js +3 -10
  27. package/src/config/pragmas/tables-streams.js +7 -5
  28. package/src/config/pragmas/tables.js +1 -1
  29. package/src/config/pragmas/validate/_events.js +1 -1
  30. package/src/config/pragmas/validate/_http.js +4 -4
  31. package/src/config/pragmas/validate/_lib.js +1 -1
  32. package/src/config/pragmas/validate/_scheduled.js +2 -2
  33. package/src/config/pragmas/validate/_shared.js +1 -1
  34. package/src/config/pragmas/validate/_tables-streams.js +6 -8
  35. package/src/config/pragmas/validate/_tables.js +2 -2
  36. package/src/config/pragmas/validate/index.js +2 -2
  37. package/src/config/pragmas/views.js +39 -37
  38. package/src/config/pragmas/ws.js +6 -4
  39. package/src/config/project/index.js +15 -10
  40. package/src/config/project/plugins/index.js +5 -0
  41. package/src/config/project/plugins/runtimes.js +56 -0
  42. package/src/config/project/prefs.js +7 -7
  43. package/src/config/project/validate/index.js +1 -1
  44. package/src/defaults/index.js +13 -11
  45. package/src/env/index.js +1 -1
  46. package/src/get.js +1 -2
  47. package/src/index.js +17 -15
  48. package/src/lib/error-fmt.js +2 -10
  49. package/src/lib/get-lambda-dirs.js +37 -0
  50. package/src/lib/index.js +26 -0
  51. package/src/lib/is.js +3 -1
  52. package/src/lib/pragmas.js +18 -3
  53. package/src/read/reader.js +1 -1
  54. package/src/validate/config.js +12 -6
  55. package/src/validate/index.js +3 -11
  56. package/src/validate/layers.js +2 -2
  57. package/src/validate/tables-children.js +5 -5
  58. package/src/config/pragmas/indexes.js +0 -19
  59. package/src/config/pragmas/macros.js +0 -5
  60. package/src/config/pragmas/populate-lambda/_plugins.js +0 -25
  61. package/src/config/pragmas/populate-lambda/_websockets.js +0 -19
  62. package/src/config/project/plugins.js +0 -31
@@ -1,6 +1,7 @@
1
1
  let populate = require('./populate-lambda')
2
2
  let validate = require('./validate')
3
- let is = require('../../lib/is')
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
- if (!arc['tables-streams'] && !arc.tables) return null
13
- if (arc['tables-streams'] && !arc.tables) {
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(tables, inventory, errors)
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['tables-streams'](arc['tables-streams'], inventory, errors)
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))
@@ -1,4 +1,4 @@
1
- let is = require('../../lib/is')
1
+ let { is } = require('../../lib')
2
2
  let validate = require('./validate')
3
3
 
4
4
  module.exports = function configureTables ({ arc, errors }) {
@@ -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.length) {
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 { httpMethods } = require('../../../lib')
2
3
 
3
4
  module.exports = function validateHTTP (http, errors) {
4
- if (http.length) {
5
+ if (http?.length) {
5
6
  unique(http, '@http routes', errors)
6
7
 
7
- let methods = [ 'get', 'post', 'put', 'patch', 'delete', 'options', 'head', 'any' ]
8
- let validMethod = str => methods.includes(str.toLowerCase())
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(/\/:[a-zA-Z0-9]+(\/|$)/g)
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,4 +1,4 @@
1
- let is = require('../../../lib/is')
1
+ let { is } = require('../../../lib')
2
2
 
3
3
  let patterns = {
4
4
  looseName: new RegExp(/^[a-z][a-zA-Z0-9-_]+$/),
@@ -1,4 +1,4 @@
1
- let is = require('../../../lib/is')
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.length) {
13
+ if (scheduled?.length) {
14
14
  unique(scheduled, '@scheduled', errors)
15
15
 
16
16
  scheduled.forEach(schedule => {
@@ -1,5 +1,5 @@
1
1
  let { join, resolve, sep } = require('path')
2
- let is = require('../../../lib/is')
2
+ let { is } = require('../../../lib')
3
3
 
4
4
  module.exports = function validateShared (src, cwd, errors) {
5
5
  let path = src && resolve(join(cwd, src))
@@ -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
- if (tablesStreams.length) {
11
- unique(tablesStreams, '@tables-streams', errors)
10
+ unique(tablesStreams, '@tables-streams', errors)
12
11
 
13
- tablesStreams.forEach(stream => {
14
- let { name } = stream
15
- size(name, 3, 255, '@tables-streams', errors)
16
- regex(name, 'veryLooseName', '@tables-streams', errors)
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.length) {
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/is')
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.src
13
- let src = join(cwd, 'src', 'views')
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
- if (arc.views && arc.views.length) {
20
- let foundSrc = false
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
- 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
- }
30
- }
31
-
32
- // Proceeding from here resets all views config, so make sure it's only if specific views are specified
33
- let some = !(arc.views.length === 1 && foundSrc)
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
  }
@@ -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
- if (!arc.ws) return null
5
+ let wsPlugins = inventory.plugins?._methods?.set?.ws
6
+ if (!arc.ws && !wsPlugins?.length) return null
6
7
 
7
- let ws = [ ...arc.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.ws.find(item => {
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(ws, inventory, errors)
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,13 +1,14 @@
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 } = 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, errors) {
10
- let { arc, raw, filepath, inventory } = params
10
+ module.exports = function getProjectConfig (params) {
11
+ let { arc, errors, raw, filepath, inventory } = params
11
12
  let project = {
12
13
  ...inventory._project,
13
14
  arc,
@@ -20,13 +21,9 @@ module.exports = function getProjectConfig (params, errors) {
20
21
 
21
22
  if (filepath) {
22
23
  project.manifest = filepath
23
- // TODO add manifestCreated once we determine we can get birthtime reliably
24
24
  }
25
25
 
26
- // require project plugin modules
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 })
@@ -36,7 +33,7 @@ module.exports = function getProjectConfig (params, errors) {
36
33
  project[`${scope}PreferencesFile`] = p.preferencesFile
37
34
 
38
35
  // Build out the final preferences
39
- /* istanbul ignore else */ // jic
36
+ /* istanbul ignore else: jic */
40
37
  if (!project.preferences) project.preferences = {}
41
38
  Object.keys(p.preferences).forEach(pragma => {
42
39
  // Ignore the raw data
@@ -47,7 +44,7 @@ module.exports = function getProjectConfig (params, errors) {
47
44
  return
48
45
  }
49
46
  // Traverse and merge individual settings
50
- /* istanbul ignore else */ // jic
47
+ /* istanbul ignore else: jic */
51
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
@@ -56,5 +53,13 @@ module.exports = function getProjectConfig (params, errors) {
56
53
  }
57
54
  }
58
55
 
56
+ if (inventory.plugins?._methods) {
57
+ // TODO: project.env = plugins.env(params, project)
58
+
59
+ let { build, runtimes } = plugins.runtimes(params, project)
60
+ if (build) project.build = join(project.cwd, build)
61
+ if (runtimes) project.customRuntimes = runtimes
62
+ }
63
+
59
64
  return project
60
65
  }
@@ -0,0 +1,5 @@
1
+ let runtimes = require('./runtimes')
2
+
3
+ module.exports = {
4
+ runtimes,
5
+ }
@@ -0,0 +1,56 @@
1
+ let { is } = require('../../../lib')
2
+ let { aliases, runtimeList } = require('lambda-runtimes')
3
+ let allRuntimes = runtimeList.concat([ 'deno', ...Object.keys(aliases) ])
4
+
5
+ module.exports = function setRuntimePlugins (params, project) {
6
+ let { errors, inventory } = params
7
+ let runtimePlugins = inventory.plugins?._methods?.set?.runtimes
8
+ if (runtimePlugins?.length) {
9
+ let runtimes = {
10
+ runtimes: [],
11
+ }
12
+ // inventory._project is not yet built, so provide as much as we can to plugins for now
13
+ let inv = { ...inventory, _project: project }
14
+ let build
15
+ runtimePlugins.forEach(fn => {
16
+ let errType = `plugin: ${fn.plugin}, method: set.runtimes`
17
+ try {
18
+ let result = fn({ inventory: inv })
19
+ result = is.array(result) ? result : [ result ]
20
+ result.forEach(runtime => {
21
+ // TODO add more validation
22
+ let { name } = runtime
23
+ if (!name) {
24
+ let msg = `Runtime plugin must provide a name: ${errType}`
25
+ return errors.push(msg)
26
+ }
27
+ if (allRuntimes.includes(name)) {
28
+ let msg = `Runtime name '${name}' is reserved: ${errType}`
29
+ return errors.push(msg)
30
+ }
31
+ if (runtimes[name]) {
32
+ let msg = `Runtime '${name}' already registered: ${errType}`
33
+ return errors.push(msg)
34
+ }
35
+ if (runtime.build) {
36
+ if (build && build !== runtime.build) {
37
+ errors.push(`Runtime '${name}' cannot set a build directory, as it is already configured to: ${build}`)
38
+ }
39
+ else if (is.bool(runtime.build) ||
40
+ !is.string(runtime.build)) {
41
+ build = 'build'
42
+ }
43
+ else build = runtime.build
44
+ }
45
+ runtimes.runtimes.push(name)
46
+ runtimes[name] = runtime
47
+ })
48
+ }
49
+ catch (err) {
50
+ errors.push(`Runtime plugin '${fn.plugin}' failed: ${err.message}`)
51
+ }
52
+ })
53
+ return { build, runtimes }
54
+ }
55
+ return {}
56
+ }
@@ -1,12 +1,12 @@
1
1
  let read = require('../../read')
2
2
  let validate = require('./validate')
3
- let is = require('../../lib/is')
3
+ let { is } = require('../../lib')
4
4
  let { homedir } = require('os')
5
5
 
6
6
  module.exports = function getPrefs ({ scope, inventory, errors }) {
7
7
  let cwd = scope === 'global'
8
8
  ? homedir()
9
- : inventory._project.src
9
+ : inventory._project.cwd
10
10
 
11
11
  // Populate preferences
12
12
  let prefs = read({ type: 'preferences', cwd, errors })
@@ -18,13 +18,13 @@ module.exports = function getPrefs ({ scope, inventory, errors }) {
18
18
  Object.entries(prefs.arc).forEach(([ key, val ]) => {
19
19
  // TODO add additional preferences checks and normalization
20
20
 
21
- /* istanbul ignore else */ // Parser should get this, but jic
21
+ /* istanbul ignore else: Parser should get this, but jic */
22
22
  if (!preferences[key]) preferences[key] = {}
23
- /* istanbul ignore else */ // Parser should only produce arrays, but jic
23
+ /* istanbul ignore else: Parser should only produce arrays, but jic */
24
24
  if (is.array(val)) {
25
25
  val.forEach(v => {
26
26
  if (is.array(v)) {
27
- /* istanbul ignore if */ // Single vals should be strings, but jic
27
+ /* istanbul ignore if: Single vals should be strings, but jic */
28
28
  if (v.length === 1) preferences[key] = v[0]
29
29
  if (v.length === 2) preferences[key][v[0]] = v[1]
30
30
  if (v.length > 2) preferences[key][v[0]] = [ ...v.slice(1) ]
@@ -39,7 +39,7 @@ module.exports = function getPrefs ({ scope, inventory, errors }) {
39
39
  // Turn env vars with spaces into strings
40
40
  if (key === 'env') {
41
41
  [ 'testing', 'staging', 'production' ].forEach(e => {
42
- /* istanbul ignore else */ // Yet another jic
42
+ /* istanbul ignore else: Yet another jic */
43
43
  if (preferences.env[e]) {
44
44
  Object.entries(preferences.env[e]).forEach(([ key, val ]) => {
45
45
  if (is.array(val)) preferences.env[e][key] = val.join(' ')
@@ -51,7 +51,7 @@ module.exports = function getPrefs ({ scope, inventory, errors }) {
51
51
  if (key === 'sandbox-startup') {
52
52
  preferences[key] = val.map(v => {
53
53
  if (is.string(v)) return v
54
- /* istanbul ignore else */ // Yet another jic
54
+ /* istanbul ignore else: Yet another jic */
55
55
  if (is.array(v)) return v.join(' ')
56
56
  })
57
57
  }
@@ -1,4 +1,4 @@
1
- let is = require('./../../../lib/is')
1
+ let { is } = require('./../../../lib')
2
2
 
3
3
  module.exports = function validatePreferences (preferences, errors) {
4
4
  // Env checks
@@ -1,14 +1,15 @@
1
+ let { join } = require('path')
1
2
  let fnConfig = require('./function-config')
2
- let pragmas = require('../lib/pragmas')
3
+ let { pragmas } = require('../lib')
3
4
 
4
5
  /**
5
6
  * Returns a default stub inventory object
6
7
  * - Every possible officially supported value should be present
7
8
  */
8
9
  module.exports = function inventoryDefaults (params = {}) {
9
- let { cwd, region } = params
10
+ let { cwd = process.cwd(), region } = params
10
11
  // Allow region env var override
11
- region = process.env.AWS_REGION || region || 'us-west-2'
12
+ region = region || process.env.AWS_REGION || 'us-west-2'
12
13
  let defaultFunctionConfig = fnConfig()
13
14
  return {
14
15
  // Meta
@@ -19,9 +20,10 @@ module.exports = function inventoryDefaults (params = {}) {
19
20
  },
20
21
  _project: {
21
22
  type: 'aws',
22
- src: cwd,
23
+ cwd, // Project root dir
24
+ src: join(cwd, 'src'), // Default source tree dir
25
+ build: null, // Optional build artifact dir
23
26
  manifest: null, // Root project manifest filename
24
- // manifestCreated // TODO
25
27
  preferences: null, // Realized preferences obj, resolved from global > local
26
28
  localPreferences: null, // Local preferences obj
27
29
  localPreferencesFile: null, // Local preferences file path
@@ -29,10 +31,10 @@ module.exports = function inventoryDefaults (params = {}) {
29
31
  globalPreferencesFile: null, // Global preferences file path
30
32
  defaultFunctionConfig, // Project-level function config
31
33
  rootHandler: null, // null | configured | arcStaticAssetProxy | proxy
32
- plugins: null, // `require`d plugin modules as a map of plugin name to module
34
+ env: null, // Env vars pulled from SSM + plugins
35
+ customRuntimes: null, // Runtime plugins
33
36
  arc: [], // Raw arc obj
34
37
  raw: '', // Raw arc string
35
- env: null, // Env vars pulled from SSM (if enabled)
36
38
  },
37
39
  // App + vendor config
38
40
  app: '',
@@ -52,9 +54,7 @@ module.exports = function inventoryDefaults (params = {}) {
52
54
  cdn: null,
53
55
  events: null,
54
56
  http: null,
55
- indexes: null,
56
- macros: null,
57
- plugins: null, // These are the Lambdas created by plugins, not the plugin modules, which are in _project.plugins
57
+ plugins: null,
58
58
  proxy: null,
59
59
  queues: null,
60
60
  scheduled: null,
@@ -65,7 +65,9 @@ module.exports = function inventoryDefaults (params = {}) {
65
65
  'tables-streams': null,
66
66
  views: null,
67
67
  ws: null,
68
- // Collection of all Lambda paths
68
+ // Unclassified / non-pragma custom Lambdas created by plugins
69
+ customLambdas: null,
70
+ // Collection of all Lambda source paths
69
71
  lambdaSrcDirs: null,
70
72
  // Lambda lookup by source directory
71
73
  lambdasBySrcDir: null,
package/src/env/index.js CHANGED
@@ -45,7 +45,7 @@ module.exports = function env (params, inventory, callback) {
45
45
  }
46
46
  }))
47
47
  // Check for more data and, if so, recurse
48
- /* istanbul ignore if */ // Sadly no way to easily mock this for testing
48
+ /* istanbul ignore if: Sadly no way to easily mock this for testing */
49
49
  if (data.NextToken) {
50
50
  getSomeEnvVars(name, data.NextToken, callback)
51
51
  }
package/src/get.js CHANGED
@@ -1,4 +1,4 @@
1
- let is = require('./lib/is')
1
+ let { is } = require('./lib')
2
2
 
3
3
  module.exports = function _get (inventory) {
4
4
  function getter (prag, name) {
@@ -38,5 +38,4 @@ module.exports = function _get (inventory) {
38
38
  // These refer to other pragmas, and thus may allow multiple same/same-named entities
39
39
  let multipleResults = [
40
40
  'tables-indexes',
41
- 'indexes',
42
41
  ]
package/src/index.js CHANGED
@@ -5,7 +5,7 @@ let config = require('./config')
5
5
  let getEnv = require('./env')
6
6
  let validate = require('./validate')
7
7
  let get = require('./get')
8
- let errorFmt = require('./lib/error-fmt')
8
+ let { errorFmt } = require('./lib')
9
9
 
10
10
  /**
11
11
  * Architect Inventory
@@ -50,10 +50,7 @@ module.exports = function architectInventory (params = {}, callback) {
50
50
 
51
51
  // Exit early if supplied Arc is fundamentally broken
52
52
  if (errors.length) {
53
- callback(errorFmt({
54
- type: 'manifest',
55
- errors,
56
- }))
53
+ callback(errorFmt({ type: 'manifest', errors }))
57
54
  return promise
58
55
  }
59
56
 
@@ -61,27 +58,32 @@ module.exports = function architectInventory (params = {}, callback) {
61
58
  let inventory = inventoryDefaults(params)
62
59
 
63
60
  // Set up project params for config
64
- let project = { cwd, arc, raw, filepath, inventory }
61
+ let project = { arc, cwd, errors, filepath, inventory, raw }
65
62
 
66
63
  // Populate inventory.arc
67
64
  inventory._arc = config._arc(project)
68
65
 
66
+ // @plugins come first, as they register hooks all around the project
67
+ inventory.plugins = config.pragmas.plugins(project)
68
+
69
69
  // Establish default function config from project + Arc defaults
70
- inventory._project = config._project(project, errors)
70
+ inventory._project = config._project(project)
71
+
72
+ // End here if plugins failed
73
+ if (errors.length) {
74
+ callback(errorFmt({ type: 'plugin', errors }))
75
+ return promise
76
+ }
71
77
 
72
- // Userland: fill out the pragmas
78
+ // Userland: fill out the pragmas, starting with @plugins
73
79
  inventory = {
74
80
  ...inventory,
75
- ...config.pragmas(project, errors)
81
+ ...config.pragmas(project)
76
82
  }
77
83
 
78
- // End here if first-pass pragma validation failed
84
+ // End here if first-pass validation failed
79
85
  if (errors.length) {
80
- callback(errorFmt({
81
- type: 'validation',
82
- errors,
83
- inventory,
84
- }))
86
+ callback(errorFmt({ type: 'validation', errors }))
85
87
  return promise
86
88
  }
87
89