@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.
Files changed (71) hide show
  1. package/changelog.md +54 -1
  2. package/package.json +12 -10
  3. package/readme.md +5 -4
  4. package/src/config/_upsert.js +1 -1
  5. package/src/config/arc.js +3 -3
  6. package/src/config/pragmas/app.js +1 -1
  7. package/src/config/pragmas/events.js +3 -2
  8. package/src/config/pragmas/http.js +5 -4
  9. package/src/config/pragmas/index.js +16 -5
  10. package/src/config/pragmas/meta/custom-lambdas.js +10 -0
  11. package/src/config/pragmas/{src-dirs.js → meta/src-dirs.js} +13 -10
  12. package/src/config/pragmas/plugins.js +109 -4
  13. package/src/config/pragmas/populate-lambda/_custom-lambdas.js +10 -0
  14. package/src/config/pragmas/populate-lambda/_events.js +17 -11
  15. package/src/config/pragmas/populate-lambda/_http.js +18 -10
  16. package/src/config/pragmas/populate-lambda/_scheduled.js +18 -10
  17. package/src/config/pragmas/populate-lambda/_tables-streams.js +20 -23
  18. package/src/config/pragmas/populate-lambda/_ws.js +26 -0
  19. package/src/config/pragmas/populate-lambda/get-handler.js +86 -13
  20. package/src/config/pragmas/populate-lambda/get-lambda.js +23 -0
  21. package/src/config/pragmas/populate-lambda/get-runtime.js +8 -7
  22. package/src/config/pragmas/populate-lambda/index.js +134 -84
  23. package/src/config/pragmas/queues.js +3 -2
  24. package/src/config/pragmas/scheduled.js +3 -2
  25. package/src/config/pragmas/shared.js +41 -44
  26. package/src/config/pragmas/sort/http.js +3 -2
  27. package/src/config/pragmas/static.js +5 -4
  28. package/src/config/pragmas/tables-indexes.js +3 -10
  29. package/src/config/pragmas/tables-streams.js +7 -5
  30. package/src/config/pragmas/tables.js +1 -1
  31. package/src/config/pragmas/validate/_events.js +1 -1
  32. package/src/config/pragmas/validate/_http.js +4 -4
  33. package/src/config/pragmas/validate/_lib.js +3 -10
  34. package/src/config/pragmas/validate/_scheduled.js +2 -2
  35. package/src/config/pragmas/validate/_shared.js +1 -1
  36. package/src/config/pragmas/validate/_tables-streams.js +6 -8
  37. package/src/config/pragmas/validate/_tables.js +2 -2
  38. package/src/config/pragmas/validate/index.js +2 -2
  39. package/src/config/pragmas/views.js +39 -37
  40. package/src/config/pragmas/ws.js +6 -4
  41. package/src/config/project/index.js +36 -20
  42. package/src/config/project/plugins/env.js +71 -0
  43. package/src/config/project/plugins/index.js +7 -0
  44. package/src/config/project/plugins/runtimes.js +67 -0
  45. package/src/config/project/prefs/dotenv.js +81 -0
  46. package/src/config/project/{prefs.js → prefs/index.js} +41 -22
  47. package/src/config/project/validate/index.js +15 -8
  48. package/src/defaults/index.js +20 -13
  49. package/src/env/index.js +76 -61
  50. package/src/get.js +1 -2
  51. package/src/index.js +17 -15
  52. package/src/lib/asap-src.js +3 -3
  53. package/src/lib/error-fmt.js +2 -10
  54. package/src/lib/get-lambda-dirs.js +37 -0
  55. package/src/lib/index.js +42 -0
  56. package/src/lib/is.js +3 -1
  57. package/src/lib/merge-env-vars.js +32 -0
  58. package/src/lib/pragmas.js +19 -3
  59. package/src/read/index.js +1 -3
  60. package/src/read/reader.js +2 -2
  61. package/src/validate/config.js +12 -6
  62. package/src/validate/index.js +17 -18
  63. package/src/validate/layers.js +2 -2
  64. package/src/validate/paths.js +17 -0
  65. package/src/validate/tables-children.js +5 -5
  66. package/src/config/pragmas/indexes.js +0 -19
  67. package/src/config/pragmas/macros.js +0 -5
  68. package/src/config/pragmas/populate-lambda/_plugins.js +0 -25
  69. package/src/config/pragmas/populate-lambda/_websockets.js +0 -19
  70. package/src/config/project/plugins.js +0 -31
  71. package/src/lib/http-methods.js +0 -2
@@ -1,30 +1,37 @@
1
- let read = require('../../read')
2
- let validate = require('./validate')
3
- let is = require('../../lib/is')
1
+ let { join } = require('path')
2
+ let { existsSync, readFileSync } = require('fs')
3
+ let read = require('../../../read')
4
+ let validate = require('../validate')
5
+ let { is, validationPatterns: valid } = require('../../../lib')
6
+ let { parse } = require('./dotenv')
4
7
  let { homedir } = require('os')
5
8
 
6
9
  module.exports = function getPrefs ({ scope, inventory, errors }) {
7
10
  let cwd = scope === 'global'
8
11
  ? homedir()
9
- : inventory._project.src
12
+ : inventory._project.cwd
10
13
 
11
- // Populate preferences
14
+ let envFilepath = join(cwd, '.env')
15
+ let hasEnvFile = scope === 'local' && existsSync(envFilepath)
12
16
  let prefs = read({ type: 'preferences', cwd, errors })
13
- if (prefs.filepath) {
14
- let preferences = {}
17
+
18
+ if (!prefs.filepath && !hasEnvFile) return null
19
+
20
+ let preferences = {}
21
+
22
+ // Populate Architect preferences
23
+ if (prefs.filepath && prefs.arc) {
15
24
  // Ok, this gets a bit hairy
16
25
  // Arc outputs an object of nested arrays
17
26
  // Basically, construct a pared-down intermediate prefs obj for consumers
18
27
  Object.entries(prefs.arc).forEach(([ key, val ]) => {
19
- // TODO add additional preferences checks and normalization
20
-
21
- /* istanbul ignore else */ // Parser should get this, but jic
28
+ /* istanbul ignore else: Parser should get this, but jic */
22
29
  if (!preferences[key]) preferences[key] = {}
23
- /* istanbul ignore else */ // Parser should only produce arrays, but jic
30
+ /* istanbul ignore else: Parser should only produce arrays, but jic */
24
31
  if (is.array(val)) {
25
32
  val.forEach(v => {
26
33
  if (is.array(v)) {
27
- /* istanbul ignore if */ // Single vals should be strings, but jic
34
+ /* istanbul ignore if: Single vals should be strings, but jic */
28
35
  if (v.length === 1) preferences[key] = v[0]
29
36
  if (v.length === 2) preferences[key][v[0]] = v[1]
30
37
  if (v.length > 2) preferences[key][v[0]] = [ ...v.slice(1) ]
@@ -39,35 +46,47 @@ module.exports = function getPrefs ({ scope, inventory, errors }) {
39
46
  // Turn env vars with spaces into strings
40
47
  if (key === 'env') {
41
48
  [ 'testing', 'staging', 'production' ].forEach(e => {
42
- /* istanbul ignore else */ // Yet another jic
49
+ /* istanbul ignore else: Yet another jic */
43
50
  if (preferences.env[e]) {
44
51
  Object.entries(preferences.env[e]).forEach(([ key, val ]) => {
52
+ if (!valid.envVar.test(key)) {
53
+ errors.push(`Env var '${key}' is invalid, must be [a-zA-Z0-9_]`)
54
+ }
45
55
  if (is.array(val)) preferences.env[e][key] = val.join(' ')
46
56
  })
47
57
  }
58
+ else preferences.env[e] = null
48
59
  })
49
60
  }
50
61
  // Turn Sandbox scripts into commands
51
62
  if (key === 'sandbox-startup') {
52
63
  preferences[key] = val.map(v => {
53
64
  if (is.string(v)) return v
54
- /* istanbul ignore else */ // Yet another jic
65
+ /* istanbul ignore else: Yet another jic */
55
66
  if (is.array(v)) return v.join(' ')
56
67
  })
57
68
  }
58
69
  })
59
70
 
60
71
  validate(preferences, errors)
72
+ }
61
73
 
62
- return {
63
- preferences: {
64
- ...preferences,
65
- _arc: prefs.arc,
66
- _raw: prefs.raw,
67
- },
68
- preferencesFile: prefs.filepath
74
+ // Populate .env (testing environment only, disables other env vars)
75
+ if (hasEnvFile) {
76
+ let dotenv = parse(readFileSync(envFilepath))
77
+ preferences.env = {
78
+ testing: Object.keys(dotenv).length ? dotenv : null,
79
+ staging: null,
80
+ production: null,
69
81
  }
70
82
  }
71
83
 
72
- return null
84
+ return {
85
+ preferences: {
86
+ ...preferences,
87
+ _arc: prefs.arc,
88
+ _raw: prefs.raw,
89
+ },
90
+ preferencesFile: prefs.filepath
91
+ }
73
92
  }
@@ -1,13 +1,20 @@
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
5
- let { env } = preferences
6
- if (!env) return
7
- if (env && !is.object(env)) errors.push(`Invalid preferences setting: @env ${env}`)
8
-
5
+ let { env, sandbox } = preferences
9
6
  let envs = [ 'testing', 'staging', 'production' ]
10
- envs.forEach(e => {
11
- if (env[e] && !is.object(env[e])) errors.push(`Invalid preferences setting: @env ${e}`)
12
- })
7
+
8
+ if (env && !is.object(env)) {
9
+ errors.push(`Invalid preferences setting: @env ${env}`)
10
+ }
11
+ else if (env) {
12
+ envs.forEach(e => {
13
+ if (env[e] && !is.object(env[e])) errors.push(`Invalid preferences setting: @env ${e}`)
14
+ })
15
+ }
16
+
17
+ if (sandbox?.env && !envs.includes(sandbox.env)) {
18
+ errors.push(`Invalid preferences setting: @sandbox env ${sandbox.env}`)
19
+ }
13
20
  }
@@ -1,38 +1,45 @@
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(), deployStage = null, 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
15
16
  _arc: {
16
17
  version: 'Unknown', // @architect/architect semver (if installed)
17
18
  defaultFunctionConfig, // Architect's default function config
18
- pragmas, // Registry of all + Lambda pragmas
19
+ pragmas, // Registry of all, Lambda, reserved, retired pragmas
20
+ deployStage, // Deploy stage of the running project (if specified)
19
21
  },
20
22
  _project: {
21
23
  type: 'aws',
22
- src: cwd,
24
+ cwd, // Project root dir
25
+ src: join(cwd, 'src'), // Default source tree dir
26
+ build: null, // Optional build artifact dir
23
27
  manifest: null, // Root project manifest filename
24
- // manifestCreated // TODO
25
- preferences: null, // Realized preferences obj, resolved from global > local
28
+ preferences: null, // Realized preferences obj, resolved from local > global
26
29
  localPreferences: null, // Local preferences obj
27
30
  localPreferencesFile: null, // Local preferences file path
28
31
  globalPreferences: null, // Global preferences obj
29
32
  globalPreferencesFile: null, // Global preferences file path
30
33
  defaultFunctionConfig, // Project-level function config
31
34
  rootHandler: null, // null | configured | arcStaticAssetProxy | proxy
32
- plugins: null, // `require`d plugin modules as a map of plugin name to module
35
+ env: { // Env vars pulled from:
36
+ local: null, // - Local/global prefs or .env
37
+ plugins: null, // - Plugins
38
+ aws: null, // - SSM
39
+ },
40
+ customRuntimes: null, // Runtime plugins
33
41
  arc: [], // Raw arc obj
34
42
  raw: '', // Raw arc string
35
- env: null, // Env vars pulled from SSM (if enabled)
36
43
  },
37
44
  // App + vendor config
38
45
  app: '',
@@ -52,9 +59,7 @@ module.exports = function inventoryDefaults (params = {}) {
52
59
  cdn: null,
53
60
  events: null,
54
61
  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
62
+ plugins: null,
58
63
  proxy: null,
59
64
  queues: null,
60
65
  scheduled: null,
@@ -65,7 +70,9 @@ module.exports = function inventoryDefaults (params = {}) {
65
70
  'tables-streams': null,
66
71
  views: null,
67
72
  ws: null,
68
- // Collection of all Lambda paths
73
+ // Unclassified / non-pragma custom Lambdas created by plugins
74
+ customLambdas: null,
75
+ // Collection of all Lambda source paths
69
76
  lambdaSrcDirs: null,
70
77
  // Lambda lookup by source directory
71
78
  lambdasBySrcDir: null,
package/src/env/index.js CHANGED
@@ -1,76 +1,91 @@
1
+ let { mergeEnvVars } = require('../lib')
2
+
1
3
  /**
2
4
  * Read env vars out of SSM
3
5
  */
4
6
  module.exports = function env (params, inventory, callback) {
5
- if (params.env) {
6
- /* istanbul ignore next */
7
- try {
8
- // eslint-disable-next-line
9
- var aws = require('aws-sdk')
10
- }
11
- catch (err) {
12
- let msg = `'aws-sdk' not found, please install locally or globally (see also readme#aws-sdk-caveat)`
13
- return callback(Error(msg))
14
- }
15
- let name = inventory.app
16
- let { region } = inventory.aws
17
- let ssm = new aws.SSM({ region })
18
- let result = []
19
-
20
- function getSomeEnvVars (name, NextToken, callback) {
21
- // Base query to ssm
22
- let query = {
23
- Path: `/${name}`,
24
- Recursive: true,
25
- MaxResults: 10,
26
- WithDecryption: true
27
- }
7
+ if (!params.env) {
8
+ return callback()
9
+ }
28
10
 
29
- // Check if we're paginating
30
- /* istanbul ignore if */
31
- if (NextToken) query.NextToken = NextToken
11
+ /* istanbul ignore next */
12
+ try {
13
+ // eslint-disable-next-line
14
+ var aws = require('aws-sdk')
15
+ }
16
+ catch (err) {
17
+ let msg = `'aws-sdk' not found, please install locally or globally (see also readme#aws-sdk-caveat)`
18
+ return callback(Error(msg))
19
+ }
20
+ let name = inventory.app
21
+ let { region } = inventory.aws
22
+ let ssm = new aws.SSM({ region })
23
+ let result = []
32
24
 
33
- // Perform the query
34
- ssm.getParametersByPath(query, function _query (err, data) {
35
- if (err) callback(err)
36
- else {
37
- // Tidy up the response
38
- result = result.concat(data.Parameters.map(function (param) {
39
- let bits = param.Name.split('/')
40
- return {
41
- app: name, // jic
42
- env: bits[2],
43
- name: bits[3],
44
- value: param.Value,
45
- }
46
- }))
47
- // Check for more data and, if so, recurse
48
- /* istanbul ignore if */ // Sadly no way to easily mock this for testing
49
- if (data.NextToken) {
50
- getSomeEnvVars(name, data.NextToken, callback)
51
- }
52
- else callback(null, result)
53
- }
54
- })
25
+ function getSomeEnvVars (name, NextToken, callback) {
26
+ // Base query to ssm
27
+ let query = {
28
+ Path: `/${name}`,
29
+ Recursive: true,
30
+ MaxResults: 10,
31
+ WithDecryption: true
55
32
  }
56
33
 
57
- getSomeEnvVars(name, false, function done (err, result) {
34
+ // Check if we're paginating
35
+ /* istanbul ignore if */
36
+ if (NextToken) query.NextToken = NextToken
37
+
38
+ // Perform the query
39
+ ssm.getParametersByPath(query, function _query (err, data) {
58
40
  if (err) callback(err)
59
41
  else {
60
- if (result.length) {
61
- let testing = null
62
- let staging = null
63
- let production = null
64
- result.forEach(r => {
65
- if (r.env === 'testing') testing = Object.assign({}, testing, { [r.name]: r.value })
66
- if (r.env === 'staging') staging = Object.assign({}, staging, { [r.name]: r.value })
67
- if (r.env === 'production') production = Object.assign({}, production, { [r.name]: r.value })
68
- })
69
- inventory._project.env = { testing, staging, production }
42
+ // Tidy up the response
43
+ result = result.concat(data.Parameters.map(function (param) {
44
+ let bits = param.Name.split('/')
45
+ return {
46
+ app: name, // jic
47
+ env: bits[2],
48
+ name: bits[3],
49
+ value: param.Value,
50
+ }
51
+ }))
52
+ // Check for more data and, if so, recurse
53
+ /* istanbul ignore if: Sadly no way to easily mock this for testing */
54
+ if (data.NextToken) {
55
+ getSomeEnvVars(name, data.NextToken, callback)
70
56
  }
71
- callback()
57
+ else callback(null, result)
72
58
  }
73
59
  })
74
60
  }
75
- else callback()
61
+
62
+ getSomeEnvVars(name, false, function done (err, result) {
63
+ if (err) callback(err)
64
+ else {
65
+ let testing = null
66
+ let staging = null
67
+ let production = null
68
+ if (result.length) {
69
+ // TODO refactor into a reducer?
70
+ result.forEach(({ env, name: k, value: v }) => {
71
+ if (env === 'testing') testing = Object.assign({}, testing, { [k]: v })
72
+ if (env === 'staging') staging = Object.assign({}, staging, { [k]: v })
73
+ if (env === 'production') production = Object.assign({}, production, { [k]: v })
74
+ })
75
+ }
76
+
77
+ let errors = []
78
+ inventory._project.env.aws = mergeEnvVars({
79
+ env: 'Application',
80
+ source: inventory._project.env.plugins,
81
+ target: { testing, staging, production },
82
+ errors,
83
+ })
84
+ if (errors.length) {
85
+ callback(Error(errors[0]))
86
+ return
87
+ }
88
+ callback()
89
+ }
90
+ })
76
91
  }
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
 
@@ -17,7 +17,7 @@ module.exports = function asapSrc () {
17
17
  try {
18
18
  return require.resolve('@architect/asap')
19
19
  }
20
- catch (err) { /* Swallow */ }
21
-
22
- throw Error('Cannot find ASAP module!')
20
+ catch (err) {
21
+ throw Error('Cannot find ASAP module!')
22
+ }
23
23
  }
@@ -1,26 +1,18 @@
1
- let { basename } = require('path')
2
-
3
1
  /**
4
2
  * Common error formatter
5
3
  *
6
4
  * @param params {object}
7
5
  * @param params.type {string} - Inventory error type: `manifest`, `validation`, or `configuration`
8
6
  * @param params.errors {array} - Array of one or more errors to output
9
- * @param params.meta {string} - Appends optional info to primary error message
10
7
  * @param params.inventory {object} - Inventory object
11
8
  *
12
9
  * @returns Formatted Error + appended ARC_ERRORS property
13
10
  */
14
11
  module.exports = function format (params) {
15
- let { type, errors, meta, inventory } = params
16
- if (!meta && type === 'validation') {
17
- meta = inventory._project.manifest
18
- ? ` in ${basename(inventory._project.manifest)}`
19
- : ''
20
- }
12
+ let { type, errors } = params
21
13
  let output = errors.map(err => `- ${err}`).join('\n')
22
14
  let errType = type[0].toUpperCase() + type.substr(1)
23
- let err = Error(`${errType} error${errors.length > 1 ? 's' : ''}${meta ? meta : ''}:\n${output}`)
15
+ let err = Error(`${errType} error${errors.length > 1 ? 's' : ''}:\n${output}`)
24
16
  err.ARC_ERRORS = { type, errors }
25
17
  return err
26
18
  }
@@ -0,0 +1,37 @@
1
+ let { isAbsolute, join } = require('path')
2
+
3
+ /**
4
+ * Get the src (and build) dirs for a Lambda
5
+ * - Arc Lambdas: pass a name + pragma || relative file path
6
+ * - Plugin Lambdas: pass a relative file path || absolute file path
7
+ */
8
+ function getLambdaDirs (params, options) {
9
+ let { cwd, item, projSrc, projBuild, type: pragma } = params
10
+ let { name, plugin, customSrc } = options
11
+ let lambdaDirs = {}
12
+
13
+ if (plugin) {
14
+ let src = normalizeSrc(cwd, item.src)
15
+ lambdaDirs.src = src
16
+ if (projBuild) {
17
+ lambdaDirs.build = src.replace(src, projBuild)
18
+ }
19
+ }
20
+ else {
21
+ let root = customSrc ? cwd : projSrc
22
+ let path = customSrc || join(pragma, name)
23
+ lambdaDirs.src = join(root, path)
24
+ if (projBuild) {
25
+ lambdaDirs.build = join(projBuild, path)
26
+ }
27
+ }
28
+ return lambdaDirs
29
+ }
30
+
31
+ function normalizeSrc (cwd, dir) {
32
+ if (isAbsolute(dir)) return dir
33
+ return join(cwd, dir)
34
+ }
35
+
36
+ getLambdaDirs.normalizeSrc = normalizeSrc
37
+ module.exports = getLambdaDirs
@@ -0,0 +1,42 @@
1
+ let asapSrc = require('./asap-src')
2
+ let errorFmt = require('./error-fmt')
3
+ let getLambdaDirs = require('./get-lambda-dirs')
4
+ let is = require('./is')
5
+ let mergeEnvVars = require('./merge-env-vars')
6
+ let pragmas = require('./pragmas')
7
+
8
+ /**
9
+ * Why take up a whole fs block when smol libs can just live here?
10
+ */
11
+
12
+ // For setting `lambda.build`, compiled + transpiled are effectively the same
13
+ let compiledRuntimes = [ 'compiled', 'transpiled' ]
14
+
15
+ // `any` must come last for Sandbox route sorting purposes
16
+ let httpMethods = [ 'get', 'post', 'put', 'patch', 'delete', 'options', 'head', 'any' ]
17
+
18
+ let validationPatterns = {
19
+ strictName: /^[a-z][a-z0-9-]+$/,
20
+ looseName: /^[a-z][a-zA-Z0-9-_]+$/,
21
+ looserName: /^[a-z][a-zA-Z0-9-._]+$/,
22
+ veryLooseName: /^[a-zA-Z0-9/\-._]*$/,
23
+ // IEEE 1003.1-2001 does not allow lowercase, so consider this a compromise for the Windows folks in the house
24
+ envVar: /^[a-zA-Z0-9_]+$/,
25
+ }
26
+
27
+ // Error tidier: remove the error name, just print the message + stack data
28
+ let tidyError = err => err.message + `\n` + err.stack.split('\n').slice(1).join('\n')
29
+
30
+ module.exports = {
31
+ asapSrc,
32
+ compiledRuntimes,
33
+ errorFmt,
34
+ getLambdaDirs,
35
+ httpMethods,
36
+ is,
37
+ mergeEnvVars,
38
+ normalizeSrc: getLambdaDirs.normalizeSrc,
39
+ pragmas,
40
+ tidyError,
41
+ validationPatterns,
42
+ }
package/src/lib/is.js CHANGED
@@ -4,10 +4,12 @@ module.exports = {
4
4
  // Types
5
5
  array: item => Array.isArray(item),
6
6
  bool: item => typeof item === 'boolean',
7
+ defined: item => typeof item !== 'undefined',
8
+ fn: item => typeof item === 'function',
9
+ nullish: item => typeof item === 'undefined' || item === null,
7
10
  number: item => Number.isInteger(item),
8
11
  object: item => typeof item === 'object' && !Array.isArray(item),
9
12
  string: item => typeof item === 'string',
10
- defined: item => typeof item !== 'undefined' && item !== null,
11
13
  // Filesystem
12
14
  exists: path => existsSync(path),
13
15
  folder: path => existsSync(path) && lstatSync(path).isDirectory(),
@@ -0,0 +1,32 @@
1
+ let envs = [ 'testing', 'staging', 'production' ]
2
+
3
+ module.exports = function mergeEnvVars (params) {
4
+ let { name, source, target, errors } = params
5
+ if (source === null) return target
6
+ if (target === null) return source
7
+ let probs = []
8
+
9
+ // Deep copy to reset any potential refs
10
+ let merged = JSON.parse(JSON.stringify(target))
11
+ envs.forEach(env => {
12
+ if (!source[env]) return
13
+ Object.keys(source[env]).forEach(k => {
14
+ if (merged[env]?.[k]) {
15
+ probs.push(`'${env}' variable '${k}'`)
16
+ }
17
+ else {
18
+ if (!merged[env]) merged[env] = {}
19
+ merged[env][k] = source[env][k]
20
+ }
21
+ })
22
+ })
23
+
24
+ if (probs.length) {
25
+ let s = probs.length > 1 ? 's' : ''
26
+ let msg = `${name} env var${s} conflicts with plugin:\n` +
27
+ `- ${probs.join('\n- ')}`
28
+ errors.push(msg)
29
+ }
30
+
31
+ return merged
32
+ }
@@ -6,8 +6,6 @@ module.exports = {
6
6
  'cdn',
7
7
  'events',
8
8
  'http',
9
- 'indexes', // -> transitioning to @tables-indexes
10
- 'macros',
11
9
  'plugins',
12
10
  'proxy',
13
11
  'queues',
@@ -24,10 +22,28 @@ module.exports = {
24
22
  lambdas: [
25
23
  'events',
26
24
  'http',
27
- 'plugins',
28
25
  'queues',
29
26
  'scheduled',
30
27
  'tables-streams',
31
28
  'ws',
32
29
  ],
30
+ // Reserved pragma names that map to internal Inventory properties
31
+ reserved: [
32
+ 'customLambdas',
33
+ ],
34
+ // Retired pragmas no longer in active use
35
+ retired: [
36
+ 'indexes',
37
+ 'macros',
38
+ 'slack',
39
+ 'streams', // Never fully launched
40
+ // Static types
41
+ 'css',
42
+ 'html',
43
+ 'js',
44
+ 'json',
45
+ 'jsonapi',
46
+ 'text',
47
+ 'xml',
48
+ ]
33
49
  }